在ruby中支持双向语法的问题 [英] Problem Supporting two way syntax in ruby

查看:67
本文介绍了在ruby中支持双向语法的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class Office 

我有一种情况,我需要调用这样的东西:

attr_accessor:workers,:id

def初始化
@workers = []
结束

def worker 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)如果worker.respond_to?(k)
结束
self.workers<<工人
结束

结束

工人阶级

  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<(lt)(worker)
如果工人
type = worker.type
resp = Worker.post(/ office /#{office_id} /workers.json,:worker => {:type => type} )
调试器
@id = resp.id
resp.to_hash.each_pair do | k,v |
self.send(#{k} =,v)如果self.respond_to?(k)
结束
调试器
返回自我
结束
结束

我可以很好地做到这一点

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

但是我需要做的和上面所做的一样,如下所示。在此之前,我需要更改Office的初始化方法以激发工人实例的 def<(worker)方法。

  class Office 
...
def初始化
@workers = Worker.new
@ workers.office_id = self.id
结束


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

现在的问题是,稍后的实现会创建2个工人实例??

解决方案

我不完全确定,但是我想你想要这样:

  class Office 

attr_accessor:workers,:id

def初始化
@workers = []
end

alias_method:workers,:return_worker_array

def worker worker
除非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)如果worker.respond_to?(k)
return_worker_array<< worker
end
end

end

通过这种方式,您可以完全清除工人#< ,您也应该删除该行

  office.workers = self 

in Worker#initialize 因为 office.workers 应该是一个数组。改变一个属性的类型(duck-typing会好)是一个坏主意,因为它很可能会失去对当前状态的跟踪,并且迟早会出错。



要遵循分离问题,我建议仅在 Office 中完成对 workers 的全部管理c $ c>,否则它会过于混淆得太快,从长远来看很难维持。

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

解决方案

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.

这篇关于在ruby中支持双向语法的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆