2011-10-20 05:43:48 +00:00
|
|
|
module Draper
|
2012-10-09 09:07:14 +00:00
|
|
|
class CollectionDecorator
|
2011-10-20 05:43:48 +00:00
|
|
|
include Enumerable
|
2012-10-16 14:45:09 +00:00
|
|
|
include ViewHelpers
|
2011-10-20 05:43:48 +00:00
|
|
|
|
2012-10-31 23:19:33 +00:00
|
|
|
attr_accessor :source, :options, :decorator_class
|
2012-12-13 02:52:12 +00:00
|
|
|
protected :options, :options=
|
2012-10-31 22:27:40 +00:00
|
|
|
alias_method :to_source, :source
|
|
|
|
|
2012-11-01 00:38:25 +00:00
|
|
|
delegate :as_json, *(Array.instance_methods - Object.instance_methods), to: :decorated_collection
|
2012-08-29 21:13:23 +00:00
|
|
|
|
2012-10-31 23:49:12 +00:00
|
|
|
# @param source collection to decorate
|
2012-12-13 02:52:12 +00:00
|
|
|
# @param [Hash] options (optional)
|
|
|
|
# @option options [Class, Symbol] :with the class used to decorate
|
2012-11-07 21:35:02 +00:00
|
|
|
# items, or `:infer` to call each item's `decorate` method instead
|
2012-12-13 02:52:12 +00:00
|
|
|
# @option options [Hash] :context context available to each item's decorator
|
2012-10-31 23:49:12 +00:00
|
|
|
def initialize(source, options = {})
|
|
|
|
@source = source
|
|
|
|
@decorator_class = options.delete(:with) || self.class.inferred_decorator_class
|
2012-12-13 06:01:59 +00:00
|
|
|
options.assert_valid_keys(:with, :context)
|
2012-10-31 23:49:12 +00:00
|
|
|
@options = options
|
2012-08-30 13:00:37 +00:00
|
|
|
end
|
2012-05-09 20:48:28 +00:00
|
|
|
|
2012-10-31 23:49:12 +00:00
|
|
|
class << self
|
|
|
|
alias_method :decorate, :new
|
2011-10-20 05:43:48 +00:00
|
|
|
end
|
|
|
|
|
2012-05-09 20:48:28 +00:00
|
|
|
def decorated_collection
|
2012-11-07 21:35:02 +00:00
|
|
|
@decorated_collection ||= source.collect {|item| decorate_item(item) }
|
2011-10-20 05:43:48 +00:00
|
|
|
end
|
|
|
|
|
2012-10-31 23:52:55 +00:00
|
|
|
def find(*args, &block)
|
2012-08-18 09:54:16 +00:00
|
|
|
if block_given?
|
2012-10-31 23:52:55 +00:00
|
|
|
decorated_collection.find(*args, &block)
|
2012-08-18 09:54:16 +00:00
|
|
|
else
|
2012-10-31 23:52:55 +00:00
|
|
|
decorator_class.find(*args)
|
2012-08-18 09:54:16 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-10-31 23:19:50 +00:00
|
|
|
def method_missing(method, *args, &block)
|
2012-10-31 22:27:40 +00:00
|
|
|
source.send(method, *args, &block)
|
2011-10-20 05:43:48 +00:00
|
|
|
end
|
|
|
|
|
2012-04-10 20:12:27 +00:00
|
|
|
def respond_to?(method, include_private = false)
|
2012-10-31 22:27:40 +00:00
|
|
|
super || source.respond_to?(method, include_private)
|
2011-10-20 21:22:05 +00:00
|
|
|
end
|
2012-02-13 15:24:31 +00:00
|
|
|
|
2011-12-07 15:18:06 +00:00
|
|
|
def kind_of?(klass)
|
2012-10-31 23:19:50 +00:00
|
|
|
super || source.kind_of?(klass)
|
2011-12-07 15:18:06 +00:00
|
|
|
end
|
2012-10-31 22:27:40 +00:00
|
|
|
alias_method :is_a?, :kind_of?
|
2011-10-20 21:22:05 +00:00
|
|
|
|
2011-10-27 15:42:23 +00:00
|
|
|
def ==(other)
|
2012-10-31 22:27:40 +00:00
|
|
|
source == (other.respond_to?(:source) ? other.source : other)
|
2011-10-27 15:42:23 +00:00
|
|
|
end
|
|
|
|
|
2011-10-20 05:43:48 +00:00
|
|
|
def to_s
|
2012-10-31 23:19:33 +00:00
|
|
|
"#<CollectionDecorator of #{decorator_class} for #{source.inspect}>"
|
2011-10-20 05:43:48 +00:00
|
|
|
end
|
2012-05-12 08:40:04 +00:00
|
|
|
|
2012-12-13 02:52:12 +00:00
|
|
|
# Accessor for `:context` option
|
|
|
|
def context
|
|
|
|
options.fetch(:context, {})
|
|
|
|
end
|
|
|
|
|
|
|
|
# Setter for `:context` option
|
|
|
|
def context=(input)
|
|
|
|
options[:context] = input
|
|
|
|
each {|item| item.context = input } unless respond_to?(:loaded?) && !loaded?
|
2012-05-08 15:44:50 +00:00
|
|
|
end
|
2012-01-27 19:40:49 +00:00
|
|
|
|
2012-10-31 23:19:33 +00:00
|
|
|
protected
|
2012-10-31 22:27:40 +00:00
|
|
|
|
2012-11-07 21:35:02 +00:00
|
|
|
def decorate_item(item)
|
|
|
|
if decorator_class == :infer
|
2012-12-13 02:52:12 +00:00
|
|
|
item.decorate(context: context)
|
2012-11-07 21:35:02 +00:00
|
|
|
else
|
2012-12-13 02:52:12 +00:00
|
|
|
decorator_class.decorate(item, context: context)
|
2012-11-07 21:35:02 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-10-31 23:19:33 +00:00
|
|
|
def self.inferred_decorator_class
|
2012-11-01 01:38:16 +00:00
|
|
|
decorator_name = "#{name.chomp("Decorator").singularize}Decorator"
|
|
|
|
decorator_uninferrable if decorator_name == name
|
|
|
|
|
|
|
|
decorator_name.constantize
|
|
|
|
|
2012-08-29 21:13:23 +00:00
|
|
|
rescue NameError
|
2012-11-01 01:38:16 +00:00
|
|
|
decorator_uninferrable
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.decorator_uninferrable
|
2012-11-01 00:16:09 +00:00
|
|
|
raise Draper::UninferrableDecoratorError.new(self)
|
2012-08-29 21:13:23 +00:00
|
|
|
end
|
2011-10-20 05:43:48 +00:00
|
|
|
end
|
2011-10-20 21:22:05 +00:00
|
|
|
end
|