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它与记录是否保存到数据库无关。(这里对has_and_belongs_to_manyhas_many :through关系有一个小例外,将其添加到集合中会立即通过 ActiveRecord 在内部反映到数据库中)。

一旦您将新记录添加到集合中,回调就会触发。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 回答