我正在使用Ruby on Rails 3.2.9和Ruby 1.9.3。我有以下case
语句:
case
when private?
case
when not_active? then [:a, :b, :c, :d]
when active? then raise "private cannot be active"
else raise "not recognized"
end
when shared?
case
when not_active? then [:a, :b, :c]
when active? then raise "shared cannot be active"
else raise "not recognized"
end
when public?
case
when not_active? then [:a, :b]
when active? then [:a]
else raise "not recognized"
end
else raise "not recognized"
end
如何重构上面的代码?
答案 0 :(得分:6)
raise "not recognized" unless private? or shared? or public?
raise "not recognized" unless not_active? or active?
raise "private cannot be active" if private? and active?
raise "shared cannot be active" if shared? and active?
[:a, *(:b unless active?), *(:c unless public?), *(:d if private?)]
raise "visibility not recognized" unless private? or shared? or public?
raise "activeness not recognized" unless not_active? or active?
raise "active must be public" if active? and not public?
[:a, *(:b unless active?), *(:c unless public?), *(:d if private?)]
顺便说一下,inactive?
是比not_active?
更好的方法名称。
答案 1 :(得分:0)
有组织的:
CONDITIONS =
{"private?" => {"not_active?" => [:a, :b, :c, :d],
"active?" => "private cannot be active"},
{"shared?" => {"not_active?" => [:a, :b, :c],
"active?" => "shared cannot be active"},
{"public?" => {"not_active?" => [:a, :b],
"active?" => [:a]}}
def foo(it)
value = "not recognised"
CONDITIONS.each do |k, v|
if it.send(k.to_sym)
v.each do |inner_k, inner_v|
if it.send(inner_k.to_sym)
value = inner_v
end
end
end
end
raise value if (value.class.name == "String")
value
end
如果是扩展,您只需要使CONDITIONS散列更大。
答案 2 :(得分:0)
DRY恋物癖:
class Public
def not_active; [:a, :b]; end
def active; not_active.first; end
def missing_method; false; end
end
class Shared < Public
def not_active; super << :c; end
def active; raise "#{self.class.name.underscore} cannot be active"; end
end
class Private < Shared
def not_active; super << :d; end
end
state = active? ? :active : (not_active? ? :not_active : :missing_method)
(Private.new.send(state) if private?)||
(Shared.new.send(state) if shared?)||
(Public.new.send(state) if public?)||raise("not recognized")
答案 3 :(得分:0)
如何使用Array?
actions = [
['[:a, :b, :c, :d]', 'raise "private cannot be active"'],
['[:a, :b, :c]', 'raise "shared cannot be active"'],
['[:a, :b]', '[:a]']
]
x = [:private?, :shared?, :public?].find_index { |i| send(i) }
y = [:not_active?, :active?].find_index { |i| send(i) }
if x and y
eval(actions[x][y])
else
raise "not recognized"
end