Automatically decorate associations with decorates_association

This commit is contained in:
Michael Fairley 2011-11-18 15:24:03 -08:00
parent 02ed89437e
commit 1580baa287
3 changed files with 49 additions and 0 deletions

View File

@ -53,6 +53,22 @@ module Draper
define_method(input){ @model }
end
# Typically called withing a decorator definition, this method causes
# the assocation to be decorated when it is retrieved.
#
# @param [Symbol] name of association to decorate, like `:products`
def self.decorates_association(association_symbol)
define_method(association_symbol) do
orig_association = model.send(association_symbol)
return nil if orig_association.nil?
if orig_association.respond_to? :proxy_reflection # The association is a collection
"#{orig_association.proxy_reflection.klass}Decorator".constantize.decorate(orig_association)
else
"#{orig_association.class}Decorator".constantize.decorate(orig_association)
end
end
end
# Specifies a black list of methods which may *not* be proxied to
# to the wrapped object.
#

View File

@ -74,6 +74,27 @@ describe Draper::Base do
end
end
context(".decorates_association") do
context "for collection associations" do
before(:each){ subject.class_eval{ decorates_association :similar_products } }
it "causes the association's method to return a collection of wrapped objects" do
subject.similar_products.each{ |decorated| decorated.should be_instance_of(ProductDecorator) }
end
end
context "for a singular association" do
before(:each){ subject.class_eval{ decorates_association :previous_version } }
it "causes the association's method to return a single wrapped object if the association is singular" do
subject.previous_version.should be_instance_of(ProductDecorator)
end
it "causes the association's method to return nil if the association is nil" do
source.stub(:previous_version){ nil }
subject.previous_version.should be_nil
end
end
end
context(".model / .to_model") do
it "should return the wrapped object" do
subject.to_model.should == source

View File

@ -44,4 +44,16 @@ class Product < ActiveRecord::Base
def block
yield
end
def similar_products
result = [Product.new, Product.new]
def result.proxy_reflection
OpenStruct.new(:klass => Product)
end
result
end
def previous_version
Product.new
end
end