保存多对多的Rails只能保存一个关联

时间:2014-10-23 16:02:24

标签: ruby-on-rails

我的模特中有以下关系:

class ClientProfile < ActiveRecord::Base
  has_many :client_folders
  has_many :folders, through: :client_folders

  accepts_nested_attributes_for :folders
end

class Folder < ActiveRecord::Base
  has_many :client_folders
  has_many :client_profiles, through: :client_folders
end

class ClientFolder < ActiveRecord::Base
  belongs_to :client_profile
  belongs_to :folder
end

我在控制器中建立了关系:

@client_profile = ClientProfile.new
2.times do |i|
  @folder = Folder.new(folder_name: "folder #{i}")
  @client_profile.folders << @folder
end

我在视图中创建了以下fields_for关联:

<%= form_for @client_profile do |f| %>
  ...
  <%= f.fields_for :folders do |folder_builder| %>
      <%= folder_builder.text_field :some_column %>
      ...
  <% end %>
<% end %>

创建动作:

  def create
    @client_profile = ClientProfile.new client_profile_params
    if @client_profile.save
      ...
    else
      ...
    end
  end

当我保存关联时,它会创建client_profile以及两个文件夹,并且连接模型ClientFolder会正确创建两次。但是,在创建的两个ClientFolders中,它只填充了folder_id。client_profile_id保留为null。

我尝试过的一个解决方案是将以下内容添加到client_profile中,以确保它正确保存连接模型关系:

  def folders_attributes=(params)
    if params["0"][:id].nil?
      params.values.each do |v|
        f = Folder.new v
        self.folders << f
      end
    end
  end

但是这会在保存时引发以下异常:

NoMethodError - undefined method `each' for #<ClientFolder:0x007fd364743d78>:
  activemodel (4.1.5) lib/active_model/attribute_methods.rb:435:in `method_missing'
  activerecord (4.1.5) lib/active_record/attribute_methods.rb:208:in `method_missing'
  activerecord (4.1.5) lib/active_record/autosave_association.rb:349:in `save_collection_association'
  activerecord (4.1.5) lib/active_record/autosave_association.rb:186:in `block in add_autosave_association_callbacks'
  activerecord (4.1.5) lib/active_record/autosave_association.rb:157:in `instance_eval'
  activerecord (4.1.5) lib/active_record/autosave_association.rb:157:in `block in define_non_cyclic_method'
  activesupport (4.1.5) lib/active_support/callbacks.rb:424:in `block in make_lambda'
  activesupport (4.1.5) lib/active_support/callbacks.rb:221:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:221:in `block in halting_and_conditional'
  activesupport (4.1.5) lib/active_support/callbacks.rb:215:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:215:in `block in halting_and_conditional'
  activesupport (4.1.5) lib/active_support/callbacks.rb:215:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:215:in `block in halting_and_conditional'
  activesupport (4.1.5) lib/active_support/callbacks.rb:215:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:215:in `block in halting_and_conditional'
  activesupport (4.1.5) lib/active_support/callbacks.rb:86:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:86:in `run_callbacks'
  activerecord (4.1.5) lib/active_record/callbacks.rb:306:in `_create_record'
  activerecord (4.1.5) lib/active_record/timestamp.rb:57:in `_create_record'
  activerecord (4.1.5) lib/active_record/persistence.rb:482:in `create_or_update'
  activerecord (4.1.5) lib/active_record/callbacks.rb:302:in `block in create_or_update'
  activesupport (4.1.5) lib/active_support/callbacks.rb:113:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:113:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:166:in `block in halting'
  activesupport (4.1.5) lib/active_support/callbacks.rb:166:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:166:in `block in halting'
  activesupport (4.1.5) lib/active_support/callbacks.rb:166:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:166:in `block in halting'
  activesupport (4.1.5) lib/active_support/callbacks.rb:86:in `call'
  activesupport (4.1.5) lib/active_support/callbacks.rb:86:in `run_callbacks'
  activerecord (4.1.5) lib/active_record/callbacks.rb:302:in `create_or_update'
  activerecord (4.1.5) lib/active_record/persistence.rb:103:in `save'
  activerecord (4.1.5) lib/active_record/validations.rb:51:in `save'
  activerecord (4.1.5) lib/active_record/attribute_methods/dirty.rb:21:in `save'
  activerecord (4.1.5) lib/active_record/transactions.rb:268:in `block (2 levels) in save'
  activerecord (4.1.5) lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
  activerecord (4.1.5) lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `block in transaction'
  activerecord (4.1.5) lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `within_new_transaction'
  activerecord (4.1.5) lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `transaction'
  activerecord (4.1.5) lib/active_record/transactions.rb:208:in `transaction'
  activerecord (4.1.5) lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
  activerecord (4.1.5) lib/active_record/transactions.rb:268:in `block in save'

其他人建议添加联接模型关联:

accepts_nested_attributes_for :client_folders

但这样做没有意义,因为我根本没有在表单中使用client_folders。当我在表单中使用fields_for:folders时,它应该足够智能,以便在create中正确保存连接模型。

如何解决此问题?

1 个答案:

答案 0 :(得分:0)

我发现了这个问题。

我在模型中定义了两次关系:

  has_many :client_folders
  has_one  :client_folders, :class_name => 'ClientFolder', :foreign_key => :folder_id

当我删除has_one时,一切都有效。