在gem中转换ActiveRecord的扩展名

时间:2013-08-13 17:55:06

标签: ruby-on-rails ruby-on-rails-3 activerecord rubygems

此扩展程序为所有应用模型创建cache_find方法(我使用this post创建此方法)。

配置/ active_record_extension.rb

require 'active_support/concern'

module ActiveRecordExtension

  extend ActiveSupport::Concern

  # add your instance methods here
  def flush_find
    Rails.cache.delete([self.class.name, :cached_find, id])
  end

  included do
    after_commit :flush_find
  end

  module ClassMethods
    def cached_find id
      Rails.cache.fetch([self.name, :cached_find, id]) { self.find(id) }
    end
  end
end

# include the extension
ActiveRecord::Base.send(:include, ActiveRecordExtension)

我将此代码转换为gem并添加到此repo

所以我想动态添加这些方法,如下所示:

class User << ActiveRecord::Base
  # id, name, email, age...

  cached :find, :find_by_name, :find_by_email
end

以上代码应该生成cached_findflush_findcached_find_by_nameflush_find_by_name ......你明白了。

我需要帮助:

  1. Rails.cache gem。
  2. 中测试model_caching个方法
  3. 创建代码,根据cached方法参数动态地将方法添加到应用模型。
  4. 有些链接帮助了我但并不满足所有要求:

    https://github.com/radar/guides/blob/master/extending-active-record.md

    http://railscasts.com/episodes/245-new-gem-with-bundler

    http://guides.rubyonrails.org/plugins.html

    可以随意克隆并改进gem code

2 个答案:

答案 0 :(得分:3)

您不必破解ActiveRecord :: Base。您可以添加Marc-Alexandre所说的内容,如下所示:

module ActiveRecordExtension
  extend ActiveSupport::Concern

  ...

  module ClassMethods
    def cached(*args)
      define_method "cached_#{arg.to_s}" do 
        # do whatever you want to do inside cached_xx
      end

      define_method "flush_#{arg.to_s}" do
        # do whatever you want to to inside flush_xx
      end
    end
  end
end

另外,我不会直接在ActiveRecord中自动包含扩展名,我认为最好将它明确地包含在您要使用它的模型中。

答案 1 :(得分:1)

要动态添加代码,您需要破解ActiveRecord :: Base类。在另一个文件中(通常放在lib / core_ext中),您可以执行以下操作:

ActiveRecord::Base.class_eval do
  def self.cached(*args)
    args.each do |arg|
      define_method "cached_#{arg.to_s}" do 
        # do whatever you want to do inside cached_xx
      end

      define_method "flush_#{arg.to_s}" do
        # do whatever you want to to inside flush_xx
      end
    end
  end
end

它的作用基本上是将所有参数用于缓存(:find,:find_by_name等)并定义两个方法(cache_find,cache_find_by_name)和flush_find,..等)

希望这有帮助!