LoginSignup
1
1

More than 5 years have passed since last update.

ruby 中的 alias_method 和 Rails 中的 alias_method_chain

Posted at
  • ruby 中有这样一个给方法添加别名的函数:

通过这个方式, 可以一定意义上做到方法的重写. 因为新方法可以有新的行为,而且还保留着旧方法的访问.

module Mod
  alias_method :orig_exit, :exit # 这个有点坑,乍一看,以为这个 exit 就是下面的这个方法呢!!!
  def exit(code=0)
    puts "Exiting with code #{code}"
    orig_exit(code)
  end
end
include Mod
exit(99)

输出Exiting with code 99

  • rails 中为了能够实现类型装饰模式的行为,基于上面的这个 alias_method 做了一个 alias_method_chain 的方法, 它的作用就是能够在原本执行的方法前后加上一些起装饰作用的代码. 下面看看它源码:
class Module

  def alias_method_chain(target, feature)
    # Strip out punctuation on predicates or bang methods since
    # e.g. target?_without_feature is not a valid method name.

    # 剔除方法名中的 ? = 和 !, 然后保存这个符号
    aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
    yield(aliased_target, punctuation) if block_given?

    # 定义2个方法名字
    with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"


    alias_method without_method, target
    alias_method target, with_method

    case
      when public_method_defined?(without_method)
        public target
      when protected_method_defined?(without_method)
        protected target
      when private_method_defined?(without_method)
        private target
    end
  end

  ...

end

可以从上面的说明中感觉到,有时候会把方法名给别来别去的, 这个时候就 rails 按照自己的风格作为一个约束来封装了这个一系列的动作.
看看下面的代码:


module Foo
  class Bar
    def initialize
      p 'init'
    end

    def initialize_with_p
      p 'with p'
      initialize_without_p
    end

    def initialize_without_p
      p 'without p'
    end

    alias_method_chain :initialize, :p
  end

end


fb = Foo::Bar.new

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1