2012-03-21 18 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

相關問題