在我的模型中,我有以下属性:is_a
,is_b
和is_c
。默认情况下,所有都为空。
我需要API来设置它们。这些属性可以严格设置为一个或组。如果我要编写API,我将在我的模型中进行以下操作:
def set_as_a # strictly a
self.update_attributes!(:is_a => true, :is_b => false, :is_c => false)
end
def set_as_b # strictly b
self.update_attributes!(:is_a => false, :is_b => true, :is_c => false)
end
... # strictly c
def set_as_a_and_b # a and b
self.update_attributes!(:is_a => true, :is_b => true, :is_c => false)
end
..... # so on
虽然这有效但看起来并不优雅。此外,如果将来如果该集合具有多于3个属性,则将导致更多重复的代码。实现这一目标的正确方法是什么?
答案 0 :(得分:4)
ViewCompat.getLayoutDirection(container)
没有定义2 ^ N个方法,只需简单的Ruby元编程。
编辑:好点,@斯特凡。EDIT2:我之前的编辑引入了一个错误。现在修好了。
EDIT3:关于class SettableAsABC
ATTRS = [:a, :b, :c]
METHOD_RE = /^set_as_([[:alnum:]]+?(?:_and_[[:alnum:]]+?)*)$/
def method_missing(name, *args)
if name.to_s =~ METHOD_RE
trues = $1.split('_and_').map(&:to_sym)
attrs = Hash[ATTRS.map { |a| ["is_#{a}".to_sym, trues.include?(a)] }]
update_attributes(attrs)
else
super
end
end
def respond_to_missing?(name, include_private = false)
!!(name =~ METHOD_RE) || super
end
end
a = SettableAsABC.new
a.set_as_a_and_c
答案 1 :(得分:1)
我可能会误解某些东西,但为什么不写一个采用params的方法?:
def set_attributes(opts = {})
update_attributes!(opts) unless opts.none?
end
# usage
set_attributes(is_a: false, is_b: true)
我想出了动态创建属性组合的方法:
attributes = %w(a b c d)
(1..attributes.size).flat_map { |size| attributes.combination(size).to_a }.each do |methods|
define_method "set_as_#{methods.join('_and_')}" do
update_attributes!(Hash[methods.map { |v| ["is_#{v}", true] }])
end
end
它将生成以下menthods:
set_as_a
set_as_b
set_as_c
set_as_d
set_as_a_and_b
set_as_a_and_c
set_as_a_and_d
set_as_b_and_c
set_as_b_and_d
set_as_c_and_d
set_as_a_and_b_and_c
set_as_a_and_b_and_d
set_as_a_and_c_and_d
set_as_b_and_c_and_d
set_as_a_and_b_and_c_and_d
答案 2 :(得分:0)
这个怎么样?
carImage
希望有所帮助!