Back

Ruby meta programming spell: alias_method_chain

发布时间: 2013-02-17 03:32:00

了解这个spell的基础是,你要知道 alias_method :的用法: alias_method :new_name, :old_name

这个东东非常常见,遍及RAILS代码的每个角落。起源是:

1. 假设我们希望为某个方法加上新功能:  可以用 alias_method.

ActionController::TestCase.class_eval do
  # save a reference to the original process method
  alias_method :original_process, :process
 
  # now redefine process and delegate to original_process
  def process(action, params=nil, session=nil, flash=nil, http_method='GET')
    params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
    original_process(action, params, session, flash, http_method)
  end
end

2. 上面的方法有一点风险:如果 original_process 这个方法名已经被使用了的话,程序就会不正常。所以,为了避免这个问题,大家习惯于为新方法加一个文字后缀:

ActionController::TestCase.class_eval do
  def process_with_stringified_params(...)
    params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
    process_without_stringified_params(action, params, session, flash, http_method)
  end
  alias_method :process_without_stringified_params, :process
  alias_method :process, :process_with_stringified_params
end

3. 后来大家觉得一次写两个alias_method 好麻烦啊。 因为目的仅仅是为了新增加一个方法。而不是要改动两个方法。所以,就诞生了 alias_method_chain:

ActionController::TestCase.class_eval do
  def process_with_stringified_params(...)
    params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
    process_without_stringified_params(action, params, session, flash, http_method)
  end
  # 这里是核心,替代了原来的两个 alias_method.  
  alias_method_chain :process, :stringified_params
end

Back