2

我认为我可能不会以最红宝石的方式编写延迟实例化的方法/属性。以这种方法为例:

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

有没有更类似于 ruby​​ 的方式来重构这个方法?

4

4 回答 4

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
于 2012-06-27T20:38:58.047 回答
2

你问的是什么叫做记忆。正如 Yuri 建议的那样,为此使用 Proc 很尴尬。

这是我的快速重构。我可能仍会进一步重构它......但它是一个更简单的重构,它更像是 Ruby 风格。

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。这是一篇关于记忆的文章。

于 2012-06-27T20:33:11.197 回答
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界面,你可以把它改成你喜欢的。这是鲁比,宝贝!你可以像泡泡糖一样扭曲、弯曲和拉伸的语言。也许这样的界面会很好:

def_memoized :tax do
  # expensive calculation here
end

我喜欢将每个项目对核心 Ruby 的扩展放在一个名为lib/core_extensions.rb. 这就是那种会进去的东西。

于 2012-06-27T20:52:35.560 回答
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

还有其他实现它的方法,但与你所拥有的相比,这是一个很大的改进。

于 2012-06-27T20:23:04.793 回答