什么是覆盖的ActiveRecord的find两个模型和集合最彻底的方法? [英] What's the cleanest way to override ActiveRecord's find for both models and collections?

查看:117
本文介绍了什么是覆盖的ActiveRecord的find两个模型和集合最彻底的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有库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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆