Skip to content

Commit

Permalink
Fix block context (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
dim committed Apr 6, 2022
1 parent 504e6c3 commit c2814f9
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 33 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
filterable-by (0.6.2)
filterable-by (0.6.3)
activerecord
activesupport

Expand Down
2 changes: 1 addition & 1 deletion filterable-by.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'filterable-by'
s.version = '0.6.2'
s.version = '0.6.3'
s.authors = ['Dimitrij Denissenko']
s.email = ['dimitrij@blacksquaremedia.com']
s.summary = 'Generate white-listed filter scopes from URL parameter values'
Expand Down
67 changes: 41 additions & 26 deletions lib/filterable_by.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,56 @@

module ActiveRecord
module FilterableBy
def self.normalize(value)
case value
when String, Numeric
value
when Array
value.select {|v| normalize(v) }
class << self
def normalize(value)
case value
when String, Numeric
value
when Array
value.select {|v| normalize(v) }
end
end
end

def self.merge(scope, unscoped, hash, name, **opts, &block)
key = name
positive = normalize(hash[key]) if hash.key?(key)
if positive.present?
sub = block.arity == 2 ? yield(unscoped, positive, **opts) : yield(positive, **opts)
return nil unless sub
def merge(scope, unscoped, hash, name, **opts, &block)
key = name
positive = normalize(hash[key]) if hash.key?(key)
if positive.present?
sub = eval_scope(scope, unscoped, positive, **opts, &block)
return nil unless sub

scope = scope.merge(sub)
end

key = "#{name}_not"
negative = normalize(hash[key]) if hash.key?(key)
if negative.present?
sub = eval_scope(scope, unscoped, negative, **opts, &block)
return nil unless sub

scope = scope.merge(sub)
scope = scope.merge(invert_where(sub))
end

scope
end

key = "#{name}_not"
negative = normalize(hash[key]) if hash.key?(key)
if negative.present?
sub = block.arity == 2 ? yield(unscoped, negative, **opts) : yield(negative, **opts)
return nil unless sub
private

if sub.respond_to?(:invert_where)
sub = sub.invert_where
def eval_scope(scope, unscoped, value, **opts, &block)
if block.arity == 2
scope.instance_exec(unscoped, value, **opts, &block)
else
sub.where_clause = sub.where_clause.invert
scope.instance_exec(value, **opts, &block)
end
scope = scope.merge(sub)
end

scope
def invert_where(scope)
if scope.respond_to?(:invert_where!)
scope.invert_where!
else
scope.where_clause = scope.where_clause.invert
end
scope
end
end

module ClassMethods
Expand All @@ -58,7 +74,7 @@ def filterable_by(*names, &block)
end

names.each do |name|
_filterable_by_config[name.to_s] = block
_filterable_by_config[name.to_s] = block || ->(value, **) { where(name.to_sym => value) }
end
end

Expand All @@ -74,7 +90,6 @@ def filter_by(hash = nil, **opts)
return scope unless hash.respond_to?(:key?) && hash.respond_to?(:[])

_filterable_by_config.each do |name, block|
block = ->(value, **) { where(name.to_sym => value) } if block.nil?
scope = FilterableBy.merge(scope, unscoped, hash, name, **opts, &block)
break unless scope
end
Expand Down
10 changes: 5 additions & 5 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,8 @@ class Author < ActiveRecord::Base

class AbstractPost < ActiveRecord::Base
self.abstract_class = true
filterable_by :author_id
end

class Post < AbstractPost
belongs_to :author

filterable_by :author_id
filterable_by :only do |value, **opts|
case value
when 'me'
Expand All @@ -43,6 +39,10 @@ class Post < AbstractPost
end
end

class Post < AbstractPost
belongs_to :author
end

class Feedback < ActiveRecord::Base
belongs_to :author
belongs_to :post
Expand Down

0 comments on commit c2814f9

Please sign in to comment.