如何使用Draper用模块化装饰器装饰STI模型?

时间:2014-06-16 19:14:12

标签: ruby-on-rails ruby draper

我正在使用Draper作为一般视图层装饰器。

我有一些与控制台相关的人类可读性功能,我想将其引入新的装饰器。

我的第一个想法是将它们放在一个模块中,例如Human::XxxDecorator,使它们与我的普通视图层装饰器隔离:它们仅用于rails c调试/黑客/测试工作。

这在顶级工作正常;我可以使用命名空间装饰器显式地修饰模型。

现在我需要装饰一系列STI车辆。我不确定在装饰器的相同模块中创建特定于车辆类型的装饰器的最佳方法是什么,例如,我有:

  • Human::CarDecorator
  • Human::TruckDecorator
  • Human::MotorcycleDecorator

我不知道如何从中获取,例如,

pry » dfleet = Human::FleetDecorator.new(Fleet.find(1))

到其嵌入的车辆集合中,每个车辆都有Human模块中的相应装饰器。使用decorates的天真方法不起作用;我明白了:

Draper::UninferrableDecoratorError: Could not infer a decorator for Vehicle

组合:

  • 来自特定模块的装饰器,
  • 适用于STI模型的装饰者

放弃了。

在深入研究Draper装饰器推理代码之前(我只是假设这是最好的起点),这是一个已经解决的问题而且我错过了什么?

3 个答案:

答案 0 :(得分:4)

正如我在评论中写的那样,删除你车辆的内置装饰,并编码你的:

def vehicles
  object.vehicles.map do |v|
    # logic to instantiate proper decorator
  end
end 

哈克传入:

module Human
  class FleetDecorator < Draper::Decorator
    decorates_association :vehicles, with: ::Human::VehicleDecoratorDispatcher
  end

  class VehicleDecoratorDispatcher < Draper::Decorator
    def initialize(*args)
      super
      @object = ... # here you build the proper decorator based on the rules on @object
    end

  end
end

但我怀疑这更清楚......

答案 1 :(得分:1)

您可以使用constantize:

def dfleet
  dfleet_decorator_class.new(object.dfleet)
end

def dfleet_decorator_class
  "#{object.dfleet.class}Decorator".constantize
end

答案 2 :(得分:0)

使用装饰:。以下是一个示例:CLICK