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
精彩评论