我该如何清理这个Ruby代码?

时间:2011-11-04 15:33:27

标签: ruby-on-rails ruby refactoring

问题

我想解析文本框的行,以便从中生成项目。

我已经开始工作,但它看起来很丑陋。

如何清理“if / else”一塌糊涂?

代码

class LineParser
  def self.parse(line)
    line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
    return matches_to_hash(line_matches)
  end
  def self.matches_to_hash(matches)
    hash = {}
    keys = [:name, :price, :description_text, :quantity, :cat1]
    keys.each do |key|
      if key == :price
        hash[key] = matches[key].to_f
      elsif key == :quantity
        if matches[key].nil?
          hash[key] = 1
        else
          hash[key] = matches[key].to_i
        end
      else
        hash[key] = matches[key]
      end
    end
    hash
  end
end

5 个答案:

答案 0 :(得分:4)

if matches[key].nil?
  hash[key] = 1
else
  hash[key] = matches[key].to_i
end

相当于

hash[key] = (matches[key] || 1).to_i

对于具有多个分支的if / else链,也许case语句更合适。

答案 1 :(得分:3)

从解析中删除了显式返回。

class LineParser
  def self.parse(line)
    line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
    matches_to_hash(line_matches)
  end
  def self.matches_to_hash(matches)
    {
      :price            => matches[:price].to_f,
      :quantity         => (matches[:quantity] || 1).to_i,
      :name             => matches[:name],
      :description_text => matches[:description_text],
      :cat1             => matches[:cat1]
    }
  end
end

答案 2 :(得分:2)

要整理matches_to_hash,我会这样做:

def self.matches_to_hash(matches)
  hash = {}
  hash[:name] = matches[:name]
  hash[:price] = matches[:price].to_f
  hash[:description_text] = matches[:description_text]
  hash[:quantity] = matches[:quantity].nil? ? 1 : matches[:quantity].to_i
  hash[:cat1] = matches[:cat1]
  hash
end

但是,我想我只会将解析改为:

def self.parse(line)
  line_matches = line.chomp.match(/([[:print:]]+) \$(\d+\.*\d*)( +?([^\+#]([[:print:]][^\+#])*))?( +?(\+(\d+)))?( +?#([[:print:]][^#]*))?$/)
  hash = {}
  hash[:name] = $1
  hash[:price] = $2.to_f
  hash[:description_text] = $3
  hash[:quantity] = $4.nil? ? 1 : $4.to_i
  hash[:cat1] = $5
  hash
end

答案 3 :(得分:1)

class LineParser
  def self.parse(line)
    line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
    return matches_to_hash(line_matches)
  end
  def self.matches_to_hash(matches)
    hash = {}
    [:name, :price, :description_text, :quantity, :cat1].each do |key|
      case key
       when :price
         hash[key] = matches[key].to_f
       when :quantity
          hash[key] = 1 if matches[key].nil?
          hash[key] = matches[key].to_i unless matches[key].nil?
       else
         hash[key] = matches[key]
     end
     hash
  end
end

答案 4 :(得分:1)

我不完全确定当每个键执行不同的操作时,为什么要循环键。为什么不一个一个地处理它们呢?

class LineParser
  def self.parse(line)
    line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
    return matches_to_hash(line_matches)
  end
  def self.matches_to_hash(matches)
    hash = {}
    hash[:price] = matches[:price].to_f
    hash[:quantity] = (matches[:quantity] || 1).to_i
    hash[:name] = matches[:name]
    hash[:description_text] = matches[:description_text]
    hash[:cat1] = matches[:cat1]
    hash
  end
end

注意:我也偷了Thilo发布的关于数量的聪明一点。