簡體   English   中英

Rails的輔助方法記憶

[英]Rails Memoization of Helper method

我有一個輔助方法,該方法執行昂貴的計算並返回Hash ,並且該Hash在我的整個應用程序生命周期中都是恆定的(這意味着它只能在重新部署后才能更改),並且也不接受任何參數。

為了提高性能,我希望可以“緩存”生成的Hash

不想用Rails緩存對於這一點,因為我想避免額外的行程Memcached和我不想要的反序列串入一個散列的開銷。

我的第一個想法是將結果哈希分配給Constant並在其上調用.freeze 但是幫助程序是一個實例方法,常量始終存在於類中,我不得不執行以下超級hacky解決方案:

module FooHelper

def expensive_calculation_method
  resulting_hash
end

EXPENSIVE_CALCULATION_CONSTANT = Class.new.extend(self).expensive_calculation_method.freeze

這是由於helper方法是實例方法,helper是Module(導致偽類擴展,所以我可以調用實例方法),並且我還必須在實例方法之后聲明常量AFTER(如果我正確聲明的話)在module FooHelper ,我得到了一個undefined method 'expensive_calculation_method'

第二個想法是使用記憶,但是至少對於Rails Controller來說,記憶是在單個請求的生命周期內變量的持久性,因此僅當您在單個請求中多次重復使用變量時才有價值,這不是我的想法。情況,但同時Helpers是模塊,而不是要實例化的類,並且到目前為止,我不知道該怎么做。

我將如何緩存該哈希,或以對請求的持久化方式對其進行記憶?

如果要在啟動時緩存某些痛苦的操作的結果,請執行以下操作:

module MyExpensiveOperation
  COMPUTED_RESULT = OtherModule.expensive_operation

  def self.cached
    COMPUTED_RESULT
  end
end

只需確保以某種方式加載了該模塊,否則該模塊將不會啟動。 您始終可以在environment.rb或作為config/initializer類型文件強制require該模塊。

如果要延遲加載,其基本原理是相同的:

module MyExpensiveOperation
  def self.cached
    return @cached if (defined?(@cached))

    @cached = OtherModule.expensive_operation
  end
end

這將處理由於任何原因返回nilfalse 它將運行一次,並且只能運行一次,除非您有多個線程同時觸發它。 如果是這種情況,則可以通過自動鎖定來使您的模塊並發感知。

根據您的評論,這只會在應用程序啟動時發生變化,因此將其放在初始化程序中就可以解決問題。

# config/initializers/expensive_thing.rb
$EXENSIVE_THING_GLOBAL = expensive_calculation

# or
EXPENSIVE_THING_CONSTANT = expensive_calculation

# or

Rails.application.config.expensive_thing = expensive_calcualatioin

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM