Merge pull request #2 from johnbintz/decorates_with
Select the decorator to use for each @ivar
This commit is contained in:
commit
5685bbe0a1
|
@ -13,10 +13,27 @@ require 'active_support/core_ext/class/attribute'
|
|||
#
|
||||
# @thing_1 and @thing_2 will be decorated right before a rendering occurs.
|
||||
#
|
||||
# You can also specify the decorator you wish to use for a particular instance variable:
|
||||
#
|
||||
# class StuffController < ApplicationController
|
||||
# include DecoratesBeforeRendering
|
||||
#
|
||||
# decorates :thing_1, :with => ThingListDecorator
|
||||
# decorates :thing_2
|
||||
# end
|
||||
#
|
||||
# @thing_1 will be a ThingListDecorator (or contain them), and @thing_2 will be a Thing2Decorator.
|
||||
#
|
||||
module DecoratesBeforeRendering
|
||||
module ClassMethods
|
||||
def decorates(*unsigiled_ivar_names)
|
||||
self.__ivars_to_decorate__ = unsigiled_ivar_names.map { |i| "@#{i}" }
|
||||
options = {}
|
||||
if unsigiled_ivar_names.last.instance_of?(::Hash)
|
||||
options = unsigiled_ivar_names.pop
|
||||
end
|
||||
|
||||
self.__ivars_to_decorate__ ||= []
|
||||
self.__ivars_to_decorate__ << [ unsigiled_ivar_names.map { |i| "@#{i}" }, options ]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -30,16 +47,20 @@ private
|
|||
def __decorate_ivars__
|
||||
ivars_to_decorate = self.class.__ivars_to_decorate__
|
||||
|
||||
return if ivars_to_decorate.nil?
|
||||
return if ivars_to_decorate.nil? or ivars_to_decorate.empty?
|
||||
|
||||
ivars_to_decorate.each do |ivar_name|
|
||||
ivar = instance_variable_get(ivar_name)
|
||||
instance_variable_set(ivar_name, __decorator_for__(ivar)) unless ivar.nil?
|
||||
ivars_to_decorate.each do |ivar_names, options|
|
||||
ivar_names.each do |ivar_name|
|
||||
if ivar = instance_variable_get(ivar_name)
|
||||
decorator = (options[:with] || __decorator_for__(ivar)).decorate(ivar)
|
||||
instance_variable_set(ivar_name, decorator)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def __decorator_for__(ivar)
|
||||
__decorator_name_for__(ivar).constantize.decorate(ivar)
|
||||
__decorator_name_for__(ivar).constantize
|
||||
end
|
||||
|
||||
def __decorator_name_for__(ivar)
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
require_relative '../lib/decorates_before_rendering'
|
||||
|
||||
class MyCompletelyFakeModelDecorator; end
|
||||
class MyOtherCompletelyFakeModelDecorator; end
|
||||
|
||||
describe DecoratesBeforeRendering do
|
||||
# NOTE: these are married together, so they're tested together.
|
||||
describe '::decorates + #render' do
|
||||
let(:sentinel) { double(:sentinel) }
|
||||
let(:ivar) { double('@ivar') }
|
||||
let(:ivars) { double('@ivars') }
|
||||
|
||||
# NOTE: This superclass is here so we know that the correct render gets
|
||||
# called. It can't be defined in the subclass, or else that one
|
||||
|
@ -27,16 +29,17 @@ describe DecoratesBeforeRendering do
|
|||
Class.new(superclass) do
|
||||
include DecoratesBeforeRendering
|
||||
|
||||
attr_reader :ivar
|
||||
attr_reader :ivar, :ivars
|
||||
|
||||
def initialize(sentinel, ivar)
|
||||
def initialize(sentinel, ivar, ivars = nil)
|
||||
super(sentinel)
|
||||
|
||||
@ivar = ivar
|
||||
@ivars = ivars
|
||||
end
|
||||
end
|
||||
end
|
||||
let(:instance) { klass.new(sentinel, ivar) }
|
||||
let(:instance) { klass.new(sentinel, ivar, ivars) }
|
||||
let(:args) { double('*args') }
|
||||
|
||||
context "no ivars" do
|
||||
|
@ -92,5 +95,19 @@ describe DecoratesBeforeRendering do
|
|||
subclass_instance.render(args)
|
||||
end
|
||||
end
|
||||
|
||||
context "Specify a different decorator class for an automatic decorator" do
|
||||
it "should function correctly" do
|
||||
klass.decorates(:ivars, :with => MyOtherCompletelyFakeModelDecorator)
|
||||
klass.decorates(:ivar)
|
||||
subclass_instance = Class.new(klass).new(sentinel, ivar, ivars)
|
||||
sentinel.should_receive(:render).with(args)
|
||||
MyOtherCompletelyFakeModelDecorator.should_receive(:decorate).with(ivars)
|
||||
MyCompletelyFakeModelDecorator.should_receive(:decorate).with(ivar)
|
||||
ivar.stub_chain(:class, :model_name => 'MyCompletelyFakeModel')
|
||||
subclass_instance.render(args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue