2012-05-23 23 views
1

我是Sinatra和網絡編程的新手,所以一些使用的術語可能不太正確。無論如何...緩存Sinatra中的文本文件內容

我有一個應用程序,逐行讀入.txt數組,然後當你加載index.html.erb它隨機顯示其中一行。我把內容放在一個文本文件中,而不是直接放到數組中,這樣如果我需要添加更多的數據,更容易更新,然後直接添加到數組並重新部署應用程序。我擔心的是,如果每次載入頁面時都重新創建數組並重新讀取文件。我不知道服務器端是如何工作的,或者如何檢查它。創建數組的代碼讀取:

before do 
    @ways ||= [''] 
    if @ways[1].nil? 
    File.open('ways.txt', 'r').each_line { |line| @ways << line } 
    end 
end 

然後我的路線:

get '/' do 
    @way = @ways.sample 

    erb :index 
end 

有沒有一種方法,以確保這是儘可能高效?還是應該完全以其他方式完成?根據Chrome開發工具,它可以傳輸約800b每頁的負載。

+1

提示:隨機數組元素使用'@ ways.sample'。 –

+0

謝謝!修訂。 – lyonsinbeta

回答

4

你在這裏寫的東西確實會將文件讀入每個請求的數組中。

提示:你可以把它短,更快地@ways = File.readlines('ways.txt')

如果你想緩存此數組,你可以在應用程序啓動爲常數這樣做,例如:

WAYS = File.readlines('ways.txt').map(&:chomp) 
get "/" do 
    @way = WAYS.sample 
    erb :index 
end 

然而,如果您編輯了文本文件,則需要退出並重新啓動服務器。如果您想避免這種情況,您可以在before操作中檢查文件的修改時間,如果內容已更改,則只更新陣列(replace it)。

如果您需要此最後建議的幫助,請告訴我,我可以編輯以適合您。


編輯:下面是一個常量來保存數據並重新加載的一種方式,只有當文件的變化:

WAYS = { file:'ways.txt', all:[] } 
before do 
    if WAYS[:updated] != (mtime=File.mtime(WAYS[:file])) 
    WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp) 
    WAYS[:updated] = mtime 
    end 
end 
get "/" do 
    @way = WAYS[:all].sample 
    erb :index 
end 

這是一個有點咄咄逼人—檢查文件的修改時間對每個請求—,但性能應該適用於所有,但最重的負載或最慢的磁盤。

另一種解決方案是啓動線程以每隔幾分鐘強制檢查/更新數組,例如,

require 'sinatra' 

WAYS = { file:'ways.txt', all:[] } 
Thread.new do 
    loop do 
    if WAYS[:updated] != (mtime= File.mtime(WAYS[:file])) 
     WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp) 
     WAYS[:updated] = mtime 
    end 
    sleep 5 # seconds 
    end 
end 

get '/' do 
    WAYS[:all].sample 
end 
+0

我明白你在做什麼,但如果你可以充實一點,我將不勝感激。 – lyonsinbeta

+0

@thekungfuman看我的編輯。 – Phrogz

+0

這太棒了!你給了我很多東西來閱讀。非常感謝! – lyonsinbeta

相關問題