2014-09-23 46 views
-2

我寫了一個輔助方法,以在街道地址城市轉化成其相應FIPS地方代碼:如何使此方法更高效?

def place_fips 
    place_fips = 'PLACE:' + Place.where(statename: @address.state, placeshort: @address.city).first.placefp 
end 

我現在想在其它幾種方法,這爲城市獲取人口統計數據,以使用「place_fips」 :

def city_pop_tot 
    str = @census.where({ fields: 'P0030001', level: place_fips })[0]["P0030001"].to_i 
end 

我現在有關於這些city_pop_foo方法7(每個種族分類,例如,city_pop_whitecity_pop_blackcity_pop_asian等)

這一切工作罰款,但響應時間太長,因爲它每次遇到city_pop_foo方法之一運行place_fips查詢。有沒有辦法一次性定義place_fips,並在後續的方法中使用它,而不必每次都從數據庫中獲取它?

而且,我懷疑有一個辦法,而不是有幾個def city_pop_foo方法乾燥此代碼,只要定義def city_pop一次,然後傳遞參數,將在@census.where查詢改變P00####(這樣我就可以寫的東西像<%= city_pop(white) %><%= city_pop(black) %><%= city_pop(asian) %>等在我看來)。我在正確的軌道上嗎?這可能是什麼樣子?

+4

這個問題似乎是題外話題,因爲它是關於需要重構的工作代碼,這更適合http://codereview.stackexchange.com/。 – 2014-09-23 04:33:07

回答

0

解決這個問題的方法之一就是記憶。請看下面的例子:

class Greeter 
    def greet 
    puts greeting 
    end 

    def greeting 
    compute_greeting 
    end 

    private 

    def compute_greeting 
    sleep 3 # heavy lifting 
    "Hello, world!" 
    end 
end 

greeter = Greeter.new 
greeter.greet   # takes ~3 seconds 
greeter.greet   # takes ~3 seconds as well 
greeter.greet   # takes ~3 seconds as well 

我們解決這個問題,你可以使用一個名爲像的方法和有條件分配與||=將只設置變量,如果它是nil一個實例變量,否則返回保存的版本:

class Greeter 
    def greet 
    puts greeting 
    end 

    def greeting 
    @greeting ||= compute_greeting 
    end 

    private 

    def compute_greeting 
    sleep 3 # heavy lifting 
    "Hello, world!" 
    end 
end 

greeter = Greeter.new 
greeter.greet   # takes ~3 seconds 
greeter.greet   # runs instantly 
greeter.greet   # runs instantly 

當然,如果緩存的內容以任何方式依賴於對象的狀態,則需要在狀態更改時進行內務管理。下面的代碼被打破,例如:

class PersonalGreeter 
    attr_accessor :name 

    def initialize(name) 
    @name = name 
    end 

    def greet 
    puts greeting 
    end 

    def greeting 
    @greeting ||= compute_greeting 
    end 

    private 

    def compute_greeting 
    sleep 3 # heavy lifting 
    "Hello, #{name}!" 
    end 
end 

greeter = PersonalGreeter.new('Sergio Hernandez') 
greeter.greet # Hello, Sergio Hernandez! 
greeter.name = 'Zaphod Beeblebrox' 
greeter.greet # Hello, Sergio Hernandez! 

所以,你需要清除緩存/ memoized問候每當名稱更改:

class PersonalGreeter 
    attr_reader :name 

    def initialize(name) 
    @name = name 
    end 

    def name=(new_name) 
    @greeting = nil 
    @name = new_name 
    end 

    def greet 
    puts greeting 
    end 

    def greeting 
    @greeting ||= compute_greeting 
    end 

    private 

    def compute_greeting 
    sleep 3 # heavy lifting 
    "Hello, #{name}!" 
    end 
end 

greeter = PersonalGreeter.new('Sergio Hernandez') 
greeter.greet # Hello, Sergio Hernandez! 
greeter.name = 'Zaphod Beeblebrox' 
greeter.greet # Hello, Zaphod Beeblebrox! 

這只是一個簡單的例子,已經有了相當複雜。正如你可以想象的那樣,這很快就會與更大的班級脫節,所以要確保你儘量少用備忘錄,只有在有實際利益的地方。