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 <<(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??
Ruby does not support method overloading Method overloading is a feature of statically typed language in which binding of methods takes place during compile time. But Ruby being a dynamically typed language, it does not support static binding at all.
If you are eager to know how to use an OR condition in a Ruby switch case: So, in a case statement, a , is the equivalent of || in an if statement. See "How A Ruby Case Statement Works And What You Can Do With It".
|| has a higher precedence than or . So, in between the two you have other operators including ternary ( ? : ) and assignment ( = ) so which one you choose can affect the outcome of statements. Here's a ruby operator precedence table.
The || operator returns the Boolean OR of its operands. It returns a true value if either of its operands is a true value. If both operands are false values, then it returns a false value. Like && , the || operator ignores its righthand operand if its value has no impact on the value of the operation.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With