-
Notifications
You must be signed in to change notification settings - Fork 3
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
Allow negation #8
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
PATH | ||
remote: . | ||
specs: | ||
filterable-by (0.5.3) | ||
filterable-by (0.6.0) | ||
activerecord | ||
activesupport | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,15 +17,15 @@ class Comment < ActiveRecord::Base | |
belongs_to :post | ||
|
||
filterable_by :post_id, :user_id | ||
filterable_by :post_author_id do |scope, value| | ||
scope.joins(:posts).where(:'posts.author_id' => value) | ||
filterable_by :post_author_id do |value| | ||
joins(:posts).where(:'posts.author_id' => value) | ||
end | ||
filterable_by :only do |scope, value, **opts| | ||
filterable_by :only do |value, **opts| | ||
case value | ||
when 'mine' | ||
scope.where(user_id: opts[:user_id]) if opts[:user_id] | ||
where(user_id: opts[:user_id]) if opts[:user_id] | ||
else | ||
scope | ||
all | ||
end | ||
end | ||
end | ||
|
@@ -39,6 +39,12 @@ Simple use cases: | |
Comment.filter_by({ 'post_id' => '1' }) | ||
# => WHERE post_id = 1 | ||
|
||
Comment.filter_by({ 'post_id' => ['1', '2'] }) | ||
# => WHERE post_id IN (1, 2) | ||
|
||
Comment.filter_by({ 'post_id_not' => '3' }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the other change is that you now can append |
||
# => WHERE post_id != 3 | ||
|
||
Comment.filter_by({ 'user_id' => '2', 'ignored' => '3' }) | ||
# => WHERE user_id = 2 | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,28 @@ def self.normalize(value) | |
end | ||
end | ||
|
||
def self.merge(scope, unscoped, hash, name, **opts, &block) | ||
key = name | ||
positive = normalize(hash[key]) if hash.key?(key) | ||
if positive.present? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @andyborn here we only apply block/limit scope if |
||
sub = block.arity == 2 ? yield(unscoped, positive, **opts) : yield(positive, **opts) | ||
return nil unless sub | ||
|
||
scope = scope.merge(sub) | ||
end | ||
|
||
key = "#{name}_not" | ||
negative = normalize(hash[key]) if hash.key?(key) | ||
if negative.present? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same with |
||
sub = block.arity == 2 ? yield(unscoped, negative, **opts) : yield(negative, **opts) | ||
return nil unless sub | ||
|
||
scope = scope.merge(sub.invert_where) | ||
end | ||
|
||
scope | ||
end | ||
|
||
module ClassMethods | ||
def self.extended(base) # :nodoc: | ||
base.class_attribute :_filterable_by_config, instance_accessor: false, instance_predicate: false | ||
|
@@ -26,8 +48,12 @@ def inherited(base) # :nodoc: | |
end | ||
|
||
def filterable_by(*names, &block) | ||
if block && block.arity > 1 | ||
ActiveSupport::Deprecation.warn('using scope in filterable_by blocks is deprecated. Please use filterable_by(:x) {|val| where(field: val) } instead.') | ||
end | ||
|
||
names.each do |name| | ||
_filterable_by_config[name.to_s] = block || ->(scope, value, **) { scope.where(name.to_sym => value) } | ||
_filterable_by_config[name.to_s] = block || ->(value, **) { where(name.to_sym => value) } | ||
end | ||
end | ||
|
||
|
@@ -38,16 +64,13 @@ def filter_by(hash = nil, **opts) | |
hash = opts | ||
opts = {} | ||
end | ||
|
||
scope = all | ||
return scope unless hash.respond_to?(:key?) && hash.respond_to?(:[]) | ||
|
||
_filterable_by_config.each do |name, block| | ||
next unless hash.key?(name) | ||
|
||
value = FilterableBy.normalize(hash[name]) | ||
next if value.blank? | ||
|
||
scope = block.call(scope, value, **opts) | ||
scope = FilterableBy.merge(scope, unscoped, hash, name, **opts, &block) | ||
break unless scope | ||
end | ||
|
||
scope || none | ||
|
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.
so the big change is that you don't now need
scope
as a block argument, but the old method is still supported (although deprecated)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.
will we still be able to handle when value is nil cases?
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.
value cannot be nil, these blocks are only run
unless value.bank?