我认为我可能不会以最红宝石的方式编写懒惰的实例化方法/属性。以此方法为例:
def tax
@tax ||= Proc.new do
if flat_tax > commission_plan.tax_max
return commission_plan.tax_max
end if commission_plan.tax_max
if flat_tax < commission_plan.tax_min
return commission_plan.tax_min
end if commission_plan.tax_min
flat_tax
end.call
end
有没有更像红宝石的方法来重构这个方法?
答案 0 :(得分:6)
def tax
@tax ||= calc_tax
end
private
def calc_tax
min, max = commission_plan.tax_min, commission_plan.tax_max
if (min..max).include? flat_tax
flat_tax
else
flat_tax > max ? max : min
end
end
答案 1 :(得分:2)
你在问什么叫做Memoization。正如Yuri建议的那样,你为此使用Proc是很尴尬的。
这是我的快速重构。我可能仍然会进一步重构......但这是一个简单的重构,它更像Ruby-ish。
def tax
@tax ||= calculate_tax
end
def calculate_tax
if commission_plan.tax_max && flat_tax > commission_plan.tax_max
commission_plan.tax_max
elsif commission_plan.tax_min && flat_tax < commission_plan.tax_min
commission_plan.tax_min
else
flat_tax
end
end
此外,如果您不介意包含一些外部依赖项,请查看ActiveSupport::Memoizable。这篇文章讨论memoization。
答案 2 :(得分:2)
如果您不想向外部库添加依赖项,则可以轻松添加自己的“memoize”帮助程序。有点像:
class Class
def memoize(method)
original_method = instance_method(method)
instance_var = "@__#{method}__".to_sym
define_method(method) do |*a,&b|
cached = instance_variable_get(instance_var)
unless cached
cached = old_method.bind(self).call(*a,&b)
instance_variable_set(instance_var, cached)
end
cached
end
end
end
然后使用就像:
def tax
# expensive calculation here
end
memoize :tax
如果您不喜欢这个memoize
界面,可以将其更改为您喜欢的任何内容。这是Ruby,宝贝!你可以像泡泡糖一样扭曲,弯曲和伸展的语言。也许像这样的界面会很好:
def_memoized :tax do
# expensive calculation here
end
我喜欢将我的每个项目扩展项放在名为lib/core_extensions.rb
的文件中的核心Ruby中。这就是那种情况。
答案 3 :(得分:1)
我不明白你为什么要创建这个匿名函数。这是......多余的。这是一个更好,更清洁的代码:
def tax
return commission_plan.tax_max if commission_plan.tax_max &&
flat_tax > commission_plan.tax_max
return commission_plan.tax_min if commission_plan.tax_min &&
flat_tax > commission_plan.tax_min
return flat_tax
end
还有其他方法可以实现它,但与你的相比,这是一个很大的进步。