7

私はRails 3 Wayの本を読んでいて、その時点で混乱しました:

:after_add => コー​​ルバック << メソッドによってレコードがコレクションに追加された後に呼び出されます。コレクションの create メソッドによってトリガーされない

私が理解しているように、 book.chapters.create(title: 'First Chapter') は before_add コールバックを呼び出しませんが、実際には呼び出しています。

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

コンソール内(縮小版)

 > 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

after_addここで、コールバックが に対して呼び出されていることがわかりますcreate

私は何か誤解していますか?

編集

b.chapters.new(title: 'New Chapter')
b.chapters.build(title: 'New Chapter')

コールバックも呼び出す

4

1 に答える 1

11

コレクションに項目が追加されると、before_addおよびafter_addコールバックがトリガーされます。レコードがデータベースに保存されるかどうかとは関係ありません。(コレクションへの追加が ActiveRecord によって内部的にデータベースに即座に反映されるリレーションには、ここhas_and_belongs_to_manyでわずかな例外があります)。has_many :through

コレクションに新しいレコードを追加するとすぐに、コールバックが発生します。要素がコレクションに追加される前に before_add が呼び出され、その後に after_add が呼び出されます。

以下の例は、理解を深めるのに役立つかもしれません。

# 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'
于 2017-01-03T14:35:23.703 に答える