简体   繁体   English

ruby - 重构if else语句

[英]ruby - refactoring if else statement

I've tried reading some tutorials on refactoring and I am struggling with conditionals. 我已经尝试阅读一些关于重构的教程,我正在努力解决条件问题。 I don't want to use a ternary operator but maybe this should be extracted in a method? 我不想使用三元运算符,但也许这应该在方法中提取? Or is there a smart way to use map? 或者有一种聪明的方式来使用地图吗?

detail.stated = if value[:stated].blank?
                  nil
                elsif value[:stated] == "Incomplete"
                  nil
                elsif value[:is_ratio] == "true"
                  value[:stated] == "true"
                else
                  apply_currency_increment_for_save(value[:stated])
                end

If you move this logic into a method, it can be made a lot cleaner thanks to early return (and keyword arguments): 如果将此逻辑移动到一个方法中,由于早期return (和关键字参数),它可以变得更加清晰:

def stated?(stated:, is_ratio: nil, **)
  return if stated.blank? || stated == "Incomplete"
  return stated == "true" if is_ratio == "true"
  apply_currency_increment_for_save(stated)
end

Then... 然后...

detail.stated = stated?(value)
stated = value[:stated]
detail.stated = case
  when stated.blank? || stated == "Incomplete"
    nil
  when value[:is_ratio] == "true"
    value[:stated] == "true"
  else
    apply_currency_increment_for_save stated
end

What's happening: when case is used without an expression, it becomes the civilized equivalent of an if ... elsif ... else ... fi. 发生了什么:如果在没有表达的case使用case ,它就会成为if ... elsif ... else ... fi.的文明等价物if ... elsif ... else ... fi.

You can use its result, too, just like with if...end . 你也可以使用它的结果,就像if...end

Move the code into apply_currency_increment_for_save and do: 将代码移动到apply_currency_increment_for_save并执行:

def apply_currency_increment_for_save(value)
  return if value.nil? || value == "Incomplete"
  return "true" if value == "true"
  # rest of the code. Or move into another function if its too complex
end                         

The logic is encapsulated and it takes 2 lines only 逻辑是封装的,只需要2行

I like @Jordan's suggestion. 我喜欢@Jordan的建议。 However, it seems the call is incomplete -- the 'is_ratio' parameter is also selected from value but not supplied. 但是,似乎调用不完整 - 'is_ratio'参数也是从值中选择但未提供。

Just for the sake of argument I'll suggest that you could go one step further and provide a class that is very narrowly focused on evaluating a "stated" value. 仅仅为了论证,我建议你可以更进一步,提供一个非常专注于评估“陈述”价值的课程 This might seem extreme but it fits with the notion of single responsibility (the responsibility is evaluating "value" for stated -- while the 'detail' object might be focused on something else and merely makes use of the evaluation). 这似乎是极端的,但它符合单一责任的概念(责任是评估所述的“价值” - 而“细节”对象可能只关注其他事物,而仅仅是利用评估)。

It'd look something like this: 它看起来像这样:

class StatedEvaluator
  attr_reader :value, :is_ratio

  def initialize(value = {})
    @value = ActiveSupport::StringInquirer.new(value.fetch(:stated, ''))
    @is_ratio = ActiveSupport::StringInquirer.new(value.fetch(:is_ratio, ''))
  end

  def stated
    return nil if value.blank? || value.Incomplete?
    return value.true? if is_ratio.true?
    apply_currency_increment_for_save(value)
  end
end

detail.stated = StatedEvaluator.new(value).stated

Note that this makes use of Rails' StringInquirer class . 请注意,这使用了Rails的StringInquirer类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM