开发者

Problem Supporting two way syntax in ruby

I have a situation where i need to call something like this :

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

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 !@office_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

I can do something like this very well

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

But i need to do same what i have done above like the following. Before that, i need to change the initialize method of Office to fire up the def <&l开发者_C百科t;(worker) method of the worker instance.

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


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

Now the problem is, the later implementation creates 2 instances of the worker??


I'm not entirely sure, but I suppose you'd like to have this:

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

This way you can get rid of Worker#<< entirely and you should also remove the line

office.workers = self

in Worker#initialize since office.workers is supposed to be an array. It's a bad idea to change the type of an attribute (duck-typing would be OK) back and forth because it's likely you lose track of the current state and you will run into errors sooner or later.

To follow "Separation of Concerns", I would recommend to do the entire management of workers solely in Office, otherwise it gets too confusing too quickly and will be much harder to maintain on the long run.


I'm not 100% certain why you aren't getting an error here, but since Office#workers last line is self.workers << worker, you are adding the new worker created in Office#workers (made on the 3rd line of the method), and then returning the workers object, which then gets #<< called again on it with the new worker created outside of the method

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜