理解acts_as_anything的创建
我成功创建了一个具有一些类和模块的 gem,以便能够在 Rails 项目中的任何类型的类中执行类似的操作:
class AnyRubyOrActiveModelClass
acts_as_anything [:foo, :bar]
def foo
.. do some foo
end
def self.bar
.. do some bar
end
end
为此,我在 gem 中创建了一个看起来像这样的模块:
module InstanceMagic
class << self.class.superclass
define_method(:acts_as_anything) do |methods|
self.class_eval do
include ClassMagic
.. do some alias_method with given methods
end
end
end
此模块已成功别名我的方法 :foo 来自上面的示例,第二个模块 ClassMagic 对我的 :bar 类方法做了同样的事情(遵循 此处)。
在一个测试项目中,这种方法效果非常好。在现实生活中的项目中,它导致了对另一颗采用(可能类似)方法的宝石的干扰。即使我只将我的 gem 集成到项目中,这个 gem 也会抱怨类中缺少方法 - 甚至没有将 actions_as_anything 集成到类中。
所以我将代码分解为:
module InstanceMagic
class << self.class.superclass
define_method(:acts_as_anything) do |methods|
#really empty here
end
end
结果另一个宝石仍然损坏。
我使用了类<< self.class.superclass 显式扩展 Object,这样即使非 ActiveSomething 类但所有类都会受到影响,并且我的 actions_as_anything 可用。所以我仍然有三个问题。
为什么最后 5 行代码会破坏另一个 gem 并使其抱怨缺少它试图动态创建的方法?我想了解一下。
有更好的方法来实现我的目标吗?
当我使用 method_added 和 singleton_method_added (我在模块中实际执行的操作)时,我是否应该查找这些方法是否已经存在,为“原始”方法别名,插入我的方法并在完成工作后调用原始方法?
知道了很多,我仍然希望有人能指出我正确的方向。
谢谢。 菲利克斯
I successfully created a gem having some classes and modules to be'ing able to to something like that in ANY kind of class in a Rails project:
class AnyRubyOrActiveModelClass
acts_as_anything [:foo, :bar]
def foo
.. do some foo
end
def self.bar
.. do some bar
end
end
To do so I created a Module in my gem that looked something like that:
module InstanceMagic
class << self.class.superclass
define_method(:acts_as_anything) do |methods|
self.class_eval do
include ClassMagic
.. do some alias_method with given methods
end
end
end
This module successfully aliased my method :foo from the example above, the second module ClassMagic did the same for my :bar class method (following the advice from here).
In a testproject that approach worked very well. In a real life project it led to interference with another gem taking a - maybe similar - approach. This gem complained about missing methods in a class even when I only integrated my gem into the project - not even integrated acts_as_anything into the class.
So I broke down my code to only that:
module InstanceMagic
class << self.class.superclass
define_method(:acts_as_anything) do |methods|
#really empty here
end
end
As a result the other gem still breaks.
I used class << self.class.superclass to explicitly extend Object, so that even non ActiveSomething classes but ALL classes are affected and my acts_as_anything is available. So I remain with three questions.
Why do the last 5 lines of code break another gem and making it complain about missing methods it's trying to dynamically create? I would like to understand.
Is there a better approach to achieve my goal?
When I use method_added and singleton_method_added (what I actually do inside my modules), should I look for these methods whether they already exist, alias the "original" ones, insert my ones and call the original ones after I have done my job?
Knowing this is a lot I still hope someone can point me into the right direction.
Thank you.
Felix
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我唯一能想到的是某种顺序依赖性(远景)。尝试将代码放入 Rails 应用程序的初始化程序中,看看是否仍然会导致相同的问题。
The only thing I can think of is some sort of order dependency (long shot). Try to put your code in an initializer in the rails app and see if it still causes the same problems.