デフォルトではこれを直接行うことはできませんが、Rubyを使用してそのようなものを構築することはできますmethod_missing
。
2つの解決策:
解決策1-ラッパークラスを使用する
このクラスMArray
をmulti-assign-arrayと呼びます。
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>]