Rails AntiPatterns书 - 对构图的怀疑

时间:2012-01-25 09:50:18

标签: ruby-on-rails composition anti-patterns

我正在阅读Rails AntiPatterns书,我很享受。在某一点上,作者谈到了合成的优点,并给出了一个例子,其中 Order 类赋予转换(到其他格式)到另一个类的责任,称为 OrderConverter 。这些类定义为:

class Order < ActiveRecord::Base
    def converter
        OrderConverter.new(self)
    end
end

class OrderConverter
    attr_reader :order
    def initialize(order)
        @order = order
    end
    def to_xml
        # ...
    end
    def to_json
        # ...
    end
    ...
end

然后作者说:“通过这种方式,您可以将转换方法放在一个单独且易于测试的类中。转换订单的PDF版本现在只需要调用以下内容:

@order.converter.to_pdf

关于这一点,我的问题是:

  • 为什么您认为订单对象前面有@?不应该创建为:

    order = Order.new

然后转换:

order.converter.to_pdf 
  • 为什么OrderConverter中需要attr_reader :order行?我们可以从 OrderConverter 对象访问订单吗?是否需要能够做到 order.converter.to_pdf?如果没有 attr_reader ,我们可以做到这一点吗?

2 个答案:

答案 0 :(得分:2)

变量前面的@使其成为实例变量。如果它不存在,变量就只是一个局部变量。我猜这是因为这是一本关于Rails的书,它假设这段代码在控制器中。控制器希望跨方法共享或在其视图中公开的变量需要是实例变量。如果是这种情况,@order可能是通过请求中的参数或从数据库中提取的值创建的。

这可能不是那么重要,他的例子和你的例子都有用 - 我认为作者只是展示了对OrderConverter的调用是什么样的,并忽略了Order对象的方式得到了。

attr_reader :order@order中的OrderConverter实例变量创建了一个“getter”方法 - to_pdf不需要它 - 它将用于获取{{1}通过Order退出OrderConverter。我认为到目前为止您没有需要在代码中使用此代码,但可能稍后需要它。

答案 1 :(得分:2)

Order的实例传递给initialize方法并存储为实例变量(使用@ syntax:@order)。这样,可以从转换器中的其他方法访问此变量(该变量具有实例范围):

class OrderConverter
  def to_pdf
    @order.items.each do |item|
       # Write the order items to the PDF
    end
  end
end

attr_reader不是严格要求的,但是从其他方法访问Order对象的便捷方式:

class OrderConverter
  def to_pdf
    order.items.each do |item|
       # Write the order items to the PDF
    end
  end
end

它还允许您从任何转换器实例中获取对订单的引用:

converter.order