2014-09-23 82 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! 

这只是一个简单的例子,已经有了相当复杂。正如你可以想象的那样,这很快就会与更大的班级脱节,所以要确保你尽量少用备忘录,只有在有实际利益的地方。