Dave Newton
Dave Newton

Reputation: 160261

How can I decorate STI models with modularized decorators using Draper?

I'm using Draper for general view-layer decorators.

I have some console-related, human-readability functionality I'd like to pull into new decorators.

My first thought was to put them in a module, e.g., Human::XxxDecorator, keeping them isolated from my normal view-layer decorators: they're just for rails c debugging/hacking/testing work.

This works fine at the top level; I can explicitly decorate a model with the namespaced decorator.

Now I need to decorate a collection of STI vehicles. I'm not sure what the best way to create vehicle-type-specific decorators in the same module of decorators, e.g., I have:

I'm not sure how to get from, e.g.,

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

to its embedded collections of vehicles, each with an appropriate decorator from the Human module. The naive approach using decorates doesn't work; I get:

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

The combination of:

is throwing things off.

Before digging into the Draper decorator inference code (I'm only assuming that's the best place to start), is this a problem that's already been solved and I'm missing something?

Upvotes: 2

Views: 1459

Answers (3)

Dan Draper
Dan Draper

Reputation: 1121

You could use constantize:

def dfleet
  dfleet_decorator_class.new(object.dfleet)
end

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

Upvotes: 1

Kerozu
Kerozu

Reputation: 673

Use decorates: . Here is an example: CLICK

Upvotes: 0

apneadiving
apneadiving

Reputation: 115541

As I wrote in comments, remove the builtin decoration of your vehicles, and code yours:

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

Hack incoming:

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

But I doubt this is clearer...

Upvotes: 4

Related Questions