I'm writing a function that takes a string and returns a corresponding model class. The old version consists of ugly case statements, and the refactored version has a less-ugly hash. However the hash still feels repetitive to me. Could you give me some advice?
# 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
update:
I would be more interested in solutions that assume that the label.default
is subject to change. My apologies for not making this clear in the code.
What about this?
LABELS = {
"boundary box" => Slide,
"circle" => GroupBox,
"rectangle" => GroupBox,
"text" => Text
}
def determine_node_label(category)
LABELS[category] || Content
end
If you do want the dynamic default value, you can use Hash.fetch
. Also, pass the default value as the method parameter.
LABELS = {
"boundary box" => Slide,
"circle" => GroupBox,
"rectangle" => GroupBox,
"text" => Text
}
def determine_node_label(category, default = 'Content')
LABELS.fetch(category, default)
end
For ease of maintainability I suggest the data be maintained in the following hash.
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"}
Note that I made the values literals (strings) to demonstrate how this hash will be manipulated. In the actual application the values would not necessarily be literals.
Then provide a method to create the desired hash h
from DATA
and a specified default value (the latter to be returned by h[k]
when h
does not have a key 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
This might be used as follows.
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"
To subsequently change the default you could either call data_to_hash
again, with the revised default, or simply execute
h.default = "Dog"
or wrap the latter in a method.
def change_default(h, new_default)
h.default = new_default
end
change_default(h, "Dog")
#=> "Dog"
h["pie"]
#=> "Content"
h["cake"]
#=> "Dog"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.