Class: Draper::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/draper/base.rb

Constant Summary

DEFAULT_DENIED =
Object.new.methods << :method_missing
FORCED_PROXY =
[:to_param]

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Base) initialize(input, context = nil)

Initialize a new decorator instance by passing in an instance of the source class. Pass in an optional context is stored for later use.

Parameters:

  • instance (Object)

    to wrap

  • context (Object) (defaults to: nil)

    (optional)



17
18
19
20
21
22
23
# File 'lib/draper/base.rb', line 17

def initialize(input, context = nil)
  input.inspect # forces evaluation of a lazy query from AR
  self.class.model_class = input.class if model_class.nil?
  @model = input
  self.context = context
  build_methods
end

Instance Attribute Details

- (Object) context

Returns the value of attribute context



5
6
7
# File 'lib/draper/base.rb', line 5

def context
  @context
end

- (Object) model

Returns the value of attribute model



5
6
7
# File 'lib/draper/base.rb', line 5

def model
  @model
end

Class Method Details

+ (Object) allows(*input_allows)

Specifies a white list of methods which may be proxied to to the wrapped object. When allows is used, only the listed methods and methods defined in the decorator itself will be available.

Do not use both .allows and .denies together, either write a whitelist with .allows or a blacklist with .denies

Parameters:

  • methods (Symbols*)

    to allow like :find, :find_by_name

Raises:

  • (ArgumentError)


73
74
75
76
77
# File 'lib/draper/base.rb', line 73

def self.allows(*input_allows)
  raise ArgumentError, "Specify at least one method (as a symbol) to allow when using allows" if input_allows.empty?
  raise ArgumentError, "Use either 'allows' or 'denies', but not both." unless (self.denied == DEFAULT_DENIED)
  self.allowed = input_allows
end

+ (Object) decorate(input, context = nil)

Initialize a new decorator instance by passing in an instance of the source class. Pass in an optional context is stored for later use.

When passing in a single object, using .decorate is identical to calling .new. However, .decorate can also accept a collection and return a collection of individually decorated objects.

Parameters:

  • instance(s) (Object)

    to wrap

  • context (Object) (defaults to: nil)

    (optional)



90
91
92
# File 'lib/draper/base.rb', line 90

def self.decorate(input, context = nil)
  input.respond_to?(:each) ? input.map{|i| new(i, context)} : new(input, context)
end

+ (Object) decorates(input)

Typically called within a decorator definition, this method specifies the name of the wrapped object class.

For instance, a ProductDecorator class might call decorates :product

But they don't have to match in name, so a EmployeeDecorator class could call decorates :person to wrap instances of Person

This is primarilly set so the .find method knows which class to query.

Parameters:

  • class_name (Symbol)

    snakecase name of the decorated class, like :product



46
47
48
49
# File 'lib/draper/base.rb', line 46

def self.decorates(input)
  self.model_class = input.to_s.camelize.constantize
  model_class.send :include, Draper::ModelSupport
end

+ (Object) denies(*input_denied)

Specifies a black list of methods which may not be proxied to to the wrapped object.

Do not use both .allows and .denies together, either write a whitelist with .allows or a blacklist with .denies

Parameters:

  • methods (Symbols*)

    to deny like :find, :find_by_name

Raises:

  • (ArgumentError)


58
59
60
61
62
# File 'lib/draper/base.rb', line 58

def self.denies(*input_denied)
  raise ArgumentError, "Specify at least one method (as a symbol) to exclude when using denies" if input_denied.empty?
  raise ArgumentError, "Use either 'allows' or 'denies', but not both." if self.allowed?
  self.denied += input_denied
end

+ (Object) find(input)

Proxies to the class specified by decorates to automatically lookup an object in the database and decorate it.

Parameters:

  • id (Symbol or String)

    to lookup

Returns:

  • (Object)

    instance of this decorator class



30
31
32
# File 'lib/draper/base.rb', line 30

def self.find(input)
  self.new(model_class.find(input))
end

+ (Object) lazy_helpers

Calling lazy_helpers will make the built-in and user-defined Rails helpers accessible as class methods in the decorator without using the h. or helpers. proxy.

The drawback is that you dump many methods into your decorator's namespace and collisions could create unexpected results.



109
110
111
# File 'lib/draper/base.rb', line 109

def self.lazy_helpers
  self.send(:include, Draper::LazyHelpers)
end

+ (ActiveModel::Name) model_name

Use primarily by form_for, this returns an instance of ActiveModel::Name set to the wrapped model's class name

Returns:

  • (ActiveModel::Name)

    model_name



117
118
119
# File 'lib/draper/base.rb', line 117

def self.model_name
  ActiveModel::Name.new(model_class)
end

Instance Method Details

- (Object) helpers Also known as: h

Access the helpers proxy to call built-in and user-defined Rails helpers. Aliased to .h for convinience.

Returns:

  • (Object)

    proxy



98
99
100
# File 'lib/draper/base.rb', line 98

def helpers
  @helpers ||= ApplicationController::all_helpers
end

- (Object) to_model

Fetch the original wrapped model.

Returns:

  • (Object)

    original_model



124
125
126
# File 'lib/draper/base.rb', line 124

def to_model
  @model
end