mirror of
https://github.com/drapergem/draper
synced 2023-03-27 23:21:17 -04:00
Provide support for class methods. Reintroduce the decorates class method, which may be used to hint at which class to delegate class methods to.
This commit is contained in:
parent
41ca1a3203
commit
731995a5fe
5 changed files with 59 additions and 22 deletions
|
@ -45,7 +45,33 @@ module Draper
|
|||
# @option options [Class, Symbol] :for The model class to find
|
||||
def self.has_finders(options = {})
|
||||
extend Draper::Finders
|
||||
self.finder_class = options[:for] || name.chomp("Decorator")
|
||||
if klass = options.delete(:for)
|
||||
decorates klass
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
# Specify the class that this class decorates.
|
||||
#
|
||||
# @param [String, Symbol, Class] Class or name of class to decorate.
|
||||
def decorates(klass)
|
||||
@source_class = klass.kind_of?(Class) ? klass : klass.to_s.classify.constantize
|
||||
end
|
||||
|
||||
# Provides access to the class that this decorator decorates
|
||||
#
|
||||
# @return [Class]: The class wrapped by the decorator
|
||||
def source_class
|
||||
@source_class ||= name.chomp("Decorator").constantize
|
||||
end
|
||||
|
||||
def method_missing(method, *args, &block)
|
||||
source_class.send(method, *args, &block)
|
||||
end
|
||||
|
||||
def respond_to?(method, include_private = false)
|
||||
super || source_class.respond_to?(method)
|
||||
end
|
||||
end
|
||||
|
||||
# Typically called within a decorator definition, this method causes
|
||||
|
|
20
lib/draper/finders.rb
Normal file → Executable file
20
lib/draper/finders.rb
Normal file → Executable file
|
@ -1,29 +1,24 @@
|
|||
module Draper
|
||||
module Finders
|
||||
|
||||
attr_reader :finder_class
|
||||
def finder_class=(klass)
|
||||
@finder_class = klass.to_s.camelize.constantize
|
||||
end
|
||||
|
||||
def find(id, options = {})
|
||||
decorate(finder_class.find(id), options)
|
||||
decorate(source_class.find(id), options)
|
||||
end
|
||||
|
||||
def all(options = {})
|
||||
decorate_collection(finder_class.all, options)
|
||||
decorate_collection(source_class.all, options)
|
||||
end
|
||||
|
||||
def first(options = {})
|
||||
decorate(finder_class.first, options)
|
||||
decorate(source_class.first, options)
|
||||
end
|
||||
|
||||
def last(options = {})
|
||||
decorate(finder_class.last, options)
|
||||
decorate(source_class.last, options)
|
||||
end
|
||||
|
||||
def method_missing(method, *args, &block)
|
||||
result = finder_class.send(method, *args, &block)
|
||||
result = source_class.send(method, *args, &block)
|
||||
options = args.extract_options!
|
||||
|
||||
case method.to_s
|
||||
|
@ -35,10 +30,5 @@ module Draper
|
|||
result
|
||||
end
|
||||
end
|
||||
|
||||
def respond_to?(method, include_private = false)
|
||||
super || finder_class.respond_to?(method)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -450,12 +450,12 @@ describe Draper::Decorator do
|
|||
|
||||
context "with no options" do
|
||||
it "infers the finder class" do
|
||||
ProductDecorator.finder_class.should be Product
|
||||
ProductDecorator.source_class.should be Product
|
||||
end
|
||||
|
||||
context "for a namespaced model" do
|
||||
it "infers the finder class" do
|
||||
Namespace::ProductDecorator.finder_class.should be Namespace::Product
|
||||
Namespace::ProductDecorator.source_class.should be Namespace::Product
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -466,21 +466,21 @@ describe Draper::Decorator do
|
|||
context "with a symbol" do
|
||||
it "sets the finder class" do
|
||||
subject.has_finders for: :product
|
||||
subject.finder_class.should be Product
|
||||
subject.source_class.should be Product
|
||||
end
|
||||
end
|
||||
|
||||
context "with a string" do
|
||||
it "sets the finder class" do
|
||||
subject.has_finders for: "some_thing"
|
||||
subject.finder_class.should be SomeThing
|
||||
subject.source_class.should be SomeThing
|
||||
end
|
||||
end
|
||||
|
||||
context "with a class" do
|
||||
it "sets the finder_class" do
|
||||
it "sets the source_class" do
|
||||
subject.has_finders for: Namespace::Product
|
||||
subject.finder_class.should be Namespace::Product
|
||||
subject.source_class.should be Namespace::Product
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -494,4 +494,18 @@ describe Draper::Decorator do
|
|||
end
|
||||
end
|
||||
|
||||
context "class methods" do
|
||||
it "passes through to the underlying wrapped class" do
|
||||
ProductDecorator.sample_class_method.should == Product.sample_class_method
|
||||
end
|
||||
|
||||
context "when told to decorate a different class " do
|
||||
subject { decorator_class }
|
||||
before { decorator_class.decorates :product }
|
||||
|
||||
it "should manually set the class to pass methods to" do
|
||||
subject.sample_class_method.should == Product.sample_class_method
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
4
spec/dummy/app/decorators/post_decorator.rb
Normal file → Executable file
4
spec/dummy/app/decorators/post_decorator.rb
Normal file → Executable file
|
@ -22,4 +22,8 @@ class PostDecorator < Draper::Decorator
|
|||
def url_with_id
|
||||
h.post_url(id: id)
|
||||
end
|
||||
|
||||
def link
|
||||
h.link_to id.to_s, self
|
||||
end
|
||||
end
|
||||
|
|
3
spec/dummy/spec/decorators/post_decorator_spec.rb
Normal file → Executable file
3
spec/dummy/spec/decorators/post_decorator_spec.rb
Normal file → Executable file
|
@ -20,4 +20,7 @@ describe PostDecorator do
|
|||
subject.url_with_id.should == "http://www.example.com/en/posts/#{source.id}"
|
||||
end
|
||||
|
||||
it "can be passed implicitly to url_for" do
|
||||
subject.link.should == "<a href=\"/en/posts/#{source.id}\">#{source.id}</a>"
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue