draper/lib/draper/collection_decorator.rb

93 lines
2.4 KiB
Ruby
Raw Permalink Normal View History

2011-10-20 05:43:48 +00:00
module Draper
class CollectionDecorator
2011-10-20 05:43:48 +00:00
include Enumerable
include Draper::ViewHelpers
include Draper::QueryMethods
extend Draper::Delegation
2011-10-20 05:43:48 +00:00
# @return the collection being decorated.
attr_reader :object
# @return [Class] the decorator class used to decorate each item, as set by
# {#initialize}.
attr_reader :decorator_class
2013-01-07 16:33:24 +00:00
# @return [Hash] extra data to be used in user-defined methods, and passed
# to each item's decorator.
2012-12-19 21:48:37 +00:00
attr_accessor :context
array_methods = Array.instance_methods - Object.instance_methods
delegate :==, :as_json, *array_methods, to: :decorated_collection
# @param [Enumerable] object
2013-01-07 16:33:24 +00:00
# collection to decorate.
# @option options [Class, nil] :with (nil)
# the decorator class used to decorate each item. When `nil`, each item's
2013-01-07 16:33:24 +00:00
# {Decoratable#decorate decorate} method will be used.
# @option options [Hash] :context ({})
# extra data to be stored in the collection decorator and used in
# user-defined methods, and passed to each item's decorator.
def initialize(object, options = {})
options.assert_valid_keys(:with, :context)
@object = object
2012-12-19 21:45:22 +00:00
@decorator_class = options[:with]
2012-12-13 06:38:15 +00:00
@context = options.fetch(:context, {})
2012-08-30 13:00:37 +00:00
end
class << self
alias :decorate :new
2011-10-20 05:43:48 +00:00
end
2013-01-07 16:33:24 +00:00
# @return [Array] the decorated items.
def decorated_collection
@decorated_collection ||= object.map{|item| decorate_item(item)}
2011-10-20 05:43:48 +00:00
end
delegate :find, to: :decorated_collection
2011-10-20 05:43:48 +00:00
def to_s
"#<#{self.class.name} of #{decorator_class || "inferred decorators"} for #{object.inspect}>"
2011-10-20 05:43:48 +00:00
end
2012-05-12 08:40:04 +00:00
2012-12-13 06:38:15 +00:00
def context=(value)
@context = value
each {|item| item.context = value } if @decorated_collection
2012-05-08 15:44:50 +00:00
end
# @return [true]
def decorated?
true
end
alias :decorated_with? :instance_of?
def kind_of?(klass)
decorated_collection.kind_of?(klass) || super
end
2013-03-11 08:19:00 +00:00
alias_method :is_a?, :kind_of?
def replace(other)
decorated_collection.replace(other)
self
end
2012-10-31 23:19:33 +00:00
protected
2013-01-07 16:33:24 +00:00
# Decorates the given item.
def decorate_item(item)
item_decorator.call(item, context: context)
end
2013-01-07 16:33:24 +00:00
private
2012-12-19 21:45:22 +00:00
def item_decorator
if decorator_class
2012-12-19 21:45:22 +00:00
decorator_class.method(:decorate)
else
2012-12-19 21:45:22 +00:00
->(item, options) { item.decorate(options) }
end
end
2011-10-20 05:43:48 +00:00
end
end