【问题标题】:Creating nested models - Rails 3.1创建嵌套模型 - Rails 3.1
【发布时间】:2011-10-10 15:41:28
【问题描述】:

我正在尝试一次创建 3 个嵌套模型,但在验证时遇到了问题。

这些是我的模型:

class UserEntity < ActiveRecord::Base
  has_many    :users,           :dependent => :restrict, :autosave => true
end

class User < ActiveRecord::Base
  has_many    :user_login_services, :dependent => :destroy, :autosave => true
  belongs_to  :user_entity
end

class UserLoginService < ActiveRecord::Base
  belongs_to :user
  #validates :user_id, :presence => true
end

(UserEntity可以是一家公司,有很多用户。UserLoginService用于Facebook、openID等Omniauth服务)

用户是用

创建的
def new_user_login(tokens)
  user_entity = UserEntity.new
  user = user_entity.users.build(:email => tokens[:email], :password => Devise.friendly_token[0,20], :first_name => tokens[:first_name], :last_name => tokens[:last_name], :has_local_password => false)
  user.skip_confirmation!
  user.user_login_services.build(:provider => tokens[:provider], :uid => tokens[:uid], :uname => tokens[:name], :uemail => tokens[:email])     
  user_entity.save! 
  user.confirm!

此代码似乎运行良好,并在所有 3 个表中创建了适当的条目。当我在 UserLoginService 中取消注释 'validates :user_id, :presence => true' 时,就会出现问题,这让我很满意

ActiveRecord::RecordInvalid (Validation failed: Users user login services user can't be blank):
  app/controllers/users/omniauth_callbacks_controller.rb:86:in `new_user_login'

请注意,代码在没有验证的情况下似乎可以正常工作,并且 user_login_services 表中的 user_id 设置为正确的值。

为什么会出现此错误,我该如何解决?

【问题讨论】:

    标签: model ruby-on-rails-3.1


    【解决方案1】:

    简而言之:

    在你的模型中

    class UserEntity < ActiveRecord::Base
      has_many :users
      accepts_nested_attributes_for :users
    end
    
    class User < ActiveRecord::Base
      belongs_to :user_entity
      has_many   :user_login_services, :dependent => :destroy
      accepts_nested_attributes_for :user_login_services
    end
    
    class UserLoginService < ActiveRecord::Base
      belongs_to :user
      validates :user_id, :presence => true
    end
    

    在你的控制器中

    def create
      @user_entity = UserEntity.new(params[:user_entity])
      @user_entity.save
      # To Do: handle redirections on error and success
    end
    

    在你的表单中

    <%= form_for(@user_entity) do |f| %>
      <%= f.fields_for :users do |u| %>
        <%= u.fields_for :user_login_services do |ul| %>
          <%= ul.select :user_id, @user_entity.users.collect{|u| [u.name, u.id]} %>
        <% end %>
      <% end %>
    <% end %>
    

    另外我建议您查看:http://railscasts.com/episodes/196-nested-model-form-part-1

    【讨论】:

      【解决方案2】:

      您需要定义 accepts_nested_attributes_forinverse_of 关系。

      class UserEntity < ActiveRecord::Base
        has_many   :users, :dependent => :restrict, :autosave => true, :inverse_of => :users_entity
        accepts_nested_attributes_for :users
      end
      
      class User < ActiveRecord::Base
        has_many    :user_login_services, :dependent => :destroy, :autosave => true, :inverse_of => :user
        belongs_to  :user_entity, :inverse_of => :users
        accepts_nested_attributes_for :user_login_services
      end
      
      class UserLoginService < ActiveRecord::Base
        belongs_to :user, :inverse_of => :users_login_services
        validates :user, :presence => true 
      end
      

      我还将validates :user_id 切换为validates :user,假设您想验证关联的user 的存在,而不仅仅是UserLoginService 有一个user_id

      【讨论】:

      • 非常感谢,指定 inverse_of 为我做了这件事!否则在保存 Rails 时会先尝试保存嵌套模型(使用嵌套模型 belongs_to 顶层模型),这会失败,因为顶层模型尚未创建。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多