重构 关于 ruby-china 代码中的 callback

niedhui · 2011年11月27日 · 最后由 fredwu 回复于 2012年11月22日 · 3902 次阅读

fork 了 ruby-china 的代码,学习下。 有个编程习惯的问题,代码中的很多 callback 都是这样写的:

after_create :update_parent_topic
def update_parent_topic
end

after_create :send_mail_notify
def send_mail_notify
end

before_save :extract_mentioned_users
def extract_mentioned_users
end

一般如果 callback 的代码只用一次,我就会直接写成

after_create do

end

如果 callback 的代码会用到多次,就写成

after_update :update_topic_updated_at
after_destroy :update_topic_updated_a
before_save :extract_mentioned_userst
# 省掉其他的callback声明
private
def update_topic_updated_at
end

各位呢?

两种写法不等价吧

#1 楼 @hooopo 是等价的,都是 Callback 的注册语法,Block 的写法适用于代码很少,或者只有一行的情况:http://guides.rubyonrails.org/active_record_validations_callbacks.html#callbacks-overview

The macro-style class methods can also receive a block. Consider using this style if the code inside your block is so short that it fits in just one line.

#2 楼 @lgn21st 在继承的时候是有区别的 https://github.com/rails/rails/blob/master/activerecord/lib/active_record/callbacks.rb

# == Inheritable callback queues
#
# Besides the overwritable callback methods, it's also possible to register callbacks through the
# use of the callback macros. Their main advantage is that the macros add behavior into a callback
# queue that is kept intact down through an inheritance hierarchy.
#
#   class Topic < ActiveRecord::Base
#     before_destroy :destroy_author
#   end
#
#   class Reply < Topic
#     before_destroy :destroy_readers
#   end
#
# Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
# run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation
# where the +before_destroy+ method is overridden:
#
#   class Topic < ActiveRecord::Base
#     def before_destroy() destroy_author end
#   end
#
#   class Reply < Topic
#     def before_destroy() destroy_readers end
#   end
#
# In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
# So, use the callback macros when you want to ensure that a certain callback is called for the entire
# hierarchy, and use the regular overwriteable methods when you want to leave it up to each descendant
# to decide whether they want to call +super+ and trigger the inherited callbacks.
#
# *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
# callbacks before specifying the associations. Otherwise, you might trigger the loading of a
# child before the parent has registered the callbacks and they won't be inherited.

所以说 callback 有三种写法:

before_create :do_sth

before_create do
  # do something
end

这两种是等价的

def before_create 
  # do something
end

这个是不会被继承的。 可对?

咦 好像我搞错了,囧 rz

喜欢这样写:

before_create do # do something end

受教了。

不管使用多少次,我都一律放在 method 里。

method 的名称是“文档”——告知这个 callback 的用处。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号