我已经编写了一个帮助方法,可以将街道地址中的城市转换为相应的FIPS Place代码:
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
方法(每种种类一种 - 例如city_pop_white
,city_pop_black
,city_pop_asian
等。
所有的工作都很好,但响应时间过长,因为每次遇到place_fips
方法之一时它都会运行city_pop_foo
查询。有没有办法定义place_fips
一次,并在后续方法中使用它而不是每次都从数据库中取出它?
此外,我怀疑还有一种方法 - 而不是使用多个def city_pop_foo
方法 - 干掉这段代码并只定义def city_pop
一次,然后传入将改变{{1}的参数在P00####
查询中(所以我可以在我的观看中写出@census.where
,<%= city_pop(white) %>
,<%= city_pop(black) %>
等内容。我在这里走在正确的轨道上吗?这可能是什么样的?
答案 0 :(得分: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!
因此,只要名称发生变化,您就需要清除缓存/记忆的问候语:
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!
这只是一个简单的例子,已经相当复杂。正如您可以想象的那样,这很快就会失控,因此请务必谨慎使用备忘录,只能在有实际利益的地方使用。