ActiveRecord何时会保存关联?

时间:2013-09-09 16:44:19

标签: ruby-on-rails activerecord associations has-many

1)我知道根据http://railsapi.com/doc/rails-v2.3.8/classes/ActiveRecord/AutosaveAssociation.html

,它会在autosave: true时保存关联

2)我知道它会保存像

这样构建的关联
book = Book.new(name: 'foo')
book.authors.build(name: 'bar') #has_many
book.save

或喜欢

book = Book.new(name: 'foo')
book.build_author(name: 'bar') #has_one
book.save

3)我认为在分配或添加关联时也会保存关联

book = Book.new(name: 'foo')
book.author = Author.new(name: 'bar')
book.save

book = Book.new(name: 'foo')
book.authors << Author.new(name: 'bar')
book.save

但是,我有一个复杂的错误,涉及到我想要的时候不能自动保存的东西。所以,我想通过检查book进行调试,以验证我认为实际保存的内容。

TL; DR; 保存关联时检查什么内部状态?我假设模型有一个像associations_to_save这样的内部实例变量,在创建它们时会添加关联。然后,当模型被保存时,它会遍历这些关联并保存它们。

3 个答案:

答案 0 :(得分:27)

不幸的是没有像association_to_save这样的东西。然而,有一些规则说明什么时候被保存。你可以在这里找到:http://guides.rubyonrails.org/association_basics.html。积分:4.1.5(belongs_to),4.2.5(has_one),4.3.4(has_many)和4.4.4(habtm)。

更新:

如果是has_many关联,如果child.new_record,子节点会在保存父节点时保存?返回true(子节点尚未保存到db),或者需要更新foreign_key列。这就是原因:

  1. 将对象添加到已保存父级的关联中,请保存新子级。
  2. 在未保存的父级上添加对象关联不会保存(没有外键值)
  3. 如果正在保存未保存的父级并且在关联缓存中有一些子对象,则会保存这些对象以更新foreign_key。

答案 1 :(得分:1)

不确定这是否对其他人有帮助,但是最近我在Rails 5.2中遇到了类似的问题。

当尝试保存对象2层时,如果顶层和顶层对象已经保存,则我的测试失败。就是

book_cover.persisted? == true
book_cover.book.persisted? == true

page = book_cover.book.pages.new

page.persisted? == false

# After saving the top level object
book_cover.save
page.persisted? == false

# After saving the immediate parent of page
book_cover.book.save
page.persisted? == true

由于父“书的封面”不是新对象“页面”的直接父,保存“书的封面”实际上并没有最终保存“页面”对象。

根据情况,我只是显式地调用了“ book”对象上的save以保存所有子对象。

答案 2 :(得分:0)

我想我的回答对提问者来说来得太晚了?(并且我不会在保存活动记录关联时直接回答)但是有一些方法可以帮助深入了解对象的关联及其状态 - 例如 {{ 1}} 甚至(私有)方法,如 changed_for_autosave?autosave_association.rb (API / documentation) 的一部分)或(也是私有的)nested_records_changed_for_autosave?(在 associations.rb 内) .

小心使用 association_instance_get,因为它经历加载在内存中的嵌套自动保存关联(不加载任何新关联!)

这些也可能与一些反射类方法结合使用,例如 nested_records_changed_for_autosave?reflect_on_aggregationreflect_on_all_aggregationsreflect_on_all_associationsreflect_on_all_autosave_associations 和 {{1 }} (API for further documentation),用于自动化关联检查过程,如下所示:

reflect_on_association

使用reflections(似乎没有很好地记录(简要提到herehere))返回self.class.reflect_on_all_autosave_associations #=> reflections association_instance_get(reflection.name) #=> association association.target #=> actual associated object(s) object.changes #=> e. g. { "name" => ["bill", "bob"] } 和{{的关联对象 1}} 或 target#belongs_to 的关联对象的集合。

(我没有提供可用的代码,因为需要更多的想法来检查空数组、nil 值等等。)

在这些关联的对象方法上,如 #has_one#has_many#has_and_belongs_to_many 存在。