2012-06-16 124 views
1
class A 
    attr_accessor :dab 
    .... 
end 

現在我有一個實例數組的許多成員,說值分配給一類

arr = [A.new, A.new, A.new] 

現在我想設置一個值,在類A目前的所有實例陣列arr。在ruby/rails中有沒有捷徑來做到這一點?

另外,我有AActiveRecord::Base

的繼承和我的實際需要是:

A.find_all_by_some_condition.all.dabs = 2 

於是,所有找到的對象將有dab設置爲2

是否有捷徑爲了這?

+0

我的第一次嘗試是向數組類添加一個'dab = value'方法,並在最後將這些代碼添加到A類的文件中。正在聰明/愚蠢的檢查dab =是否只處理A類的實例:) –

回答

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)可能會派上用場。如果你不知道它,請查看&符號。很有用。

+3

您可以使用#符號/符號/ proc來處理'#each',就像#map一樣。地圖實際上是用於轉換數據結構,而不是用於迭代。 – d11wtq

+0

非常真實的d11wtq。編輯 –

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 

我們還需要在Array添加支持MArray,使包裝就會發生。我們將調用該方法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

這由於我們直接修改Array中的method_missing,所以更加「危險」。它可能會產生一些奇怪的副作用(例如,如果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>]