Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When will ActiveRecord save associations?

  1. I know that it will save associations when autosave: true as per https://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html

  2. I know that it will save associations that are constructed like

    book = Book.new(name: 'foo') book.authors.build(name: 'bar') #has_many book.save

or like

book = Book.new(name: 'foo') book.build_author(name: 'bar') #has_one book.save 
  1. I think associations are also saved when they are assigned or added

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

or

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

But, I have a complicated bug that involves something not auto-saving when I would expect it to. So, I want to debug by inspecting book to verify what I think is going to be saved will actually be saved.

TL; DR; What internal state is checked when saving associations? I'm assuming that a model has an internal instance variable like associations_to_save that associations get added to when they are created. Then, when the model is saved, it loops through those associations and saves them too.

like image 800
hrdwdmrbl Avatar asked Sep 09 '13 16:09

hrdwdmrbl


People also ask

Is ActiveRecord a framework?

1.3 Active Record as an ORM Framework Represent inheritance hierarchies through related models. Validate models before they get persisted to the database. Perform database operations in an object-oriented fashion.

What is ActiveRecord in Ruby on Rails?

What is ActiveRecord? ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.


2 Answers

Unfortunately there are no such thing like associations_to_save. However there are some rules saying what is being saved when. You can find those here: http://guides.rubyonrails.org/association_basics.html. Points: 4.1.5 (belongs_to), 4.2.5 (has_one), 4.3.4 (has_many) and 4.4.4 (habtm).

UPDATE:

In case of has_many association, the child is saved on saving the parent if child.new_record? returns true (child was not yet saved to db), or the foreign_key column needs to be updated. This is why:

  1. Adding object to association on saved parent do save new child.
  2. Adding object to association on unsaved parent doesn't save (no foreign key value)
  3. If unsaved parent is being saved and has some child objects in association cache, those objects are saved to update foreign_key.
like image 120
BroiSatse Avatar answered Sep 20 '22 21:09

BroiSatse


Not sure if this will help anyone else, but I recently ran into a similar issue recently in Rails 5.2.

When trying to save an object 2 layers deep my tests failed if the top level and the first level objects had already been saved. Ie.

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 

Since the parent "book cover" wasn't the direct parent of the new object "page" saving "book cover" didn't actually end up saving the "page" object.

Depending on the situation I just explicitly called save on the "book" object to save all the child objects.

like image 43
Matt H Avatar answered Sep 18 '22 21:09

Matt H