2011-06-06 45 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的整个管理,否则它会太快地混淆,从长远来看将更难以维护。