Rails:在ActiveRecord模型检索之前运行代码

时间:2012-03-21 18:29:02

标签: ruby-on-rails ruby activerecord

有没有办法在模型检索之前运行代码?我知道 after_find 回调,但我需要先运行。无论返回的记录数是多少,我还希望每次检索只运行ONCE。查看RoR源代码,查询实际上是在 ActiveRecord :: Relation 中的 exec_queries (或 to_a )中执行的。我是否应该覆盖此方法以添加此挂钩?

为了防止这一切都错了,我问的原因是我有一个外部REST API用于检索数据,但是在每次重新加载页面后检索太慢了。我最初使用memcached,但我想我可以使用ActiveRecord来缓存数据库中的数据,这样我就可以轻松地查询数据,并可能将其与其他REST API中的类似数据连接起来。我想插入一个回调,在一段特定的超时时间之后,在返回ActiveRecord结果之前从REST重新加载数据。

基本上我正在寻找从另一个源(REST)集中刷新我的数据库的最佳方法,而不是混乱我的控制器或覆盖我使用的每个模型访问器(有没有办法轻易地覆盖它们?)。也许最好的解决方案就在这里。

所有内置方法,如所有,查找,第一次和最后一次调用 apply_finder_options (然后其中),但动态创建的查找程序(find_by_name,等)调用 find_dynamic_match ,最终调用 where 。这就是我对关系的 to_a 方法的原因,因为它是常见的并且在查询实际执行时被调用,而不仅仅是在执行查询之前构建关系时。然而,在Rails中获得这个低级别让我感到不舒服。

似乎我的问题不应该是一个不常见的问题,所以也许我的方法是错的?

仅供参考,我是铁杆和红宝石的新手。谢谢!

1 个答案:

答案 0 :(得分:1)

我强烈建议不要使用低级钩子代替显式缓存检查。 ActiveRecord有自己的缓存机制,但如果不是为你而且你需要构建自己的缓存机制 - 在使用ActiveRecord查找器之前使用它显式。像这样的钩子可以使确定发生的事情和原因非常混乱,并且不是推荐的做法。以下是使用代理模型的示例:

class CacheProxy
  attr_accessor :klass
  def initialize(klass)
    @klass = klass
  end

  def method_missing(method_id, *arguments, &block)
    reload_if_necessary
    klass.send(method_id, *arguments, &block)
  end

  private
  def reload_if_necessary
    return unless needs_reload?
    # perform reload
  end

  def needs_reload?
    # determine if we need to reload the cache
  end
end

class ActiveRecord::Base
  def self.proxy
    CacheProxy.new(self)
  end
end

现在你甚至可以MyModel.proxy.find_by_first_name_and_last_name('John', 'Doe')

相关问题