Skip to content

Commit

Permalink
Rename source to object
Browse files Browse the repository at this point in the history
Closes #501
  • Loading branch information
haines committed Apr 30, 2013
1 parent 807a50c commit 4b933ef
Show file tree
Hide file tree
Showing 21 changed files with 228 additions and 206 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class ArticleDecorator < Draper::Decorator
end

def published_at
source.published_at.strftime("%A, %B %e")
object.published_at.strftime("%A, %B %e")
end
end
```
Expand Down Expand Up @@ -173,12 +173,12 @@ never have to type `h.` again.

When writing decorator methods you'll usually need to access the wrapped model.
While you may choose to use delegation ([covered below](#delegating-methods))
for convenience, you can always use the `source` (or its alias `model`):
for convenience, you can always use the `object` (or its alias `model`):

```ruby
class ArticleDecorator < Draper::Decorator
def published_at
source.published_at.strftime("%A, %B %e")
object.published_at.strftime("%A, %B %e")
end
end
```
Expand Down Expand Up @@ -250,7 +250,7 @@ Some pagination gems add methods to `ActiveRecord::Relation`. For example,
[Kaminari](https://github.com/amatsuda/kaminari)'s `paginate` helper method
requires the collection to implement `current_page`, `total_pages`, and
`limit_value`. To expose these on a collection decorator, you can delegate to
the `source`:
the `object`:

```ruby
class PaginatingDecorator < Draper::CollectionDecorator
Expand All @@ -260,7 +260,7 @@ end

The `delegate` method used here is the same as that added by [Active
Support](http://api.rubyonrails.org/classes/Module.html#method-i-delegate),
except that the `:to` option is not required; it defaults to `:source` when
except that the `:to` option is not required; it defaults to `:object` when
omitted.

[will_paginate](https://github.com/mislav/will_paginate) needs you to
Expand Down Expand Up @@ -444,7 +444,7 @@ end
### Delegating Methods

When your decorator calls `delegate_all`, any method called on the decorator not
defined in the decorator itself will be delegated to the decorated source. This
defined in the decorator itself will be delegated to the decorated object. This
is a very permissive interface.

If you want to strictly control which methods are called within views, you can
Expand All @@ -456,8 +456,8 @@ class ArticleDecorator < Draper::Decorator
end
```

We omit the `:to` argument here as it defaults to the `source` object. You could
choose to delegate methods to other places like this:
We omit the `:to` argument here as it defaults to the `object` being decorated.
You could choose to delegate methods to other places like this:

```ruby
class ArticleDecorator < Draper::Decorator
Expand Down
2 changes: 1 addition & 1 deletion lib/draper/automatic_delegation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def respond_to_missing?(method, include_private = false)

# @private
def delegatable?(method)
source.respond_to?(method)
object.respond_to?(method)
end

module ClassMethods
Expand Down
14 changes: 7 additions & 7 deletions lib/draper/collection_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ class CollectionDecorator
array_methods = Array.instance_methods - Object.instance_methods
delegate :==, :as_json, *array_methods, to: :decorated_collection

# @param [Enumerable] source
# @param [Enumerable] object
# collection to decorate.
# @option options [Class, nil] :with (nil)
# the decorator class used to decorate each item. When `nil`, each item's
# {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(source, options = {})
def initialize(object, options = {})
options.assert_valid_keys(:with, :context)
@source = source
@object = object
@decorator_class = options[:with]
@context = options.fetch(:context, {})
end
Expand All @@ -36,7 +36,7 @@ class << self

# @return [Array] the decorated items.
def decorated_collection
@decorated_collection ||= source.map{|item| decorate_item(item)}
@decorated_collection ||= object.map{|item| decorate_item(item)}
end

# Delegated to the decorated collection when using the block form
Expand All @@ -47,12 +47,12 @@ def find(*args, &block)
decorated_collection.find(*args, &block)
else
ActiveSupport::Deprecation.warn("Using ActiveRecord's `find` on a CollectionDecorator is deprecated. Call `find` on a model, and then decorate the result", caller)
decorate_item(source.find(*args))
decorate_item(object.find(*args))
end
end

def to_s
"#<#{self.class.name} of #{decorator_class || "inferred decorators"} for #{source.inspect}>"
"#<#{self.class.name} of #{decorator_class || "inferred decorators"} for #{object.inspect}>"
end

def context=(value)
Expand Down Expand Up @@ -80,7 +80,7 @@ def replace(other)
protected

# @return the collection being decorated.
attr_reader :source
attr_reader :object

# Decorates the given item.
def decorate_item(item)
Expand Down
2 changes: 1 addition & 1 deletion lib/draper/decoratable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def decorator_class
#
# @return [Boolean]
def ===(other)
super || (other.respond_to?(:source) && super(other.source))
super || (other.respond_to?(:object) && super(other.object))
end

end
Expand Down
2 changes: 1 addition & 1 deletion lib/draper/decoratable/equality.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def self.test(object, other)
# @private
def self.test_for_decorator(object, other)
other.respond_to?(:decorated?) && other.decorated? &&
other.respond_to?(:source) && test(object, other.source)
other.respond_to?(:object) && test(object, other.object)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/draper/decorated_association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def call
attr_reader :factory, :owner, :association, :scope

def decorate
associated = owner.source.send(association)
associated = owner.object.send(association)
associated = associated.send(scope) if scope

@decorated = factory.decorate(associated, context_args: owner.context)
Expand Down
47 changes: 24 additions & 23 deletions lib/draper/decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ class Decorator
include ActiveModel::Serializers::Xml

# @return the object being decorated.
attr_reader :source
alias_method :model, :source
alias_method :to_source, :source
attr_reader :object
alias_method :model, :object
alias_method :source, :object # TODO: deprecate this
alias_method :to_source, :object # TODO: deprecate this

# @return [Hash] extra data to be used in user-defined methods.
attr_accessor :context
Expand All @@ -21,16 +22,16 @@ class Decorator
# decorator to an instance of itself will create a decorator with the same
# source as the original, rather than redecorating the other instance.
#
# @param [Object] source
# @param [Object] object
# object to decorate.
# @option options [Hash] :context ({})
# extra data to be stored in the decorator and used in user-defined
# methods.
def initialize(source, options = {})
def initialize(object, options = {})
options.assert_valid_keys(:context)
@source = source
@object = object
@context = options.fetch(:context, {})
handle_multiple_decoration(options) if source.instance_of?(self.class)
handle_multiple_decoration(options) if object.instance_of?(self.class)
end

class << self
Expand Down Expand Up @@ -126,22 +127,22 @@ def self.decorates_associations(*associations)
# maps to `ProductsDecorator`), but otherwise defaults to
# {Draper::CollectionDecorator}.
#
# @param [Object] source
# @param [Object] object
# collection to decorate.
# @option options [Class, nil] :with (self)
# the decorator class used to decorate each item. When `nil`, it is
# inferred from each item.
# @option options [Hash] :context
# extra data to be stored in the collection decorator.
def self.decorate_collection(source, options = {})
def self.decorate_collection(object, options = {})
options.assert_valid_keys(:with, :context)
collection_decorator_class.new(source, options.reverse_merge(with: self))
collection_decorator_class.new(object, options.reverse_merge(with: self))
end

# @return [Array<Class>] the list of decorators that have been applied to
# the object.
def applied_decorators
chain = source.respond_to?(:applied_decorators) ? source.applied_decorators : []
chain = object.respond_to?(:applied_decorators) ? object.applied_decorators : []
chain << self.class
end

Expand All @@ -159,29 +160,29 @@ def decorated?
true
end

# Compares the source with a possibly-decorated object.
# Compares the source object with a possibly-decorated object.
#
# @return [Boolean]
def ==(other)
Draper::Decoratable::Equality.test(source, other)
Draper::Decoratable::Equality.test(object, other)
end

# Checks if `self.kind_of?(klass)` or `source.kind_of?(klass)`
# Checks if `self.kind_of?(klass)` or `object.kind_of?(klass)`
#
# @param [Class] klass
def kind_of?(klass)
super || source.kind_of?(klass)
super || object.kind_of?(klass)
end
alias_method :is_a?, :kind_of?

# Checks if `self.instance_of?(klass)` or `source.instance_of?(klass)`
# Checks if `self.instance_of?(klass)` or `object.instance_of?(klass)`
#
# @param [Class] klass
def instance_of?(klass)
super || source.instance_of?(klass)
super || object.instance_of?(klass)
end

# In case source is nil
# In case object is nil
delegate :present?, :blank?

# ActiveModel compatibility
Expand All @@ -190,10 +191,10 @@ def to_model
self
end

# @return [Hash] the source's attributes, sliced to only include those
# @return [Hash] the object's attributes, sliced to only include those
# implemented by the decorator.
def attributes
source.attributes.select {|attribute, _| respond_to?(attribute) }
object.attributes.select {|attribute, _| respond_to?(attribute) }
end

# ActiveModel compatibility
Expand Down Expand Up @@ -233,9 +234,9 @@ def self.collection_decorator_name
end

def handle_multiple_decoration(options)
if source.applied_decorators.last == self.class
@context = source.context unless options.has_key?(:context)
@source = source.source
if object.applied_decorators.last == self.class
@context = object.context unless options.has_key?(:context)
@object = object.object
else
warn "Reapplying #{self.class} decorator to target that is already decorated with it. Call stack:\n#{caller(1).join("\n")}"
end
Expand Down
4 changes: 2 additions & 2 deletions lib/draper/delegation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ module Draper
module Delegation
# @overload delegate(*methods, options = {})
# Overrides {http://api.rubyonrails.org/classes/Module.html#method-i-delegate Module.delegate}
# to make `:source` the default delegation target.
# to make `:object` the default delegation target.
#
# @return [void]
def delegate(*methods)
options = methods.extract_options!
super *methods, options.reverse_merge(to: :source)
super *methods, options.reverse_merge(to: :object)
end
end
end
30 changes: 15 additions & 15 deletions lib/draper/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ def initialize(options = {})
# Decorates an object, inferring whether to create a singular or collection
# decorator from the type of object passed.
#
# @param [Object] source
# @param [Object] object
# object to decorate.
# @option options [Hash] context
# extra data to be stored in the decorator. Overrides any context passed
# to the constructor.
# @option options [Object, Array] context_args (nil)
# argument(s) to be passed to the context proc.
# @return [Decorator, CollectionDecorator] the decorated object.
def decorate(source, options = {})
return nil if source.nil?
Worker.new(decorator_class, source).call(options.reverse_merge(default_options))
def decorate(object, options = {})
return nil if object.nil?
Worker.new(decorator_class, object).call(options.reverse_merge(default_options))
end

private
Expand All @@ -37,32 +37,32 @@ def decorate(source, options = {})

# @private
class Worker
def initialize(decorator_class, source)
def initialize(decorator_class, object)
@decorator_class = decorator_class
@source = source
@object = object
end

def call(options)
update_context options
decorator.call(source, options)
decorator.call(object, options)
end

def decorator
return decorator_method(decorator_class) if decorator_class
return source_decorator if decoratable?
return object_decorator if decoratable?
return decorator_method(Draper::CollectionDecorator) if collection?
raise Draper::UninferrableDecoratorError.new(source.class)
raise Draper::UninferrableDecoratorError.new(object.class)
end

private

attr_reader :decorator_class, :source
attr_reader :decorator_class, :object

def source_decorator
def object_decorator
if collection?
->(source, options) { source.decorator_class.decorate_collection(source, options.reverse_merge(with: nil))}
->(object, options) { object.decorator_class.decorate_collection(object, options.reverse_merge(with: nil))}
else
->(source, options) { source.decorate(options) }
->(object, options) { object.decorate(options) }
end
end

Expand All @@ -75,11 +75,11 @@ def decorator_method(klass)
end

def collection?
source.respond_to?(:first)
object.respond_to?(:first)
end

def decoratable?
source.respond_to?(:decorate)
object.respond_to?(:decorate)
end

def update_context(options)
Expand Down
2 changes: 1 addition & 1 deletion lib/generators/decorator/templates/decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class <%= class_name %>
#
# def created_at
# helpers.content_tag :span, class: 'time' do
# source.created_at.strftime("%a %m/%d/%y")
# object.created_at.strftime("%a %m/%d/%y")
# end
# end
Expand Down
Loading

0 comments on commit 4b933ef

Please sign in to comment.