2011-06-06 50 views
9

雙向語法我有一個情況我需要調用是這樣的:問題支持的紅寶石

class Office 

    attr_accessor :workers, :id 

    def initialize 
    @workers = [] 
    end 

    def workers worker 
    type = worker.type 
    resp = Worker.post("/office/#{@id}/workers.json", :worker => {:type => type}) 
    worker = Worker.new() 
    resp.to_hash.each_pair do |k,v| 
     worker.send("#{k}=",v) if worker.respond_to?(k) 
    end 
    self.workers << worker 
    end 

end 

Worker類

class Worker 
    attr_accessor :office_id, :type, :id 

    def initialize(options={}) 
    @office_id = options[:office].nil? ? nil : options[:office].id 
    @type = options[:type].nil? ? nil : options[:type].camelize 
    if [email protected]_id.nil? 
     resp = self.class.post("/office/#{@office_id}/workers.json", :worker => {:type => @type}) 
     @id = resp.id 
     office = options[:office] 
     office.workers = self 
    end 
    end 

    def <<(worker) 
    if worker 
     type = worker.type 
     resp = Worker.post("/office/#{office_id}/workers.json", :worker => {:type => type}) 
     debugger 
     @id = resp.id 
     resp.to_hash.each_pair do |k,v| 
     self.send("#{k}=",v) if self.respond_to?(k) 
     end 
     debugger 
     return self 
    end 
    end 

我可以做這樣的事情非常好

office = Office.new() 
new_worker = Worker.new() 
office.workers new_worker 

但我需要做同樣的事情,我上面做了如下。在此之前,我需要更改Office的初始化方法以啓動工作者實例的def <<(worker)方法。

class Office 
    ... 
    def initialize 
    @workers = Worker.new 
    @workers.office_id = self.id 
    end 


office = Office.new() 
new_worker = Worker.new() 
office.workers << new_worker 

現在問題是,後面的實現創建了2個工人實例?

+0

代碼是做什麼的? – Zabba 2011-06-06 06:06:22

+3

@zabba,它在office對象的工作屬性中添加新的工作對象,而worker屬性是一個數組。 – 2011-06-06 06:08:37

+1

您是否更改了更多的代碼?事實上,office.workers << new_worker應該是一個ArgumentError,因爲office.workers是一個參數爲1的方法。 – 2011-06-06 06:10:20

回答

0

我不是100%確定你爲什麼沒有在這裏得到一個錯誤,但因爲Office#工作人員的最後一行是self.workers < <工人,你正在添加在Office#workers中創建的新工人該方法的第3行),然後返回工人對象,然後獲取#< <再次調用它在方法外創建的新工人

+2

是啊這就是爲什麼它搞砸了實施,所以任何想法如何我可以實現#<<方法,當我打電話'office.workers << new_worker',因爲我已經在'office.workers new_worker' – 2011-06-06 06:37:00

+0

我會爲屬性選擇不同的名稱,以便您可以執行'office.workers new_worker'和'office.new_worker_name << new_worker'。理想情況下,我會選擇'office.add_worker new_worker'和'office.workers << new_worker',但似乎您有遺留的代碼來支持,因此您不想更改以前的調用。 (我知道這不是你要求的,但這就是我如何做到的,如果你更好地解釋了這個情況,我可能會給出一個不同的答案) – 2011-06-06 06:53:28

+2

我只想爲後面的方法使用同樣的功能在前一個和相同的名稱完成。當我呼叫'office.workers << new_worker'時,它只會調用默認的工人屬性getter/setter。 – 2011-06-06 07:00:41

1

我不完全確定,但我想你' d喜歡有這個:

class Office 

    attr_accessor :workers, :id 

    def initialize 
    @workers = [] 
    end 

    alias_method :workers, :return_worker_array 

    def workers worker 
    unless worker 
     return_worker_array 
    else 
     type = worker.type 
     resp = Worker.post("/office/#{@id}/workers.json", :worker => {:type => type}) 
     worker = Worker.new() 
     resp.to_hash.each_pair do |k,v| 
     worker.send("#{k}=",v) if worker.respond_to?(k) 
     return_worker_array << worker 
    end 
end 

end

這樣你就可以擺脫Worker#<<完全,你也應該刪除線

office.workers = self 

Worker#initialize因爲office.workers應該是一個數組。改變一個屬性的類型(鴨子輸入會好)來回是一個壞主意,因爲它很可能失去了當前狀態的軌跡,遲早你會遇到錯誤。

要遵循「分離關注點」,我建議僅對Office進行workers的整個管理,否則它會太快地混淆,從長遠來看將更難以維護。