如何进一步重构红宝石哈希

时间:2018-09-23 06:14:08

标签: ruby-on-rails ruby refactoring

我正在编写一个接受字符串并返回相应模型类的函数。旧版本由丑陋的case语句组成,而重构版本具有较丑陋的哈希。但是哈希对我仍然是重复的。你能给我一些建议吗?

# original function

def determine_node_label(category)
  label = 
    case category 
    when 'boundary box'
      Slide
    when 'circle', 'rectangle'
      GroupBox
    when 'text'
      Text
    when 'picture', 'pie', 'bar' , 'trend', 'star'
      Content
    else
      Content
    end
  return label 
end

# refactored function

def determine_node_label(category)
  label = {
    "boundary box" => Slide,
    "circle" => GroupBox,
    "rectangle" => GroupBox,
    "text" => Text,
    "picture" => Content,
    "pie" => Content,
    "bar" => Content,
    "trend" => Content,
    "star" => Content
  }
  label.default = Content
  return label["category"]
end

更新:

我对假设label.default随时可能更改的解决方案更感兴趣。我很抱歉没有在代码中明确指出这一点。

3 个答案:

答案 0 :(得分:4)

那呢?

LABELS = {
  "boundary box" => Slide,
  "circle"       => GroupBox,
  "rectangle"    => GroupBox,
  "text"         => Text
} 

def determine_node_label(category)
  LABELS[category] || Content
end

答案 1 :(得分:3)

如果您想要动态默认值,则可以使用Hash.fetch。另外,将默认值作为方法参数传递。

LABELS = {
  "boundary box" => Slide,
  "circle"       => GroupBox,
  "rectangle"    => GroupBox,
  "text"         => Text
} 

def determine_node_label(category, default = 'Content')
  LABELS.fetch(category, default)
end

答案 2 :(得分:0)

为便于维护,我建议将数据保存在以下哈希中。

DATA = {
  %w| boundary\ box |              => 'Slide',
  %w| circle rectangle |           => 'GroupBox',
  %w| text |                       => 'Text',
  %w| picture pie bar trend star | => 'Content'
}
  #=> {["boundary box"]=>"Slide", ["circle", "rectangle"]=>"GroupBox",
  #    ["text"]=>"Text", ["picture", "pie", "bar", "trend", "star"]=>"Content"}

请注意,我制作了值文字(字符串)来演示如何处理此哈希。在实际应用中,值不一定是文字。

然后提供一种从h创建所需哈希DATA和指定默认值的方法(当h[k]不具有默认值时,默认值由h返回)键k)。

def data_to_hash(data, default)
  data.each_with_object({}) { |(k,v),h| k.each { |obj| h[obj] = v } }.
       tap { |h| h.default = default }
end

这可能被用如下。

h = data_to_hash(DATA, 'Cat')
  #=> {"boundary box"=>"Slide", "circle"=>"GroupBox",
  #    "rectangle"=>"GroupBox", "text"=>"Text", "picture"=>"Content",
  #    "pie"=>"Content", "bar"=>"Content", "trend"=>"Content",
  #    "star"=>"Content"}
h["boundary box"]
  #=> "Slide"
h["pie"]
  #=> "Content"
h["cake"]
  #=> "Cat"

要随后更改默认值,您可以使用修改后的默认值再次调用data_to_hash或直接执行

h.default = "Dog"

或将后者包装在方法中。

def change_default(h, new_default)
  h.default = new_default
end

change_default(h, "Dog")
  #=> "Dog"
h["pie"]
  #=> "Content"
h["cake"]
  #=> "Dog"