2012-03-21 58 views
0

有没有一种方法可以在模型检索之前运行代码?我知道after_find回调,但我需要运行之前。无论返回的记录数是多少,我也希望它只在每次检索时运行一次。看看RoR来源,看起来查询实际上在exec_queries(或to_a)中ActiveRecord :: Relation执行。做/我应该重写这个方法来添加这个钩子?Rails:在ActiveRecord模型检索之前运行代码

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

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

这似乎所有的内置像所有的方法,发现,第一和最后呼叫apply_finder_options(然后其中),但动态创建的发现者(find_by_name等)调用find_dynamic_match最终调用其中。这是什么导致我在关系上使用to_a方法,因为它是常见的,并且在查询实际执行时调用,而不仅仅是在执行查询之前构建关系。然而,将这个低级别导入Rails会让我感到不舒服。

这似乎是我的问题不应该是一个不寻常的,所以也许我的做法是错误的?

仅供参考,我是rails和ruby的新手。谢谢!

回答

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')

+0

我第二PinnyM的关注和建议。为什么不使用memcached?假设你的其他REST API可以访问你建议放入数据库的新东西,那么他们可以访问你放入memcached的东西,对吧?他们所要做的就是定义一个关于如何命名缓存键的约定(提示:使用内置于Rails缓存中的方法:-),以及何时/如何使它们失效,然后而不是对数据库施加更多负载,你正在使用内存。同一个数据库的多个应用程序的同步给了我willies :-) – 2012-03-21 19:20:21

+0

我基本上正在寻找一种方式来填充我的表与新的数据,然后再返回数据。我暂时在我的控制器中刷新了它,但我希望有一个更集中的地方来完成它,而不是每个控制器方法。 – plasticrake 2012-03-21 19:36:37

+0

因此,创建一个模块来完成这项工作,并将其包含在每个模型中。或者可能使用一个中央“交换中心”模式来做到这一点。无论哪种方式,您都可以在不侵入ActiveRecord的情况下获得相同的功能。 – PinnyM 2012-03-21 20:10:58

相关问题