draper/lib/draper/decorated_enumerable_proxy.rb

91 lines
2.7 KiB
Ruby

require 'active_support/core_ext/object/blank'
module Draper
class DecoratedEnumerableProxy
include Enumerable
delegate :as_json, :collect, :map, :each, :[], :all?, :include?, :first, :last, :shift, :in_groups_of, :to => :decorated_collection
# Initialize a new collection decorator instance by passing in
# an instance of a collection. Pass in an optional
# context into the options hash is stored for later use.
#
#
# @param [Object] instances to wrap
# @param [Hash] options (optional)
# @option options [Class] :class The decorator class to use
# for each item in the collection.
# @option options all other options are passed to Decorator
# class for each item.
def self.decorate(collection, options = {})
new( collection, discern_class_from_my_class(options.delete(:class)), options)
end
class << self
alias_method :decorates, :decorate
end
def initialize(collection, klass, options = {})
@wrapped_collection, @klass, @options = collection, klass, options
end
def decorated_collection
@decorated_collection ||= @wrapped_collection.collect { |member| @klass.decorate(member, @options) }
end
alias_method :to_ary, :decorated_collection
def find(ifnone_or_id = nil, &blk)
if block_given?
source.find(ifnone_or_id, &blk)
else
obj = decorated_collection.first
return nil if obj.blank?
obj.class.find(ifnone_or_id)
end
end
def method_missing (method, *args, &block)
@wrapped_collection.send(method, *args, &block)
end
def respond_to?(method, include_private = false)
super || @wrapped_collection.respond_to?(method, include_private)
end
def kind_of?(klass)
@wrapped_collection.kind_of?(klass) || super
end
alias :is_a? :kind_of?
def ==(other)
@wrapped_collection == (other.respond_to?(:source) ? other.source : other)
end
def to_s
"#<DecoratedEnumerableProxy of #{@klass} for #{@wrapped_collection.inspect}>"
end
def context=(input)
self.map { |member| member.context = input }
end
def source
@wrapped_collection
end
alias_method :to_source, :source
def helpers
Draper::ViewContext.current
end
alias_method :h, :helpers
private
def self.discern_class_from_my_class default_class
return default_class if default_class
name = self.to_s.gsub("Decorator", "")
"#{name.singularize}Decorator".constantize
rescue NameError
raise NameError("You must supply a class (as the klass option) for the members of your collection or the class must be inferable from the name of this class ('#{new.class}')")
end
end
end