-
Notifications
You must be signed in to change notification settings - Fork 524
Activerecord relations #610
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 5 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
81061c8
Another approach to decorating relations
donaldpiret 45ed859
Better spec coverage and more seamless activerecord integration
donaldpiret 5a85539
One more safeguard for those who really don't want AR
donaldpiret 5de75fb
small fix
donaldpiret 98caed0
Make it work with block methods too
donaldpiret f8c32fc
Another approach to decorating relations
donaldpiret 8deb1b8
Better spec coverage and more seamless activerecord integration
donaldpiret a9389f7
One more safeguard for those who really don't want AR
donaldpiret e6461be
small fix
donaldpiret d6ccbec
Make it work with block methods too
donaldpiret eb99a67
Merge branch 'activerecord-relations' of https://github.com/donaldpir…
donaldpiret b90f476
Switch to old lambda syntax
donaldpiret 97cab69
Fix casing of ActiveRecord in comment
donaldpiret 2c6bff5
Another casing fix for ActiveRecord
donaldpiret 9de33e0
Another approach to decorating relations
donaldpiret 46acbc9
Better spec coverage and more seamless activerecord integration
donaldpiret a0905da
One more safeguard for those who really don't want AR
donaldpiret 309ee6e
small fix
donaldpiret 7384395
Make it work with block methods too
donaldpiret ba54c61
Another approach to decorating relations
donaldpiret ccf50dd
Better spec coverage and more seamless activerecord integration
donaldpiret b1c30d2
One more safeguard for those who really don't want AR
donaldpiret 15d5123
small fix
donaldpiret d2425c2
Switch to old lambda syntax
donaldpiret 5ee4ecd
Fix casing of ActiveRecord in comment
donaldpiret cf2e888
Another casing fix for ActiveRecord
donaldpiret 949c797
Merge branch 'activerecord-relations' of https://github.com/donaldpir…
donaldpiret 2e3a6b2
Remove .idea dir
donaldpiret aa8732f
Merge latest master
donaldpiret 3baa314
Small spec fix
donaldpiret aac820b
Add mongoid criteria support
donaldpiret File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| module Draper | ||
| class RelationDecorator | ||
| include Draper::ViewHelpers | ||
| extend Draper::Delegation | ||
|
|
||
| # @return [Class] the decorator class used to decorate this relation, as set by | ||
| # {#initialize}. | ||
| attr_reader :decorator_class | ||
|
|
||
| # @return [Hash] extra data to be used in user-defined methods, and passed | ||
| # to each item's decorator. | ||
| attr_accessor :context | ||
|
|
||
| # @param [ActiveRecord::Relation] relation | ||
| # relation to decorate. | ||
| # @option options [Class, nil] :with (nil) | ||
| # the decorator class used to decorate each item. When `nil`, each item's | ||
| # {Decoratable#decorate decorate} method will be used. | ||
| # @option options [Hash] :context ({}) | ||
| # extra data to be stored in the relation decorator and used in | ||
| # user-defined methods, and passed to each item's decorator. | ||
| def initialize(relation, options = {}) | ||
| options.assert_valid_keys(:with, :context) | ||
| @relation = relation | ||
| @decorator_class = options[:with] | ||
| @decorator_class ||= klass.decorator_class if relation.respond_to?(:klass) && klass.respond_to?(:decorator_class) | ||
| @context = options.fetch(:context, {}) | ||
| end | ||
|
|
||
| class << self | ||
| alias_method :decorate, :new | ||
| end | ||
|
|
||
| def to_s | ||
| "#<#{self.class.name} of #{decorator_class || "inferred decorators"} for #{relation.inspect}>" | ||
| end | ||
|
|
||
| def context=(value) | ||
| @context = value | ||
| end | ||
|
|
||
| # @return [true] | ||
| def decorated? | ||
| true | ||
| end | ||
|
|
||
| alias_method :decorated_with?, :instance_of? | ||
|
|
||
| def decorating_class | ||
| return decorator_class if decorator_class | ||
| self.class | ||
| end | ||
|
|
||
| def method_missing(method, *args, &block) | ||
| block ? | ||
| relation.send(method, *args, &proxy_block(&block)) : | ||
| handle_result(relation.send(method, *args)) | ||
| end | ||
|
|
||
| def proxy_block(&original_block) | ||
| -> (data) { original_block.call(handle_result(data)) } | ||
| end | ||
|
|
||
| def handle_result(result) | ||
| if defined?(ActiveRecord) && result.is_a?(ActiveRecord::Relation) | ||
| return self.class.decorate(result, context: context) | ||
| elsif result.is_a?(Array) | ||
| return Decorator.collection_decorator_class.new(result, context: context) | ||
| elsif relation.respond_to?(:klass) && result.is_a?(relation.klass) && klass.respond_to?(:decorate) | ||
| return result.decorate(context: context) | ||
| else | ||
| return result | ||
| end | ||
| end | ||
|
|
||
| protected | ||
|
|
||
| # @return the relation being decorated. | ||
| attr_reader :relation | ||
|
|
||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| require 'spec_helper' | ||
| require 'support/shared_examples/view_helpers' | ||
|
|
||
| module Draper | ||
| describe RelationDecorator do | ||
| it_behaves_like "view helpers", RelationDecorator.new([]) | ||
|
|
||
| describe "#initialize" do | ||
| describe "options validation" do | ||
|
|
||
| it "does not raise error on valid options" do | ||
| valid_options = {with: Decorator, context: {}} | ||
| expect{RelationDecorator.new(ActiveRecord::Relation.new, valid_options)}.not_to raise_error | ||
| end | ||
|
|
||
| it "raises error on invalid options" do | ||
| expect{RelationDecorator.new(ActiveRecord::Relation.new, foo: "bar")}.to raise_error ArgumentError, /Unknown key/ | ||
| end | ||
| end | ||
| end | ||
|
|
||
| context "with context" do | ||
| it "stores the context itself" do | ||
| context = {some: "context"} | ||
| decorator = RelationDecorator.new(ActiveRecord::Relation.new, context: context) | ||
|
|
||
| expect(decorator.context).to be context | ||
| end | ||
| end | ||
|
|
||
| describe "#context=" do | ||
| it "updates the stored context" do | ||
| decorator = RelationDecorator.new(ActiveRecord::Relation.new, context: {some: "context"}) | ||
| new_context = {other: "context"} | ||
|
|
||
| decorator.context = new_context | ||
| expect(decorator.context).to be new_context | ||
| end | ||
| end | ||
|
|
||
| it "returns a relation decorator when a scope is called on the decorated relation" do | ||
| module ActiveRecord | ||
| class Relation | ||
| include Draper::Decoratable | ||
| def some_scope; self ;end | ||
| end | ||
| end | ||
|
|
||
| klass = Product | ||
| klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end } | ||
| expect(Product).to respond_to(:some_scope) | ||
| proxy = RelationDecorator.new(klass) | ||
| expect(proxy.some_scope).to be_instance_of(proxy.class) | ||
| end | ||
|
|
||
| it 'supports chaining multiple scopes' do | ||
| module ActiveRecord | ||
| class Relation | ||
| include Draper::Decoratable | ||
| def some_scope; self ;end | ||
| end | ||
| end | ||
|
|
||
| klass = Product | ||
| klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end } | ||
| proxy = RelationDecorator.new(klass) | ||
| expect(proxy.some_scope.some_scope.some_scope).to be_instance_of(proxy.class) | ||
| expect(proxy.some_scope.some_scope.some_scope).to be_decorated | ||
| end | ||
|
|
||
| describe '#decorated?' do | ||
| it 'returns true' do | ||
| klass = Product | ||
| klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end } | ||
| decorator = ProductsRelationDecorator.new(Product.some_scope) | ||
|
|
||
| expect(decorator).to be_decorated | ||
| end | ||
| end | ||
|
|
||
| describe '#decorated_with?' do | ||
| it "checks if a decorator has been applied to a collection" do | ||
| klass = Product | ||
| klass.class_eval { def self.some_scope ; ActiveRecord::Relation.new ; end } | ||
| decorator = ProductsRelationDecorator.new(Product.some_scope) | ||
|
|
||
| expect(decorator).to be_decorated_with ProductsRelationDecorator | ||
| expect(decorator).not_to be_decorated_with OtherDecorator | ||
| end | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| class Post < ActiveRecord::Base | ||
| # attr_accessible :title, :body | ||
| scope :active, ->{ where('1 = 1') } | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ActiveRecord