Skip to content

Instantly share code, notes, and snippets.

@jhsu
Created September 19, 2012 00:33
Show Gist options
  • Save jhsu/3746944 to your computer and use it in GitHub Desktop.
Save jhsu/3746944 to your computer and use it in GitHub Desktop.
commit c46b0fd17d59e1d8c0d303fb8d614dcdf6d4fe6a
Author: Joseph Hsu <[email protected]>
Date: Wed Aug 22 21:45:55 2012 -0400
move fake ActiveRecord::Relation to helper, use #kind_of instead of comparing to string
diff --git a/lib/draper/base.rb b/lib/draper/base.rb
index 1d16459..47937f0 100755
--- a/lib/draper/base.rb
+++ b/lib/draper/base.rb
@@ -256,7 +256,7 @@ module Draper
if model.respond_to?(method)
self.class.send :define_method, method do |*args, &blokk|
result = model.send method, *args, &blokk
- if result.class.name == "ActiveRecord::Relation"
+ if defined?(ActiveRecord) && result.kind_of?(ActiveRecord::Relation)
self.class.new(model,self.options)
else
result
@@ -275,7 +275,8 @@ module Draper
def self.method_missing(method, *args, &block)
model_result = model_class.send(method, *args, &block)
- if model_result.is_a?(model_class) || model_result.class.name == 'ActiveRecord::Relation'
+ if model_result.kind_of?(model_class) ||
+ (defined?(ActiveRecord) && model_result.kind_of?(ActiveRecord::Relation))
self.decorate(model_result, :context => args.dup.extract_options!)
else
model_result
diff --git a/lib/draper/decorated_enumerable_proxy.rb b/lib/draper/decorated_enumerable_proxy.rb
index 4561456..fc123c8 100644
--- a/lib/draper/decorated_enumerable_proxy.rb
+++ b/lib/draper/decorated_enumerable_proxy.rb
@@ -28,7 +28,7 @@ module Draper
if @wrapped_collection.respond_to?(method)
self.class.send :define_method, method do |*args, &blokk|
scoped_result = @wrapped_collection.send(method, *args, &block)
- if scoped_result.class.name == "ActiveRecord::Relation"
+ if defined?(ActiveRecord) && scoped_result.kind_of?(ActiveRecord::Relation)
self.class.new(scoped_result, @klass, @options)
else
scoped_result
diff --git a/spec/draper/base_spec.rb b/spec/draper/base_spec.rb
index 6290f9b..147a3ed 100755
--- a/spec/draper/base_spec.rb
+++ b/spec/draper/base_spec.rb
@@ -51,7 +51,6 @@ describe Draper::Base do
end
it "returns a Decorator when a scope is called on decorated object" do
- class ActiveRecord::Relation; end
proxy = ProductDecorator.new(source)
klass = proxy.model.class
klass.class_eval { def some_scope ; ActiveRecord::Relation.new ; end }
@@ -59,7 +58,6 @@ describe Draper::Base do
end
it "returns a Decorator when a scope is called on the decorator" do
- class ActiveRecord::Relation; end
proxy = ProductDecorator
klass = source.class
klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end }
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 3af778f..a59c1e2 100755
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -34,3 +34,8 @@ module ActionController
Draper::System.setup(self)
end
end
+
+module ActiveRecord
+ class Relation
+ end
+end
commit 0f02556cc830c77d5a66b4b6eff396b99353569d
Author: Joseph Hsu <[email protected]>
Date: Wed Aug 22 16:51:12 2012 -0400
fix typo with class name
diff --git a/spec/draper/base_spec.rb b/spec/draper/base_spec.rb
index 80ba348..6290f9b 100755
--- a/spec/draper/base_spec.rb
+++ b/spec/draper/base_spec.rb
@@ -59,7 +59,7 @@ describe Draper::Base do
end
it "returns a Decorator when a scope is called on the decorator" do
- class ActiveRecord::Relatio; end
+ class ActiveRecord::Relation; end
proxy = ProductDecorator
klass = source.class
klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end }
commit e4595d93415826033c18d3e8cf686f2c573760b3
Author: Joseph Hsu <[email protected]>
Date: Wed Aug 22 14:50:24 2012 -0400
Wrap relation calls and scope calls in decorators
* wrap model in decorator when scope is called on decorator
* decorate named scope calls on decorators and enumerable proxies
diff --git a/lib/draper/base.rb b/lib/draper/base.rb
index 97d9ed1..1d16459 100755
--- a/lib/draper/base.rb
+++ b/lib/draper/base.rb
@@ -255,7 +255,12 @@ module Draper
if model.respond_to?(method)
self.class.send :define_method, method do |*args, &blokk|
- model.send method, *args, &blokk
+ result = model.send method, *args, &blokk
+ if result.class.name == "ActiveRecord::Relation"
+ self.class.new(model,self.options)
+ else
+ result
+ end
end
send method, *args, &block
@@ -269,10 +274,11 @@ module Draper
end
def self.method_missing(method, *args, &block)
- if method.to_s.match(/^find_((all_|last_)?by_|or_(initialize|create)_by_).*/)
- self.decorate(model_class.send(method, *args, &block), :context => args.dup.extract_options!)
+ model_result = model_class.send(method, *args, &block)
+ if model_result.is_a?(model_class) || model_result.class.name == 'ActiveRecord::Relation'
+ self.decorate(model_result, :context => args.dup.extract_options!)
else
- model_class.send(method, *args, &block)
+ model_result
end
end
diff --git a/lib/draper/decorated_enumerable_proxy.rb b/lib/draper/decorated_enumerable_proxy.rb
index f0935cc..4561456 100644
--- a/lib/draper/decorated_enumerable_proxy.rb
+++ b/lib/draper/decorated_enumerable_proxy.rb
@@ -25,7 +25,24 @@ module Draper
end
def method_missing (method, *args, &block)
- @wrapped_collection.send(method, *args, &block)
+ if @wrapped_collection.respond_to?(method)
+ self.class.send :define_method, method do |*args, &blokk|
+ scoped_result = @wrapped_collection.send(method, *args, &block)
+ if scoped_result.class.name == "ActiveRecord::Relation"
+ self.class.new(scoped_result, @klass, @options)
+ else
+ scoped_result
+ end
+ end
+
+ send method, *args, &block
+ else
+ super
+ end
+
+ rescue NoMethodError => no_method_error
+ super if no_method_error.name == method
+ raise no_method_error
end
def respond_to?(method, include_private = false)
diff --git a/spec/draper/base_spec.rb b/spec/draper/base_spec.rb
index e740ea3..80ba348 100755
--- a/spec/draper/base_spec.rb
+++ b/spec/draper/base_spec.rb
@@ -50,6 +50,22 @@ describe Draper::Base do
ProductDecorator.new(product_decorator).model.should be_instance_of Product
end
+ it "returns a Decorator when a scope is called on decorated object" do
+ class ActiveRecord::Relation; end
+ proxy = ProductDecorator.new(source)
+ klass = proxy.model.class
+ klass.class_eval { def some_scope ; ActiveRecord::Relation.new ; end }
+ proxy.some_scope.should be_instance_of(proxy.class)
+ end
+
+ it "returns a Decorator when a scope is called on the decorator" do
+ class ActiveRecord::Relatio; end
+ proxy = ProductDecorator
+ klass = source.class
+ klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end }
+ proxy.some_scope.should be_instance_of(proxy)
+ end
+
it "handle plural-like words properly'" do
class Business; end
expect do
@@ -162,6 +178,18 @@ describe Draper::Base do
end
end
+ context "with a scope applied after decoration" do
+ it "returns a DecoratedEnumerableProxy when a scope is called" do
+ class ActiveRecord::Relation
+ def some_scope; self ;end
+ end
+ klass = subject.model.class
+ klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end }
+ proxy = Draper::DecoratedEnumerableProxy
+ proxy.new(ActiveRecord::Relation.new, klass).some_scope.should be_instance_of(proxy)
+ end
+ end
+
context "for a polymorphic association" do
before(:each){ subject.class_eval{ decorates_association :thing, :polymorphic => true } }
it "causes the association to be decorated with the right decorator" do
@@ -352,8 +380,7 @@ describe Draper::Base do
it "uses the options hash in the decorator instantiation" do
Product.should_receive(:find_by_name_and_size).with("apples", "large", {:role => :admin})
- pd = ProductDecorator.find_by_name_and_size("apples", "large", {:role => :admin})
- pd.context[:role].should == :admin
+ ProductDecorator.find_by_name_and_size("apples", "large", {:role => :admin})
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment