设置属性的通用方法

时间:2016-10-07 06:55:31

标签: ruby-on-rails ruby

在我的模型中,我有以下属性:is_ais_bis_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个属性,则将导致更多重复的代码。实现这一目标的正确方法是什么?

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

的TIL

答案 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

希望有所帮助!