这是一个错误,还是我错过了什么?
让我举个简单的例子.
这是我的模特:
class User < ActiveRecord::Base has_many :posts attr_accessible :name,:posts_attributes accepts_nested_attributes_for :posts end class Post < ActiveRecord::Base belongs_to :group belongs_to :user attr_accessible :content,:title,:group_attributes accepts_nested_attributes_for :group end class Group < ActiveRecord::Base has_many :posts attr_accessible :name end
我在每个表中都创建了一条记录,并相应地将它们相关联,因此每个表中都有一条id = 1的记录 – 这是已知的.现在,如果我有一个现有用户,一个新帖子和一个现有组,并尝试使用accepts_nested_attributes_for更新该记录,它不喜欢它:
1.9.3-p125 :044 > params { :id => 1,:name => "Billy",:posts_attributes => [ [0] { :title => "Title",:content => "Some magnificent content for you!",:group_attributes => { :id => 1,:name => "Group 1" } } ] } 1.9.3-p125 :045 > u #<User:0x00000002f7f380> { :id => 1,:created_at => Fri,03 Aug 2012 20:21:37 UTC +00:00,:updated_at => Fri,03 Aug 2012 20:21:37 UTC +00:00 } 1.9.3-p125 :046 > u.update_attributes params (0.1ms) begin transaction (0.1ms) rollback transaction ActiveRecord::RecordNotFound: Couldn't find Group with ID=1 for Post with ID= from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/nested_attributes.rb:462:in `raise_nested_attributes_record_not_found' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/nested_attributes.rb:332:in `assign_nested_attributes_for_one_to_one_association' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/nested_attributes.rb:288:in `group_attributes=' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/attribute_assignment.rb:94:in `block in assign_attributes' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/attribute_assignment.rb:93:in `each' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/attribute_assignment.rb:93:in `assign_attributes' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/base.rb:498:in `initialize' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/reflection.rb:183:in `new' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/reflection.rb:183:in `build_association' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/associations/association.rb:233:in `build_record' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/associations/collection_association.rb:112:in `build' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/nested_attributes.rb:405:in `block in assign_nested_attributes_for_collection_association' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/nested_attributes.rb:400:in `each' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/nested_attributes.rb:400:in `assign_nested_attributes_for_collection_association' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/nested_attributes.rb:288:in `posts_attributes=' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/attribute_assignment.rb:85:in `block in assign_attributes' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/attribute_assignment.rb:78:in `each' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/attribute_assignment.rb:78:in `assign_attributes' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/persistence.rb:216:in `block in update_attributes' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/transactions.rb:208:in `transaction' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/transactions.rb:293:in `with_transaction_returning_status' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.7/lib/active_record/persistence.rb:215:in `update_attributes' from (irb):15 from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.7/lib/rails/commands/console.rb:47:in `start' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.7/lib/rails/commands/console.rb:8:in `start' from /home/trevor/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.7/lib/rails/commands.rb:41:in `<top (required)>' from script/rails:6:in `require' from script/rails:6:in `<main>'1.9.3-p125 :047 >
它认为它无法找到与新帖子相关的组(具有已知ID).
当我从group_attributes中删除ID时,它会起作用(但它会创建一个新的组记录).
当我给posts_attributes一个ID,并从group_attributes中删除id(并再次创建一个新组)时,它可以工作.
它们都有ID时也可以使用.
这种关系正在起作用:
1.9.3-p125 :059 > p = Post.new( { group_attributes: { name: 'Testing' } } ) #<Post:0x00000004212380> { :id => nil,:title => nil,:content => nil,:group_id => nil,:user_id => nil,:created_at => nil,:updated_at => nil } 1.9.3-p125 :060 > p.group [ [0] #<Group:0x00000004211868> { :id => nil,:name => "Testing",:updated_at => nil } ]
如果所有记录都是新记录,则在用户创建期间使用posts_attributes和group_attributes时,它也完全有效.
它不应该仍然在第一个例子中工作吗? ActiveRecord应该足够聪明才能弄明白……!
解决方法
但是,根据post_attributes中的数据创建的post对象尚未与组关联 – post.group_id为nil.因此,当ActiveRecord执行首次搜索以获取关联组时,它将显示为空.相应地,它没有在(空)结果中找到ID = 1的组.从技术上讲,记录就在那里,但在与帖子的关联方面并不存在.
你可以通过包括group_id =>证明这一点. 1在post_attributes中.我相信,如果你这样做,ActiveRecord将通过关联找到该组,然后在结果中成功地从ID = 1中选择该组,然后使用group_attributes中的附加数据更新该组.
另请注意,如果您允许用户在创建新帖子的同时更新组名称,那么在帖子中包含组内嵌组属性的唯一原因就是您要这样做.如果您要做的只是将新帖子链接到现有组,那么您只需要在post_attributes中包含group_id,就可以摆脱group_attributes.