ransack 1.5.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +47 -3
- data/CHANGELOG.md +106 -18
- data/CONTRIBUTING.md +56 -23
- data/Gemfile +16 -5
- data/README.md +114 -38
- data/Rakefile +30 -2
- data/lib/ransack.rb +9 -0
- data/lib/ransack/adapters/active_record/3.0/compat.rb +11 -8
- data/lib/ransack/adapters/active_record/3.0/context.rb +14 -22
- data/lib/ransack/adapters/active_record/3.1/context.rb +14 -22
- data/lib/ransack/adapters/active_record/context.rb +36 -31
- data/lib/ransack/adapters/active_record/ransack/constants.rb +113 -0
- data/lib/ransack/adapters/active_record/ransack/context.rb +64 -0
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +48 -0
- data/lib/ransack/adapters/active_record/ransack/translate.rb +12 -0
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +24 -0
- data/lib/ransack/adapters/mongoid.rb +13 -0
- data/lib/ransack/adapters/mongoid/3.2/.gitkeep +0 -0
- data/lib/ransack/adapters/mongoid/attributes/attribute.rb +37 -0
- data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +17 -0
- data/lib/ransack/adapters/mongoid/attributes/predications.rb +141 -0
- data/lib/ransack/adapters/mongoid/base.rb +126 -0
- data/lib/ransack/adapters/mongoid/context.rb +208 -0
- data/lib/ransack/adapters/mongoid/inquiry_hash.rb +23 -0
- data/lib/ransack/adapters/mongoid/ransack/constants.rb +88 -0
- data/lib/ransack/adapters/mongoid/ransack/context.rb +60 -0
- data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +27 -0
- data/lib/ransack/adapters/mongoid/ransack/translate.rb +13 -0
- data/lib/ransack/adapters/mongoid/ransack/visitor.rb +24 -0
- data/lib/ransack/adapters/mongoid/table.rb +35 -0
- data/lib/ransack/configuration.rb +22 -4
- data/lib/ransack/constants.rb +26 -120
- data/lib/ransack/context.rb +32 -60
- data/lib/ransack/helpers/form_builder.rb +50 -36
- data/lib/ransack/helpers/form_helper.rb +148 -104
- data/lib/ransack/naming.rb +11 -11
- data/lib/ransack/nodes.rb +2 -0
- data/lib/ransack/nodes/bindable.rb +12 -4
- data/lib/ransack/nodes/condition.rb +5 -22
- data/lib/ransack/nodes/grouping.rb +9 -10
- data/lib/ransack/nodes/sort.rb +3 -2
- data/lib/ransack/nodes/value.rb +1 -2
- data/lib/ransack/predicate.rb +3 -3
- data/lib/ransack/search.rb +46 -13
- data/lib/ransack/translate.rb +8 -8
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +4 -16
- data/ransack.gemspec +1 -0
- data/spec/mongoid/adapters/mongoid/base_spec.rb +276 -0
- data/spec/mongoid/adapters/mongoid/context_spec.rb +56 -0
- data/spec/mongoid/configuration_spec.rb +66 -0
- data/spec/mongoid/dependencies_spec.rb +8 -0
- data/spec/mongoid/helpers/ransack_helper.rb +11 -0
- data/spec/mongoid/nodes/condition_spec.rb +34 -0
- data/spec/mongoid/nodes/grouping_spec.rb +13 -0
- data/spec/mongoid/predicate_spec.rb +155 -0
- data/spec/mongoid/search_spec.rb +446 -0
- data/spec/mongoid/support/mongoid.yml +6 -0
- data/spec/mongoid/support/schema.rb +128 -0
- data/spec/mongoid/translate_spec.rb +14 -0
- data/spec/mongoid_spec_helper.rb +59 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +68 -35
- data/spec/ransack/dependencies_spec.rb +3 -1
- data/spec/ransack/helpers/form_builder_spec.rb +6 -6
- data/spec/ransack/helpers/form_helper_spec.rb +114 -47
- data/spec/ransack/nodes/condition_spec.rb +2 -2
- data/spec/ransack/search_spec.rb +2 -6
- data/spec/ransack/translate_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -3
- data/spec/support/schema.rb +9 -0
- metadata +49 -4
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'ransack/visitor'
|
2
|
+
|
3
|
+
module Ransack
|
4
|
+
class Context
|
5
|
+
attr_reader :arel_visitor
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def for_class(klass, options = {})
|
10
|
+
if klass < ActiveRecord::Base
|
11
|
+
Adapters::ActiveRecord::Context.new(klass, options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def for_object(object, options = {})
|
16
|
+
case object
|
17
|
+
when ActiveRecord::Relation
|
18
|
+
Adapters::ActiveRecord::Context.new(object.klass, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end # << self
|
23
|
+
|
24
|
+
def initialize(object, options = {})
|
25
|
+
@object = relation_for(object)
|
26
|
+
@klass = @object.klass
|
27
|
+
@join_dependency = join_dependency(@object)
|
28
|
+
@join_type = options[:join_type] || Polyamorous::OuterJoin
|
29
|
+
@search_key = options[:search_key] || Ransack.options[:search_key]
|
30
|
+
|
31
|
+
if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1
|
32
|
+
@base = @join_dependency.join_root
|
33
|
+
@engine = @base.base_klass.arel_engine
|
34
|
+
else
|
35
|
+
@base = @join_dependency.join_base
|
36
|
+
@engine = @base.arel_engine
|
37
|
+
end
|
38
|
+
|
39
|
+
@default_table = Arel::Table.new(
|
40
|
+
@base.table_name, :as => @base.aliased_table_name, :engine => @engine
|
41
|
+
)
|
42
|
+
@bind_pairs = Hash.new do |hash, key|
|
43
|
+
parent, attr_name = get_parent_and_attribute_name(key.to_s)
|
44
|
+
if parent && attr_name
|
45
|
+
hash[key] = [parent, attr_name]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def klassify(obj)
|
51
|
+
if Class === obj && ::ActiveRecord::Base > obj
|
52
|
+
obj
|
53
|
+
elsif obj.respond_to? :klass
|
54
|
+
obj.klass
|
55
|
+
elsif obj.respond_to? :active_record # Rails 3
|
56
|
+
obj.active_record
|
57
|
+
elsif obj.respond_to? :base_klass # Rails 4
|
58
|
+
obj.base_klass
|
59
|
+
else
|
60
|
+
raise ArgumentError, "Don't know how to klassify #{obj.inspect}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Ransack
|
2
|
+
module Nodes
|
3
|
+
class Condition
|
4
|
+
|
5
|
+
def arel_predicate
|
6
|
+
predicates = attributes.map do |attr|
|
7
|
+
attr.attr.send(
|
8
|
+
arel_predicate_for_attribute(attr),
|
9
|
+
formatted_values_for_attribute(attr)
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
if predicates.size > 1
|
14
|
+
case combinator
|
15
|
+
when Constants::AND
|
16
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::And.new(predicates))
|
17
|
+
when Constants::OR
|
18
|
+
predicates.inject(&:or)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
return_predicate(predicates.first)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# FIXME: Improve this edge case patch for Arel >= 6.0 (Rails >= 4.2)
|
28
|
+
# that adds several conditionals to handle changing Arel API.
|
29
|
+
# Related to Ransack issue #472 and pull requests #486-488.
|
30
|
+
#
|
31
|
+
def return_predicate(predicate)
|
32
|
+
if casted_array_with_in_predicate?(predicate)
|
33
|
+
predicate.right[0] = predicate.right[0].val
|
34
|
+
.map { |v| v.is_a?(String) ? Arel::Nodes.build_quoted(v) : v }
|
35
|
+
end
|
36
|
+
predicate
|
37
|
+
end
|
38
|
+
#
|
39
|
+
def casted_array_with_in_predicate?(predicate)
|
40
|
+
return unless defined?(Arel::Nodes::Casted)
|
41
|
+
predicate.class == Arel::Nodes::In &&
|
42
|
+
predicate.right.is_a?(Array) &&
|
43
|
+
predicate.right[0].class == Arel::Nodes::Casted
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Ransack
|
2
|
+
module Translate
|
3
|
+
|
4
|
+
def self.i18n_key(klass)
|
5
|
+
if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
|
6
|
+
klass.model_name.i18n_key.to_s.tr('.'.freeze, '/'.freeze)
|
7
|
+
else
|
8
|
+
klass.model_name.i18n_key.to_s.freeze
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ransack
|
2
|
+
class Visitor
|
3
|
+
def visit_and(object)
|
4
|
+
nodes = object.values.map { |o| accept(o) }.compact
|
5
|
+
return nil unless nodes.size > 0
|
6
|
+
|
7
|
+
if nodes.size > 1
|
8
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::And.new(nodes))
|
9
|
+
else
|
10
|
+
nodes.first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def quoted?(object)
|
15
|
+
case object
|
16
|
+
when Arel::Nodes::SqlLiteral, Bignum, Fixnum
|
17
|
+
false
|
18
|
+
else
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'ransack/adapters/mongoid/base'
|
2
|
+
::Mongoid::Document.send :include, Ransack::Adapters::Mongoid::Base
|
3
|
+
|
4
|
+
require 'ransack/adapters/mongoid/attributes/attribute'
|
5
|
+
require 'ransack/adapters/mongoid/table'
|
6
|
+
require 'ransack/adapters/mongoid/inquiry_hash'
|
7
|
+
|
8
|
+
case ::Mongoid::VERSION
|
9
|
+
when /^3\.2\./
|
10
|
+
require 'ransack/adapters/mongoid/3.2/context'
|
11
|
+
else
|
12
|
+
require 'ransack/adapters/mongoid/context'
|
13
|
+
end
|
File without changes
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'ransack/adapters/mongoid/attributes/predications'
|
2
|
+
require 'ransack/adapters/mongoid/attributes/order_predications'
|
3
|
+
|
4
|
+
module Ransack
|
5
|
+
module Adapters
|
6
|
+
module Mongoid
|
7
|
+
module Attributes
|
8
|
+
class Attribute < Struct.new :relation, :name
|
9
|
+
# include Arel::Expressions
|
10
|
+
# include Arel::Predications
|
11
|
+
# include Arel::AliasPredication
|
12
|
+
# include Arel::OrderPredications
|
13
|
+
# include Arel::Math
|
14
|
+
|
15
|
+
include ::Ransack::Adapters::Mongoid::Attributes::Predications
|
16
|
+
include ::Ransack::Adapters::Mongoid::Attributes::OrderPredications
|
17
|
+
|
18
|
+
###
|
19
|
+
# Create a node for lowering this attribute
|
20
|
+
def lower
|
21
|
+
relation.lower self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class String < Attribute; end
|
26
|
+
class Time < Attribute; end
|
27
|
+
class Boolean < Attribute; end
|
28
|
+
class Decimal < Attribute; end
|
29
|
+
class Float < Attribute; end
|
30
|
+
class Integer < Attribute; end
|
31
|
+
class Undefined < Attribute; end
|
32
|
+
end
|
33
|
+
|
34
|
+
Attribute = Attributes::Attribute
|
35
|
+
end # Attributes
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Ransack
|
2
|
+
module Adapters
|
3
|
+
module Mongoid
|
4
|
+
module Attributes
|
5
|
+
module Predications
|
6
|
+
def not_eq(other)
|
7
|
+
{ name => { '$ne' => other } }.to_inquiry
|
8
|
+
end
|
9
|
+
|
10
|
+
def not_eq_any(others)
|
11
|
+
grouping_any :not_eq, others
|
12
|
+
end
|
13
|
+
|
14
|
+
def not_eq_all(others)
|
15
|
+
grouping_all :not_eq, others
|
16
|
+
end
|
17
|
+
|
18
|
+
def eq(other)
|
19
|
+
{ name => other }.to_inquiry
|
20
|
+
end
|
21
|
+
|
22
|
+
def eq_any(others)
|
23
|
+
grouping_any :eq, others
|
24
|
+
end
|
25
|
+
|
26
|
+
def eq_all(others)
|
27
|
+
grouping_all :eq, others
|
28
|
+
end
|
29
|
+
|
30
|
+
def in(other)
|
31
|
+
{ name => { "$in" => other } }.to_inquiry
|
32
|
+
end
|
33
|
+
|
34
|
+
def in_any(others)
|
35
|
+
grouping_any :in, others
|
36
|
+
end
|
37
|
+
|
38
|
+
def in_all(others)
|
39
|
+
grouping_all :in, others
|
40
|
+
end
|
41
|
+
|
42
|
+
def not_in(other)
|
43
|
+
{ "$not" => { name => { "$in" => other } } }.to_inquiry
|
44
|
+
end
|
45
|
+
|
46
|
+
def not_in_any(others)
|
47
|
+
grouping_any :not_in, others
|
48
|
+
end
|
49
|
+
|
50
|
+
def not_in_all(others)
|
51
|
+
grouping_all :not_in, others
|
52
|
+
end
|
53
|
+
|
54
|
+
def matches(other)
|
55
|
+
{ name => /#{other}/i }.to_inquiry
|
56
|
+
end
|
57
|
+
|
58
|
+
def matches_any(others)
|
59
|
+
grouping_any :matches, others
|
60
|
+
end
|
61
|
+
|
62
|
+
def matches_all(others)
|
63
|
+
grouping_all :matches, others
|
64
|
+
end
|
65
|
+
|
66
|
+
def does_not_match(other)
|
67
|
+
{ "$not" => { name => /#{other}/i } }.to_inquiry
|
68
|
+
end
|
69
|
+
|
70
|
+
def does_not_match_any(others)
|
71
|
+
grouping_any :does_not_match, others
|
72
|
+
end
|
73
|
+
|
74
|
+
def does_not_match_all(others)
|
75
|
+
grouping_all :does_not_match, others
|
76
|
+
end
|
77
|
+
|
78
|
+
def gteq(right)
|
79
|
+
{ name => { '$gte' => right } }.to_inquiry
|
80
|
+
end
|
81
|
+
|
82
|
+
def gteq_any(others)
|
83
|
+
grouping_any :gteq, others
|
84
|
+
end
|
85
|
+
|
86
|
+
def gteq_all(others)
|
87
|
+
grouping_all :gteq, others
|
88
|
+
end
|
89
|
+
|
90
|
+
def gt(right)
|
91
|
+
{ name => { '$gt' => right } }.to_inquiry
|
92
|
+
end
|
93
|
+
|
94
|
+
def gt_any(others)
|
95
|
+
grouping_any :gt, others
|
96
|
+
end
|
97
|
+
|
98
|
+
def gt_all(others)
|
99
|
+
grouping_all :gt, others
|
100
|
+
end
|
101
|
+
|
102
|
+
def lt(right)
|
103
|
+
{ name => { '$lt' => right } }.to_inquiry
|
104
|
+
end
|
105
|
+
|
106
|
+
def lt_any(others)
|
107
|
+
grouping_any :lt, others
|
108
|
+
end
|
109
|
+
|
110
|
+
def lt_all(others)
|
111
|
+
grouping_all :lt, others
|
112
|
+
end
|
113
|
+
|
114
|
+
def lteq(right)
|
115
|
+
{ name => { '$lte' => right } }.to_inquiry
|
116
|
+
end
|
117
|
+
|
118
|
+
def lteq_any(others)
|
119
|
+
grouping_any :lteq, others
|
120
|
+
end
|
121
|
+
|
122
|
+
def lteq_all(others)
|
123
|
+
grouping_all :lteq, others
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def grouping_any(method_id, others)
|
129
|
+
nodes = others.map { |e| send(method_id, e) }
|
130
|
+
{ "$or" => nodes }.to_inquiry
|
131
|
+
end
|
132
|
+
|
133
|
+
def grouping_all(method_id, others)
|
134
|
+
nodes = others.map { |e| send(method_id, e) }
|
135
|
+
{ "$and" => nodes }.to_inquiry
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Ransack
|
4
|
+
module Adapters
|
5
|
+
module Mongoid
|
6
|
+
module Base
|
7
|
+
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
end
|
12
|
+
|
13
|
+
class ColumnWrapper < SimpleDelegator
|
14
|
+
def type
|
15
|
+
_super = super
|
16
|
+
case _super
|
17
|
+
when BSON::ObjectId, Object
|
18
|
+
:string
|
19
|
+
else
|
20
|
+
_super.name.underscore.to_sym
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Connection
|
26
|
+
def initialize model
|
27
|
+
@model = model
|
28
|
+
end
|
29
|
+
|
30
|
+
def quote_column_name name
|
31
|
+
name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
def _ransackers
|
37
|
+
@_ransackers ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def _ransackers=(value)
|
41
|
+
@_ransackers = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def ransack(params = {}, options = {})
|
45
|
+
params = params.presence || {}
|
46
|
+
Search.new(self, params ? params.delete_if {
|
47
|
+
|k, v| v.blank? && v != false } : params, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_method :search, :ransack
|
51
|
+
|
52
|
+
def ransacker(name, opts = {}, &block)
|
53
|
+
self._ransackers = _ransackers.merge name.to_s => Ransacker
|
54
|
+
.new(self, name, opts, &block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def all_ransackable_attributes
|
58
|
+
['id'] + column_names.select { |c| c != '_id' } + _ransackers.keys
|
59
|
+
end
|
60
|
+
|
61
|
+
def ransackable_attributes(auth_object = nil)
|
62
|
+
all_ransackable_attributes
|
63
|
+
end
|
64
|
+
|
65
|
+
def ransortable_attributes(auth_object = nil)
|
66
|
+
# Here so users can overwrite the attributes
|
67
|
+
# that show up in the sort_select
|
68
|
+
ransackable_attributes(auth_object)
|
69
|
+
end
|
70
|
+
|
71
|
+
def ransackable_associations(auth_object = nil)
|
72
|
+
reflect_on_all_associations_all.map { |a| a.name.to_s }
|
73
|
+
end
|
74
|
+
|
75
|
+
def reflect_on_all_associations_all
|
76
|
+
reflect_on_all_associations(:belongs_to, :has_one, :has_many)
|
77
|
+
end
|
78
|
+
|
79
|
+
# For overriding with a whitelist of symbols
|
80
|
+
def ransackable_scopes(auth_object = nil)
|
81
|
+
[]
|
82
|
+
end
|
83
|
+
|
84
|
+
# imitating active record
|
85
|
+
|
86
|
+
def joins_values *args
|
87
|
+
[]
|
88
|
+
end
|
89
|
+
|
90
|
+
def first(*args)
|
91
|
+
if args.size == 0
|
92
|
+
super
|
93
|
+
else
|
94
|
+
self.criteria.limit(args.first)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# def group_by *args, &block
|
99
|
+
# criteria
|
100
|
+
# end
|
101
|
+
|
102
|
+
def columns
|
103
|
+
@columns ||= fields.map(&:second).map{ |c| ColumnWrapper.new(c) }
|
104
|
+
end
|
105
|
+
|
106
|
+
def column_names
|
107
|
+
@column_names ||= fields.map(&:first)
|
108
|
+
end
|
109
|
+
|
110
|
+
def columns_hash
|
111
|
+
columns.index_by(&:name)
|
112
|
+
end
|
113
|
+
|
114
|
+
def table
|
115
|
+
name = ::Ransack::Adapters::Mongoid::Attributes::Attribute.new(self.criteria, :name)
|
116
|
+
{
|
117
|
+
:name => name
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end # Base
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|