Class: Draper::Decorator

Inherits:
Object
  • Object
show all
Extended by:
Delegation
Includes:
ActiveModel::Serialization, ActiveModel::Serializers::JSON, ActiveModel::Serializers::Xml, Compatibility::GlobalID, ViewHelpers
Defined in:
lib/draper/decorator.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Delegation

delegate

Methods included from ViewHelpers

#helpers

Constructor Details

#initialize(object, options = {}) ⇒ Decorator

Wraps an object in a new instance of the decorator.

Decorators may be applied to other decorators. However, applying a decorator to an instance of itself will create a decorator with the same source as the original, rather than redecorating the other instance.

Parameters:

  • object (Object)

    object to decorate.

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :context (Hash) — default: {}

    extra data to be stored in the decorator and used in user-defined methods.



32
33
34
35
36
37
# File 'lib/draper/decorator.rb', line 32

def initialize(object, options = {})
  options.assert_valid_keys(:context)
  @object = object
  @context = options.fetch(:context, {})
  handle_multiple_decoration(options) if object.instance_of?(self.class)
end

Instance Attribute Details

#contextHash

Returns extra data to be used in user-defined methods.

Returns:

  • (Hash)

    extra data to be used in user-defined methods.



19
20
21
# File 'lib/draper/decorator.rb', line 19

def context
  @context
end

#objectObject (readonly) Also known as: model

Returns the object being decorated.

Returns:

  • the object being decorated.



14
15
16
# File 'lib/draper/decorator.rb', line 14

def object
  @object
end

Class Method Details

.collection_decorator_classClass

Returns the class created by decorate_collection.

Returns:



228
229
230
231
232
233
# File 'lib/draper/decorator.rb', line 228

def self.collection_decorator_class
  name = collection_decorator_name
  name_constant = name&.safe_constantize

  name_constant || Draper::CollectionDecorator
end

.decorate_collection(object, options = {}) ⇒ Object

Decorates a collection of objects. The class of the collection decorator is inferred from the decorator class if possible (e.g. ProductDecorator maps to ProductsDecorator), but otherwise defaults to CollectionDecorator.

Parameters:

  • object (Object)

    collection to decorate.

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :with (Class, nil) — default: self

    the decorator class used to decorate each item. When nil, it is inferred from each item.

  • :context (Hash)

    extra data to be stored in the collection decorator.



140
141
142
143
# File 'lib/draper/decorator.rb', line 140

def self.decorate_collection(object, options = {})
  options.assert_valid_keys(:with, :context)
  collection_decorator_class.new(object, options.reverse_merge(with: self))
end

.decorates(object_class) ⇒ void

Note:

This is only necessary if you wish to proxy class methods to the source (including when using decorates_finders), and the source class cannot be inferred from the decorator class (e.g. ProductDecorator maps to Product).

This method returns an undefined value.

Sets the source class corresponding to the decorator class.

Parameters:

  • object_class (String, Symbol, Class)

    source class (or class name) that corresponds to this decorator.



60
61
62
63
# File 'lib/draper/decorator.rb', line 60

def self.decorates(object_class)
  @object_class = object_class.to_s.camelize.constantize
  alias_object_to_object_class_name
end

.decorates_association(association, options = {}) ⇒ void

This method returns an undefined value.

Automatically decorate an association.

Parameters:

  • association (Symbol)

    name of the association to decorate (e.g. :products).

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :with (Class)

    the decorator to apply to the association.

  • :scope (Symbol)

    a scope to apply when fetching the association.

  • :context (Hash, #call)

    extra data to be stored in the associated decorator. If omitted, the associated decorator's context will be the same as the parent decorator's. If a Proc is given, it will be called with the parent's context and should return a new context hash for the association.



106
107
108
109
110
111
112
# File 'lib/draper/decorator.rb', line 106

def self.decorates_association(association, options = {})
  options.assert_valid_keys(:with, :scope, :context)
  define_method(association) do
    decorated_associations[association] ||= Draper::DecoratedAssociation.new(self, association, options)
    decorated_associations[association].call
  end
end

.decorates_associations(*associations, options = {}) ⇒ void

This method returns an undefined value.

Automatically decorate multiple associations.

Parameters:

  • associations (Symbols*)

    names of the associations to decorate.

  • options (Hash) (defaults to: {})


121
122
123
124
125
126
# File 'lib/draper/decorator.rb', line 121

def self.decorates_associations(*associations)
  options = associations.extract_options!
  associations.each do |association|
    decorates_association(association, options)
  end
end

.decorates_findersvoid

This method returns an undefined value.

Automatically decorates ActiveRecord finder methods, so that you can use ProductDecorator.find(id) instead of ProductDecorator.decorate(Product.find(id)).

Finder methods are applied to the object_class.



88
89
90
# File 'lib/draper/decorator.rb', line 88

def self.decorates_finders
  extend Draper::Finders
end

.delegate_allvoid

This method returns an undefined value.

Automatically delegates instance methods to the source object. Class methods will be delegated to the object_class, if it is set.



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

def self.delegate_all
  include Draper::AutomaticDelegation
end

.object_classClass

Returns the source class corresponding to the decorator class, as set by decorates, or as inferred from the decorator class name (e.g. ProductDecorator maps to Product).

Returns:

  • (Class)

    the source class that corresponds to this decorator.



70
71
72
# File 'lib/draper/decorator.rb', line 70

def self.object_class
  @object_class ||= inferred_object_class
end

.object_class?Boolean

Checks whether this decorator class has a corresponding object_class.

Returns:

  • (Boolean)


75
76
77
78
79
# File 'lib/draper/decorator.rb', line 75

def self.object_class?
  object_class
rescue Draper::UninferrableObjectError
  false
end

Instance Method Details

#==(other) ⇒ Boolean

Compares the source object with a possibly-decorated object.

Returns:

  • (Boolean)


169
170
171
# File 'lib/draper/decorator.rb', line 169

def ==(other)
  Draper::Decoratable::Equality.test(object, other)
end

#applied_decoratorsArray<Class>

Returns the list of decorators that have been applied to the object.

Returns:

  • (Array<Class>)

    the list of decorators that have been applied to the object.



147
148
149
150
# File 'lib/draper/decorator.rb', line 147

def applied_decorators
  chain = object.respond_to?(:applied_decorators) ? object.applied_decorators : []
  chain << self.class
end

#attributesHash

implemented by the decorator.

Returns:

  • (Hash)

    the object's attributes, sliced to only include those



217
218
219
# File 'lib/draper/decorator.rb', line 217

def attributes
  object.attributes.select {|attribute, _| respond_to?(attribute) }
end

#decorated?true

Checks if this object is decorated.

Returns:

  • (true)


162
163
164
# File 'lib/draper/decorator.rb', line 162

def decorated?
  true
end

#decorated_with?(decorator_class) ⇒ Boolean

Checks if a given decorator has been applied to the object.

Parameters:

  • decorator_class (Class)

Returns:

  • (Boolean)


155
156
157
# File 'lib/draper/decorator.rb', line 155

def decorated_with?(decorator_class)
  applied_decorators.include?(decorator_class)
end

#eql?(other) ⇒ Boolean

Delegates equality to :== as expected

Returns:

  • (Boolean)


176
177
178
# File 'lib/draper/decorator.rb', line 176

def eql?(other)
  self == other
end

#hashFixnum

Returns a unique hash for a decorated object based on the decorator class and the object being decorated.

Returns:

  • (Fixnum)


184
185
186
# File 'lib/draper/decorator.rb', line 184

def hash
  self.class.hash ^ object.hash
end

#instance_of?(klass) ⇒ Boolean

Checks if self.instance_of?(klass) or object.instance_of?(klass)

Parameters:

  • klass (Class)

Returns:

  • (Boolean)


200
201
202
# File 'lib/draper/decorator.rb', line 200

def instance_of?(klass)
  super || object.instance_of?(klass)
end

#kind_of?(klass) ⇒ Boolean Also known as: is_a?

Checks if self.kind_of?(klass) or object.kind_of?(klass)

Parameters:

  • klass (Class)

Returns:

  • (Boolean)


191
192
193
# File 'lib/draper/decorator.rb', line 191

def kind_of?(klass)
  super || object.kind_of?(klass)
end