默认情况下你不能直接这样做,但是你可以使用 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
in的支持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
然后使用变得比 with 更短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>]