Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 <<(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??

like image 334
Manish Das Avatar asked Jun 06 '11 05:06

Manish Das


People also ask

Why does Ruby not support method overloading?

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.

Can you use || IN CASE statement Ruby?

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".

What is the difference between || and or in Ruby?

|| 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.

What does || in Ruby mean?

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.


1 Answers

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.

like image 187
emboss Avatar answered Sep 20 '22 20:09

emboss