使用存在条件检查逻辑重构if-else

时间:2017-09-07 04:18:18

标签: ruby-on-rails ruby refactoring

我想要重构这两种方法

def construct_discount_hash(product_adjustments)
  discounts = {
      events: {},
      subjects: {},
      products: {}
  }

  # product_adjustments is a model
  # This is a problem from legacy database structure where event_id, subject_id, product_id is in their own column
  product_adjustments.each do |adjustment|

    if (adjustment.event_id.present?)
      discounts[:events][adjustment.event_id] = {'$' => adjustment.amount, '%' => adjustment.percentage}
    end

    if (adjustment.subject_id.present?)
      discounts[:subjects][adjustment.subject_id] = {'$' => adjustment.amount, '%' => adjustment.percentage}
    end

    if (adjustment.product_id.present?)
        discounts[:products][adjustment.product_id] = {'$' => adjustment.amount, '%' => adjustment.percentage}
    end
  end

  discounts
end

我将在下面的方法中使用上述方法结果

# discounts is a hash generated from above code, item is a rails model
def calculate_order_content_price(discounts, item)
    product = item.product

    if (item.product_variant.present?)
      price = item.product_variant.price
    else
      price = product.price
    end

    price_adjustments = {}
    popped_from = []

    if (discounts[:products][item.product_id])
      price_adjustments = discounts[:products][item.product_id]
      discounts[:products].delete(item.product_id)
      popped_from = [:products, item.product_id]
    elsif (discounts[:subjects][product.subject_id])
      price_adjustments = discounts[:subjects][product.subject_id]
      discounts[:subjects].delete(product.subject_id)
      popped_from = [:subjects, product.subject_id]
    elsif (discounts[:events][product.event_id])
      price_adjustments = discounts[:events][product.event_id]
      discounts[:events].delete(product.event_id)
      popped_from = [:events, product.event_id]
    end

    if (adjustment = price_adjustments['$'])
      adjusted_price = price + adjustment
    elsif (adjustment = price_adjustments['%'])
      adjusted_price = price + price * (adjustment / 100.0)
      discounts[popped_from[0]][popped_from[1]] = price_adjustments
    else
      adjusted_price = price
    end

    { price: adjusted_price, discount: (price - adjusted_price) }
end

我从上面的代码中知道那里有很多代码味道。首先,我认为if-else逻辑可以以某种方式重构。有人可以提供一种技巧,我可以用它来重构if-else条件吗?我很困惑,因为if-condition正在检查值是否存在。

任何建议都会有所帮助。

2 个答案:

答案 0 :(得分:2)

我试图用两个助手简化你的construct_discount_hash

def amount_and_percentage(adjustment, model)
  { adjustment.attributes["#{model}_id"] => { '$': adjustment.amount, '%': adjustment.percentage } }
end

def construct_discount_hash(product_adjustments)
  product_adjustments.each_with_object(Hash.new(0)) do |adjustment, hash|
    case 
    when adjustment.event_id.present?
      hash[:event] = amount_and_percentage(adjustment, 'event')
    when adjustment.subject_id.present?
      hash[:subject] = amount_and_percentage(adjustment, 'subject')
    when adjustment.product_id.present?
      hash[:product] = amount_and_percentage(adjustment, 'product')  
    end
  end
end

答案 1 :(得分:1)

为你重构。

def construct_discount_hash(product_adjustments)
  # product_adjustments is a model
  # This is a problem from legacy database structure where event_id, subject_id, product_id is in their own column
  product_adjustments.each do |adjustment|
    adjustement_hash = {'$' => adjustment.amount, '%' => adjustment.percentage} if adjustement
    (discounts ||= {})[:events][adjustment.event_id] = adjustement_hash if adjustment.event_id.present?
    (discounts ||= {})[:subjects][adjustment.subject_id] = adjustement_hash if adjustment.subject_id.present?
    (discounts ||= {})[:products][adjustment.product_id] = adjustement_hash if adjustment.product_id.present?
  end
  discounts
end

我希望它会对你有所帮助。玩得开心。