mik*_*son 34 ruby ruby-on-rails
我只是阅读有关宝石/插件开发的Rails 3和对面跑去这篇文章,指出alias_method_chain不再使用.我可以看到该方法仍然存在于activesupport-3.0.0/lib/active_support/core_ext/module/aliasing.rb中.
我还应该在Rails 3中使用alias_method_chain吗?
是这仍然反映出在Rails 3的是要修改的ActiveRecord宝石/插件的最佳实践?
edg*_*ner 57
不,它已被模块中的方法覆盖和super关键字的巧妙使用所取代.
基本上,您在包含的模块中定义原始函数,并在另一个包含的模块中覆盖它.当您调用super覆盖函数时,它会调用原始函数.但有一个问题.在包含基本模块之后,您必须包括扩展模块,并按照您希望链接发生的顺序.
class Something
module Base
def my_method
# (A) original functionality
end
end
module PreExtension
def my_method
# (B) before the original
super # calls whatever was my_method before this definition was made
end
end
module PostExtension
def my_method
super # calls whatever was my_method before this definition was made
# (C) after the original
end
end
include Base # this is needed to place the base methods in the inheritance stack
include PreExtension # this will override the original my_method
include PostExtension # this will override my_method defined in PreExtension
end
s = Something.new
s.my_method
#=> this is a twice extended method call that will execute code in this order:
#=> (B) before the original
#=> (A) the original
#=> (C) after the original
Run Code Online (Sandbox Code Playgroud)
Railscasts的 Ryan Bates 谈到了如何在Rails路由代码中使用它.我建议观看它,以及他的其他截屏视频.他们有能力将针织祖母变成Rails大师.
PS:为了纠正我原来答案中的一个基本错误,我会去Peeja.谢谢.
Pee*_*eja 19
通常,模块永远不能覆盖它所包含的类中的方法.这是因为模块包含就像子类一样.超类也不能覆盖它的子类的方法,也不期望它.
当一个模块包含在一个类中时,该模块就会在该类的祖先链中的类之后插入.调用
super从类将调用模块的实现.
class Something
module PreExtension; end
module PostExtension; end
include PreExtension
include PostExtension
end
Something.ancestors # => [Something, Something::PostExtension, Something::PreExtension, Object, Kernel]
Run Code Online (Sandbox Code Playgroud)
每当在a上调用一个方法时Something,Ruby按顺序查看此列表并调用它找到的第一个实现.如果实现调用super,它会一直查找并找到下一个.
这意味着后面包含的模块优先于前面包含的模块,并且可以调用super以获取早期模块的实现.这是因为包含的模块在类之后直接插入祖先链中.这就是路由代码edgerunner提到的工作方式.该代码将所有内容放在模块中,如下所示:
class SomethingNew
module Base
def my_method
puts "(A)"
end
end
module Extension
def my_method
puts "(B)"
super
end
end
include Base
include Extension
end
SomethingNew.new.my_method
# Output:
# >> (B)
# >> (A)
SomethingNew.ancestors # => [SomethingNew, SomethingNew::Extension, SomethingNew::Base, Object, Kernel]
Run Code Online (Sandbox Code Playgroud)
这就是为什么alias_method_chain首先存在的原因.如果将基本代码放在模块中不是一个选项,我不知道如何完成等效的alias_method_chain.
| 归档时间: |
|
| 查看次数: |
13377 次 |
| 最近记录: |