Cleanup
This commit is contained in:
parent
bd1caf1976
commit
a0d9c13772
|
@ -1,9 +1,9 @@
|
||||||
module Draper
|
module Draper
|
||||||
class Base
|
class Base
|
||||||
require 'active_support/core_ext/class/attribute'
|
require 'active_support/core_ext/class/attribute'
|
||||||
class_attribute :denied, :allowed, :model_class
|
class_attribute :denied, :allowed, :model_class
|
||||||
attr_accessor :model
|
attr_accessor :model
|
||||||
|
|
||||||
DEFAULT_DENIED = Object.new.methods << :method_missing
|
DEFAULT_DENIED = Object.new.methods << :method_missing
|
||||||
FORCED_PROXY = [:to_param]
|
FORCED_PROXY = [:to_param]
|
||||||
self.denied = DEFAULT_DENIED
|
self.denied = DEFAULT_DENIED
|
||||||
|
@ -11,24 +11,24 @@ module Draper
|
||||||
def initialize(input)
|
def initialize(input)
|
||||||
input.inspect
|
input.inspect
|
||||||
self.class.model_class = input.class if model_class.nil?
|
self.class.model_class = input.class if model_class.nil?
|
||||||
@model = input
|
@model = input
|
||||||
build_methods
|
build_methods
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find(input)
|
def self.find(input)
|
||||||
self.new(model_class.find(input))
|
self.new(model_class.find(input))
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.decorates(input)
|
def self.decorates(input)
|
||||||
self.model_class = input.to_s.classify.constantize
|
self.model_class = input.to_s.classify.constantize
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.denies(*input_denied)
|
def self.denies(*input_denied)
|
||||||
raise ArgumentError, "Specify at least one method (as a symbol) to exclude when using denies" if input_denied.empty?
|
raise ArgumentError, "Specify at least one method (as a symbol) to exclude when using denies" if input_denied.empty?
|
||||||
raise ArgumentError, "Use either 'allows' or 'denies', but not both." if self.allowed?
|
raise ArgumentError, "Use either 'allows' or 'denies', but not both." if self.allowed?
|
||||||
self.denied += input_denied
|
self.denied += input_denied
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.allows(*input_allows)
|
def self.allows(*input_allows)
|
||||||
raise ArgumentError, "Specify at least one method (as a symbol) to allow when using allows" if input_allows.empty?
|
raise ArgumentError, "Specify at least one method (as a symbol) to allow when using allows" if input_allows.empty?
|
||||||
raise ArgumentError, "Use either 'allows' or 'denies', but not both." unless (self.denied == DEFAULT_DENIED)
|
raise ArgumentError, "Use either 'allows' or 'denies', but not both." unless (self.denied == DEFAULT_DENIED)
|
||||||
|
@ -38,7 +38,7 @@ module Draper
|
||||||
def self.decorate(input)
|
def self.decorate(input)
|
||||||
input.respond_to?(:each) ? input.map{|i| new(i)} : new(input)
|
input.respond_to?(:each) ? input.map{|i| new(i)} : new(input)
|
||||||
end
|
end
|
||||||
|
|
||||||
def helpers
|
def helpers
|
||||||
@helpers ||= ApplicationController::all_helpers
|
@helpers ||= ApplicationController::all_helpers
|
||||||
end
|
end
|
||||||
|
@ -47,16 +47,16 @@ module Draper
|
||||||
def self.lazy_helpers
|
def self.lazy_helpers
|
||||||
self.send(:include, Draper::LazyHelpers)
|
self.send(:include, Draper::LazyHelpers)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.model_name
|
def self.model_name
|
||||||
ActiveModel::Name.new(model_class)
|
ActiveModel::Name.new(model_class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_model
|
def to_model
|
||||||
@model
|
@model
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def select_methods
|
def select_methods
|
||||||
specified = self.allowed || (model.public_methods - denied)
|
specified = self.allowed || (model.public_methods - denied)
|
||||||
(specified - self.public_methods) + FORCED_PROXY
|
(specified - self.public_methods) + FORCED_PROXY
|
||||||
|
@ -69,7 +69,7 @@ module Draper
|
||||||
model.send method, *args, &block
|
model.send method, *args, &block
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ require 'draper'
|
||||||
|
|
||||||
describe Draper::Base do
|
describe Draper::Base do
|
||||||
subject{ Draper::Base.new(source) }
|
subject{ Draper::Base.new(source) }
|
||||||
let(:source){ Product.new }
|
let(:source){ Product.new }
|
||||||
|
|
||||||
context(".lazy_helpers") do
|
context(".lazy_helpers") do
|
||||||
it "makes Rails helpers available without using the h. proxy" do
|
it "makes Rails helpers available without using the h. proxy" do
|
||||||
|
@ -11,7 +11,7 @@ describe Draper::Base do
|
||||||
subject.send(:pluralize, 5, "cat").should == "5 cats"
|
subject.send(:pluralize, 5, "cat").should == "5 cats"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context(".model_name") do
|
context(".model_name") do
|
||||||
it "should return an ActiveModel::Name instance" do
|
it "should return an ActiveModel::Name instance" do
|
||||||
Draper::Base.model_name.should be_instance_of(ActiveModel::Name)
|
Draper::Base.model_name.should be_instance_of(ActiveModel::Name)
|
||||||
|
@ -23,14 +23,14 @@ describe Draper::Base do
|
||||||
ProductDecorator.new(source).model_class == Product
|
ProductDecorator.new(source).model_class == Product
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context(".model / .to_model") do
|
context(".model / .to_model") do
|
||||||
it "should return the wrapped object" do
|
it "should return the wrapped object" do
|
||||||
subject.to_model.should == source
|
subject.to_model.should == source
|
||||||
subject.model.should == source
|
subject.model.should == source
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context("selecting methods") do
|
context("selecting methods") do
|
||||||
it "echos the methods of the wrapped class except default exclusions" do
|
it "echos the methods of the wrapped class except default exclusions" do
|
||||||
source.methods.each do |method|
|
source.methods.each do |method|
|
||||||
|
@ -39,41 +39,41 @@ describe Draper::Base do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not override a defined method with a source method" do
|
it "should not override a defined method with a source method" do
|
||||||
DecoratorWithApplicationHelper.new(source).length.should == "overridden"
|
DecoratorWithApplicationHelper.new(source).length.should == "overridden"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should always proxy to_param" do
|
it "should always proxy to_param" do
|
||||||
source.send :class_eval, "def to_param; 1; end"
|
source.send :class_eval, "def to_param; 1; end"
|
||||||
Draper::Base.new(source).to_param.should == 1
|
Draper::Base.new(source).to_param.should == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not copy the .class, .inspect, or other existing methods" do
|
it "should not copy the .class, .inspect, or other existing methods" do
|
||||||
source.class.should_not == subject.class
|
source.class.should_not == subject.class
|
||||||
source.inspect.should_not == subject.inspect
|
source.inspect.should_not == subject.inspect
|
||||||
source.to_s.should_not == subject.to_s
|
source.to_s.should_not == subject.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should wrap source methods so they still accept blocks" do
|
it "should wrap source methods so they still accept blocks" do
|
||||||
subject.block{"marker"}.should == "marker"
|
subject.block{"marker"}.should == "marker"
|
||||||
end
|
end
|
||||||
|
|
||||||
context ".find" do
|
context ".find" do
|
||||||
it "should lookup the associated model when passed an integer" do
|
it "should lookup the associated model when passed an integer" do
|
||||||
pd = ProductDecorator.find(1)
|
pd = ProductDecorator.find(1)
|
||||||
pd.should be_instance_of(ProductDecorator)
|
pd.should be_instance_of(ProductDecorator)
|
||||||
pd.model.should be_instance_of(Product)
|
pd.model.should be_instance_of(Product)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should lookup the associated model when passed a string" do
|
it "should lookup the associated model when passed a string" do
|
||||||
pd = ProductDecorator.find("1")
|
pd = ProductDecorator.find("1")
|
||||||
pd.should be_instance_of(ProductDecorator)
|
pd.should be_instance_of(ProductDecorator)
|
||||||
pd.model.should be_instance_of(Product)
|
pd.model.should be_instance_of(Product)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context ".decorate" do
|
context ".decorate" do
|
||||||
it "should return a collection of wrapped objects when given a collection of source objects" do
|
it "should return a collection of wrapped objects when given a collection of source objects" do
|
||||||
sources = [Product.new, Product.new]
|
sources = [Product.new, Product.new]
|
||||||
|
@ -82,106 +82,106 @@ describe Draper::Base do
|
||||||
output.size.should == sources.size
|
output.size.should == sources.size
|
||||||
output.each{ |decorated| decorated.should be_instance_of(Draper::Base) }
|
output.each{ |decorated| decorated.should be_instance_of(Draper::Base) }
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return a single wrapped object when given a single source object" do
|
it "should return a single wrapped object when given a single source object" do
|
||||||
output = Draper::Base.decorate(source)
|
output = Draper::Base.decorate(source)
|
||||||
output.should be_instance_of(Draper::Base)
|
output.should be_instance_of(Draper::Base)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "a sample usage with denies" do
|
describe "a sample usage with denies" do
|
||||||
let(:subject_with_denies){ DecoratorWithDenies.new(source) }
|
let(:subject_with_denies){ DecoratorWithDenies.new(source) }
|
||||||
|
|
||||||
it "should proxy methods not listed in denies" do
|
it "should proxy methods not listed in denies" do
|
||||||
subject_with_denies.should respond_to(:hello_world)
|
subject_with_denies.should respond_to(:hello_world)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not echo methods specified with denies" do
|
it "should not echo methods specified with denies" do
|
||||||
subject_with_denies.should_not respond_to(:goodnight_moon)
|
subject_with_denies.should_not respond_to(:goodnight_moon)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not clobber other decorators' methods" do
|
it "should not clobber other decorators' methods" do
|
||||||
subject.should respond_to(:hello_world)
|
subject.should respond_to(:hello_world)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not allow method_missing to circumvent a deny" do
|
it "should not allow method_missing to circumvent a deny" do
|
||||||
expect{subject_with_denies.title}.to raise_error(NoMethodError)
|
expect{subject_with_denies.title}.to raise_error(NoMethodError)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "a sample usage with allows" do
|
describe "a sample usage with allows" do
|
||||||
let(:subject_with_allows){ DecoratorWithAllows.new(source) }
|
let(:subject_with_allows){ DecoratorWithAllows.new(source) }
|
||||||
|
|
||||||
it "should echo the allowed method" do
|
it "should echo the allowed method" do
|
||||||
subject_with_allows.should respond_to(:upcase)
|
subject_with_allows.should respond_to(:upcase)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should echo _only_ the allowed method" do
|
it "should echo _only_ the allowed method" do
|
||||||
subject_with_allows.should_not respond_to(:downcase)
|
subject_with_allows.should_not respond_to(:downcase)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "invalid usages of allows and denies" do
|
describe "invalid usages of allows and denies" do
|
||||||
let(:blank_allows){
|
let(:blank_allows){
|
||||||
class DecoratorWithInvalidAllows < Draper::Base
|
class DecoratorWithInvalidAllows < Draper::Base
|
||||||
allows
|
allows
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
let(:blank_denies){
|
let(:blank_denies){
|
||||||
class DecoratorWithInvalidDenies < Draper::Base
|
class DecoratorWithInvalidDenies < Draper::Base
|
||||||
denies
|
denies
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
let(:using_allows_then_denies){
|
let(:using_allows_then_denies){
|
||||||
class DecoratorWithAllowsAndDenies < Draper::Base
|
class DecoratorWithAllowsAndDenies < Draper::Base
|
||||||
allows :hello_world
|
allows :hello_world
|
||||||
denies :goodnight_moon
|
denies :goodnight_moon
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
let(:using_denies_then_allows){
|
let(:using_denies_then_allows){
|
||||||
class DecoratorWithDeniesAndAllows < Draper::Base
|
class DecoratorWithDeniesAndAllows < Draper::Base
|
||||||
denies :goodnight_moon
|
denies :goodnight_moon
|
||||||
allows :hello_world
|
allows :hello_world
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should raise an exception for a blank allows" do
|
it "should raise an exception for a blank allows" do
|
||||||
expect {blank_allows}.should raise_error(ArgumentError)
|
expect {blank_allows}.should raise_error(ArgumentError)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should raise an exception for a blank denies" do
|
it "should raise an exception for a blank denies" do
|
||||||
expect {blank_denies}.should raise_error(ArgumentError)
|
expect {blank_denies}.should raise_error(ArgumentError)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should raise an exception for calling allows then denies" do
|
it "should raise an exception for calling allows then denies" do
|
||||||
expect {using_allows_then_denies}.should raise_error(ArgumentError)
|
expect {using_allows_then_denies}.should raise_error(ArgumentError)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should raise an exception for calling denies then allows" do
|
it "should raise an exception for calling denies then allows" do
|
||||||
expect {using_denies_then_allows}.should raise_error(ArgumentError)
|
expect {using_denies_then_allows}.should raise_error(ArgumentError)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "in a Rails application" do
|
context "in a Rails application" do
|
||||||
let(:decorator){ DecoratorWithApplicationHelper.decorate(Object.new) }
|
let(:decorator){ DecoratorWithApplicationHelper.decorate(Object.new) }
|
||||||
|
|
||||||
it "should have access to ApplicationHelper helpers" do
|
it "should have access to ApplicationHelper helpers" do
|
||||||
decorator.uses_hello_world == "Hello, World!"
|
decorator.uses_hello_world == "Hello, World!"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be able to use the content_tag helper" do
|
it "should be able to use the content_tag helper" do
|
||||||
decorator.sample_content.to_s.should == "<span>Hello, World!</span>"
|
decorator.sample_content.to_s.should == "<span>Hello, World!</span>"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be able to use the link_to helper" do
|
it "should be able to use the link_to helper" do
|
||||||
decorator.sample_link.should == "<a href=\"/World\">Hello</a>"
|
decorator.sample_link.should == "<a href=\"/World\">Hello</a>"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be able to use the pluralize helper" do
|
it "should be able to use the pluralize helper" do
|
||||||
decorator.sample_truncate.should == "Once..."
|
decorator.sample_truncate.should == "Once..."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue