Проблема с поддержкой двухстороннего синтаксиса в ruby - PullRequest
9 голосов
/ 06 июня 2011

У меня есть ситуация, когда мне нужно позвонить примерно так:

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

Рабочий класс

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

Я могу сделать что-то подобное очень хорошо

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 экземпляра работника ??

Ответы [ 2 ]

1 голос
/ 07 июля 2011

Я не совсем уверен, но я полагаю, вы хотели бы иметь это:

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 должен быть массивом.Плохо менять тип атрибута (можно было бы набирать утку) назад и вперед, потому что, скорее всего, вы потеряете отслеживание текущего состояния и рано или поздно столкнетесь с ошибками.

Следовать«Разделение проблем», я бы порекомендовал сделать все управление workers исключительно в Office, иначе это слишком запутанно слишком быстро и будет намного сложнее поддерживать в долгосрочной перспективе.

0 голосов
/ 06 июня 2011

Я не уверен на 100%, почему вы не получаете ошибку здесь, но поскольку последняя строка Office # работников - это self.workers << работник, вы добавляете нового работника, созданного в Office # работники (сделанные на3-я строка метода), а затем возвращает рабочий объект, который затем снова вызывается # << с новым рабочим, созданным вне метода </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...