什么是覆盖的ActiveRecord的find两个模型和集合最彻底的方法? [英] What's the cleanest way to override ActiveRecord's find for both models and collections?
问题描述
我有库code重写氩气的发现方法。我还包括了模块的所有关联类所以无论MyModel.find和@ parent.my_models.find工作,并应用正确的范围。
I have library code that overrides Ar's find method. I also include the module for all Association classes so both MyModel.find and @parent.my_models.find work and apply the correct scope.
我根据我的code脱will_paginate的:
I based my code off of will_paginate's:
a = ActiveRecord::Associations
returning([ a::AssociationCollection ]) { |classes|
# detect http://dev.rubyonrails.org/changeset/9230
unless a::HasManyThroughAssociation.superclass == a::HasManyAssociation
classes << a::HasManyThroughAssociation
end
}.each do |klass|
klass.send :include, Finder::ClassMethods
klass.class_eval { alias_method_chain :method_missing, :paginate }
end
我的问题是,我只是想覆盖发现者对于某些型号。目前,我需要延长这是由所有模型共享的所有关联的集合类。我知道我可以通过传递一个模块扩展每个模型关联:
My problem is, I only want to override the finders for some models. Currently I need to extend all association collection classes which are shared by all models. I know I can extend associations per model by passing a module:
has_many :things, :extend => SomeCustomMethods
但我的图书馆基本上是ActiveRecord的插件,所以我想为适用于两种型号和范围的集合,而不会影响应用程序中的所有型号可插拔取景器扩展干净的习惯。
But my library is basically am ActiveRecord plugin, so I'd like a clean convention for plugable finder extensions that apply to both the model and scoped collections without affecting all models in the application.
推荐答案
您希望重写 find_every
,这是将最终运行AR方法的find_by_sql
与相应的查询。覆盖查找
不会为定制的发现者工作,它只是更加脆弱。
You want to override find_every
, which is the AR method that will ultimately run find_by_sql
with the corresponding query. Overriding find
won't work for customized finders, and it's just more fragile.
但要与其他插件兼容,你不能只重载此方法。相反,它的别名和做后,你想要什么叫原实:
But to be compatible with other plugins you can't just overload this method. Instead, alias it and call the original implementation after doing what you want:
module MyPlugin
def self.included(base)
class << base
alias_method :find_every_without_my_plugin, :find_every
def find_every(*args)
# do whatever you need ...
find_every_without_my_plugin(*args)
end
end
end
end
ActiveRecord::Base.send :include, MyPlugin
这将使你的插件的所有类。你怎么要控制使用哪个型号?也许一个标准插件存取?
This will enable your plugin for all classes. How do you want to control which models are enabled? Maybe a standard plugin accessor?
class User < ActiveRecord::Base
my_plugin
end
要支持这一点,你需要移动类&LT;&LT;基
一类方法(因此基础
应自
)。像:
To support this you need to move the class << base
to a class method (thus base
should be self
). Like:
module MyPlugin
def self.included(base)
class << base
base.extend ClassMethods
end
end
module ClassMethods
def my_plugin
class << self
alias_method :find_every_without_my_plugin, :find_every
# ...
end
end
end
end
这篇关于什么是覆盖的ActiveRecord的find两个模型和集合最彻底的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!