I am reading Rails 3 Way book and got confused at the point:
:after_add => callback Called after a record is added to the collection via the << method. Is not triggered by the collection’s create method
As I understand book.chapters.create(title: 'First Chapter') won't invoke before_add callback but actually it is calling.
class Book < ActiveRecord::Base
attr_accessible :title
has_many :chapters, :before_add => :add_chapter
private
def add_chapter(chapter)
logger.error('chapter added to book')
end
end
class Chapter < ActiveRecord::Base
belongs_to :book
attr_accessible :title
end
In Console(minified)
> b = Book.first
Book Load (0.1ms) SELECT "books".* FROM "books" LIMIT 1
> b.chapters.create(title: 'Last Chapter')
begin transaction
chapter added to book
INSERT INTO "chapters" ....
commit transaction
Here you can see that after_add
callback is invoke for create
.
Am I misunderstood something?
Edit
b.chapters.new(title: 'New Chapter')
b.chapters.build(title: 'New Chapter')
also invokes callback
The before_add
and after_add
callbacks are triggered when an item is added to a collection. It has nothing to do with whether or not a record is saved to the database. (A slight exception is to be made here for has_and_belongs_to_many
and has_many :through
relations, where adding it to the collection is immediately reflected to the database by ActiveRecord internally).
As soon as you add a new record to the collection, the callbacks will fire. The before_add will be called before the element is added to the collection, and the after_add after.
This example below might give you a better understanding.
# id: integer
class Author < ActiveRecord::Base
has_many :books, before_add: :bef, after_add: aft
def bef
puts "Before adding, author ##{id} has #{books.size} books"
end
def aft
puts "After adding, author ##{id} has #{books.size} books"
end
end
# id integer
# author_id: integer
class Book < ActiveRecord::Base
belongs_to :author
after_save: :saved
def saved
puts "The book is now saved!"
end
end
> book = Book.new
> author = Author.first
> author.books << book
'Before adding, author #1 has 3 books'
'After adding, author #1 has 4 books'
> author.save
'The book is now saved'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With