class A
attr_accessor :dab
....
end
现在我有一个A的实例数组,比如说
arr = [A.new, A.new, A.new]
现在我想为数组A
中存在的类arr
的所有实例设置一个值。 ruby / rails中有一个快捷方式吗?
此外,我确实A
继承自ActiveRecord::Base
我的实际需要是:
A.find_all_by_some_condition.all.dabs = 2
因此,所有找到的对象都将dab
设置为2。
这有什么捷径吗?
答案 0 :(得分:1)
要从数组中获取A类的项目,可以使用select / find_all
arr.select { |el| el.class == A }
或arr.select { |el| A === el }
虽然您希望为多个对象分配值,而不是相应的类,但要实现实际结果。 A类没有定义实际的对象,它只定义了对象在创建时使用的蓝图。所以找到一种方法来分配A的所有实例的值并不是你想要的(虽然我可能已经错过了你所要求的点)
要为一个对象数组赋值,这有效:
A.find_all_by_some_condition.each { |a| a.dab = 2 }
也许你想在那之后保存它们,现在arr.each(&:save)
可能会派上用场。如果您不知道它,请查看&符号。非常有用。
答案 1 :(得分:0)
默认情况下你不能直接这样做,但你可以使用Ruby method_missing
构建类似的东西。
两种解决方案:
解决方案1 - 使用包装类
我们将此类MArray
称为多分配数组。
class MArray
def initialize(inner_array)
@inner = inner_array
end
def method_missing(meth, value)
# Check if assignement, and if it is then run mass-assign
if meth.to_s =~ /^\w+=$/
@inner.each { |itm| itm.send(meth, value) }
else
raise ArgumentError, "MArray: not an assignment"
end
end
end
我们还需要在MArray
中添加对Array
的支持,以便进行换行。我们将方法mas
称为“质量分配”:
class Array
def mas
# Wrap MArray around self
MArray.new(self)
end
end
用法很简单:
Blob = Struct.new(:dab)
arr = [Blob.new] * 3
arr.mas.dab = 123
arr
=> [#<struct Blob dab=123>, #<struct Blob dab=123>, #<struct Blob dab=123>]
解决方案2 - 直接在Array
由于我们直接修改了method_missing
中的Array
,因此这有点“危险”。 可以创建一些奇怪的副作用(例如,如果某个其他库已经重新定义了method_missing
,或者您不小心意外调用了大量分配)。
它的工作原理是尝试检测具有复数单词的分配(以s
结尾的单词),然后触发批量分配:
class Array
def method_missing(meth, *args, &block)
# Check for plural assignment, and as an added safety check also
# see if all elements in the array support the assignment:
if meth.to_s =~ /^(\w+)s=$/ &&
self.all? { |itm| itm.respond_to?("#{$1}=") }
self.each { |itm| itm.send("#{$1}=", *args) }
else
super
end
end
end
然后用法变得比MArray
更短:
Blob = Struct.new(:dab)
arr = [Blob.new] * 3
arr.dabs = 123
arr
=> [#<struct Blob dab=123>, #<struct Blob dab=123>, #<struct Blob dab=123>]