1

此扩展cache_find为所有应用模型创建方法(我已使用此帖子创建此方法)。

配置/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_find, flush_find, cached_find_by_name, flush_find_by_name... 你明白了。

我需要帮助:

  1. gem中的测试Rails.cache方法。model_caching
  2. 创建代码以根据cached方法参数向应用模型动态添加方法。

一些对我有帮助但并不完全满足的链接:

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 代码

4

2 回答 2

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 中自动包含扩展,我认为最好将它明确包含在您要使用的模型中。

于 2013-08-20T10:28:18.560 回答
1

To add code dynamically you need to hack the ActiveRecord::Base class. In another file (you usually put in lib/core_ext) you could do as follow :

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

What it does basically is takes all your arguments for cached (:find, :find_by_name, etc) and define the two methods (cache_find, cache_find_by_name) and flush_find, .. etc)

Hope this helps !

于 2013-08-16T14:51:39.573 回答