ransack 1.7.0 → 2.4.1
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 +5 -5
- data/.github/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/test.yml +120 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +463 -27
- data/CONTRIBUTING.md +52 -22
- data/Gemfile +24 -24
- data/README.md +453 -126
- data/Rakefile +6 -25
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +24 -0
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +79 -0
- data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +11 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +80 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +74 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +93 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/join.rb +70 -0
- data/lib/polyamorous/polyamorous.rb +24 -0
- data/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/lib/polyamorous/tree_node.rb +7 -0
- data/lib/ransack/adapters/active_record/base.rb +27 -2
- data/lib/ransack/adapters/active_record/context.rb +213 -139
- data/lib/ransack/adapters/active_record/ransack/constants.rb +70 -55
- data/lib/ransack/adapters/active_record/ransack/context.rb +10 -18
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +42 -32
- data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +23 -0
- data/lib/ransack/adapters/active_record.rb +11 -10
- data/lib/ransack/adapters.rb +45 -23
- data/lib/ransack/configuration.rb +107 -4
- data/lib/ransack/constants.rb +13 -26
- data/lib/ransack/context.rb +45 -33
- data/lib/ransack/helpers/form_builder.rb +21 -12
- data/lib/ransack/helpers/form_helper.rb +75 -70
- data/lib/ransack/locale/ar.yml +70 -0
- data/lib/ransack/locale/az.yml +70 -0
- data/lib/ransack/locale/bg.yml +70 -0
- data/lib/ransack/locale/ca.yml +70 -0
- data/lib/ransack/locale/da.yml +70 -0
- data/lib/ransack/locale/el.yml +70 -0
- data/lib/ransack/locale/es.yml +22 -22
- data/lib/ransack/locale/fa.yml +70 -0
- data/lib/ransack/locale/fi.yml +71 -0
- data/lib/ransack/locale/id.yml +70 -0
- data/lib/ransack/locale/it.yml +70 -0
- data/lib/ransack/locale/ja.yml +70 -0
- data/lib/ransack/locale/nl.yml +4 -4
- data/lib/ransack/locale/pt-BR.yml +70 -0
- data/lib/ransack/locale/ru.yml +70 -0
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/locale/tr.yml +70 -0
- data/lib/ransack/locale/{zh.yml → zh-CN.yml} +13 -13
- data/lib/ransack/locale/zh-TW.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +5 -2
- data/lib/ransack/nodes/bindable.rb +18 -6
- data/lib/ransack/nodes/condition.rb +85 -28
- data/lib/ransack/nodes/grouping.rb +17 -11
- data/lib/ransack/nodes/sort.rb +9 -5
- data/lib/ransack/nodes/value.rb +74 -68
- data/lib/ransack/nodes.rb +1 -1
- data/lib/ransack/predicate.rb +17 -20
- data/lib/ransack/search.rb +17 -8
- data/lib/ransack/translate.rb +115 -115
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +1 -12
- data/lib/ransack.rb +9 -9
- data/logo/ransack-h.png +0 -0
- data/logo/ransack-h.svg +34 -0
- data/logo/ransack-v.png +0 -0
- data/logo/ransack-v.svg +34 -0
- data/logo/ransack.png +0 -0
- data/logo/ransack.svg +21 -0
- data/ransack.gemspec +7 -24
- data/spec/console.rb +4 -0
- data/spec/helpers/polyamorous_helper.rb +19 -0
- data/spec/polyamorous/join_association_spec.rb +35 -0
- data/spec/polyamorous/join_dependency_spec.rb +97 -0
- data/spec/polyamorous/join_spec.rb +19 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +370 -75
- data/spec/ransack/adapters/active_record/context_spec.rb +72 -34
- data/spec/ransack/configuration_spec.rb +97 -14
- data/spec/ransack/helpers/form_builder_spec.rb +2 -11
- data/spec/ransack/helpers/form_helper_spec.rb +481 -113
- data/spec/ransack/nodes/condition_spec.rb +24 -0
- data/spec/ransack/nodes/grouping_spec.rb +56 -0
- data/spec/ransack/predicate_spec.rb +79 -5
- data/spec/ransack/search_spec.rb +207 -81
- data/spec/spec_helper.rb +8 -0
- data/spec/support/schema.rb +100 -42
- metadata +57 -184
- data/.travis.yml +0 -69
- data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
- data/lib/ransack/adapters/active_record/3.0/context.rb +0 -201
- data/lib/ransack/adapters/active_record/3.1/context.rb +0 -215
- data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
- data/lib/ransack/adapters/active_record/compat.rb +0 -14
- data/lib/ransack/adapters/mongoid/3.2/.gitkeep +0 -0
- data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
- data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
- data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
- data/lib/ransack/adapters/mongoid/base.rb +0 -130
- data/lib/ransack/adapters/mongoid/context.rb +0 -208
- data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
- data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
- data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -60
- data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -27
- data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
- data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -24
- data/lib/ransack/adapters/mongoid/table.rb +0 -35
- data/lib/ransack/adapters/mongoid.rb +0 -13
- data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -276
- data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
- data/spec/mongoid/configuration_spec.rb +0 -102
- data/spec/mongoid/dependencies_spec.rb +0 -8
- data/spec/mongoid/helpers/ransack_helper.rb +0 -11
- data/spec/mongoid/nodes/condition_spec.rb +0 -34
- data/spec/mongoid/nodes/grouping_spec.rb +0 -13
- data/spec/mongoid/predicate_spec.rb +0 -155
- data/spec/mongoid/search_spec.rb +0 -446
- data/spec/mongoid/support/mongoid.yml +0 -6
- data/spec/mongoid/support/schema.rb +0 -128
- data/spec/mongoid/translate_spec.rb +0 -14
- data/spec/mongoid_spec_helper.rb +0 -59
- data/spec/ransack/dependencies_spec.rb +0 -12
data/spec/ransack/search_spec.rb
CHANGED
|
@@ -20,6 +20,12 @@ module Ransack
|
|
|
20
20
|
Search.new(Person, name_eq: 'foobar')
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
it 'strip leading & trailing whitespace before building' do
|
|
24
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
25
|
+
.with({ 'name_eq' => 'foobar' })
|
|
26
|
+
Search.new(Person, name_eq: ' foobar ')
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
it 'removes empty suffixed conditions before building' do
|
|
24
30
|
expect_any_instance_of(Search).to receive(:build).with({})
|
|
25
31
|
Search.new(Person, name_eq_any: [''])
|
|
@@ -43,16 +49,16 @@ module Ransack
|
|
|
43
49
|
|
|
44
50
|
it 'accepts a context option' do
|
|
45
51
|
shared_context = Context.for(Person)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
expect(
|
|
52
|
+
s1 = Search.new(Person, { name_eq: 'A' }, context: shared_context)
|
|
53
|
+
s2 = Search.new(Person, { name_eq: 'B' }, context: shared_context)
|
|
54
|
+
expect(s1.context).to be s2.context
|
|
49
55
|
end
|
|
50
56
|
end
|
|
51
57
|
|
|
52
58
|
describe '#build' do
|
|
53
59
|
it 'creates conditions for top-level attributes' do
|
|
54
|
-
|
|
55
|
-
condition =
|
|
60
|
+
s = Search.new(Person, name_eq: 'Ernie')
|
|
61
|
+
condition = s.base[:name_eq]
|
|
56
62
|
expect(condition).to be_a Nodes::Condition
|
|
57
63
|
expect(condition.predicate.name).to eq 'eq'
|
|
58
64
|
expect(condition.attributes.first.name).to eq 'name'
|
|
@@ -60,8 +66,8 @@ module Ransack
|
|
|
60
66
|
end
|
|
61
67
|
|
|
62
68
|
it 'creates conditions for association attributes' do
|
|
63
|
-
|
|
64
|
-
condition =
|
|
69
|
+
s = Search.new(Person, children_name_eq: 'Ernie')
|
|
70
|
+
condition = s.base[:children_name_eq]
|
|
65
71
|
expect(condition).to be_a Nodes::Condition
|
|
66
72
|
expect(condition.predicate.name).to eq 'eq'
|
|
67
73
|
expect(condition.attributes.first.name).to eq 'children_name'
|
|
@@ -69,8 +75,8 @@ module Ransack
|
|
|
69
75
|
end
|
|
70
76
|
|
|
71
77
|
it 'creates conditions for polymorphic belongs_to association attributes' do
|
|
72
|
-
|
|
73
|
-
condition =
|
|
78
|
+
s = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie')
|
|
79
|
+
condition = s.base[:notable_of_Person_type_name_eq]
|
|
74
80
|
expect(condition).to be_a Nodes::Condition
|
|
75
81
|
expect(condition.predicate.name).to eq 'eq'
|
|
76
82
|
expect(condition.attributes.first.name)
|
|
@@ -80,9 +86,9 @@ module Ransack
|
|
|
80
86
|
|
|
81
87
|
it 'creates conditions for multiple polymorphic belongs_to association
|
|
82
88
|
attributes' do
|
|
83
|
-
|
|
89
|
+
s = Search.new(Note,
|
|
84
90
|
notable_of_Person_type_name_or_notable_of_Article_type_title_eq: 'Ernie')
|
|
85
|
-
condition =
|
|
91
|
+
condition = s.
|
|
86
92
|
base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
|
|
87
93
|
expect(condition).to be_a Nodes::Condition
|
|
88
94
|
expect(condition.predicate.name).to eq 'eq'
|
|
@@ -93,15 +99,62 @@ module Ransack
|
|
|
93
99
|
expect(condition.value).to eq 'Ernie'
|
|
94
100
|
end
|
|
95
101
|
|
|
102
|
+
it 'creates conditions for aliased attributes',
|
|
103
|
+
if: Ransack::SUPPORTS_ATTRIBUTE_ALIAS do
|
|
104
|
+
s = Search.new(Person, full_name_eq: 'Ernie')
|
|
105
|
+
condition = s.base[:full_name_eq]
|
|
106
|
+
expect(condition).to be_a Nodes::Condition
|
|
107
|
+
expect(condition.predicate.name).to eq 'eq'
|
|
108
|
+
expect(condition.attributes.first.name).to eq 'full_name'
|
|
109
|
+
expect(condition.value).to eq 'Ernie'
|
|
110
|
+
end
|
|
111
|
+
|
|
96
112
|
it 'preserves default scope and conditions for associations' do
|
|
97
|
-
|
|
98
|
-
expect(
|
|
99
|
-
expect(
|
|
113
|
+
s = Search.new(Person, published_articles_title_eq: 'Test')
|
|
114
|
+
expect(s.result.to_sql).to include 'default_scope'
|
|
115
|
+
expect(s.result.to_sql).to include 'published'
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# The failure/oversight in Ransack::Nodes::Condition#arel_predicate or deeper is beyond my understanding of the structures
|
|
119
|
+
it 'preserves (inverts) default scope and conditions for negative subqueries' do
|
|
120
|
+
# the positive case (published_articles_title_eq) is
|
|
121
|
+
# SELECT "people".* FROM "people"
|
|
122
|
+
# LEFT OUTER JOIN "articles" ON "articles"."person_id" = "people"."id"
|
|
123
|
+
# AND "articles"."published" = 't'
|
|
124
|
+
# AND ('default_scope' = 'default_scope')
|
|
125
|
+
# WHERE "articles"."title" = 'Test' ORDER BY "people"."id" DESC
|
|
126
|
+
#
|
|
127
|
+
# negative case was
|
|
128
|
+
# SELECT "people".* FROM "people" WHERE "people"."id" NOT IN (
|
|
129
|
+
# SELECT "articles"."person_id" FROM "articles"
|
|
130
|
+
# WHERE "articles"."person_id" = "people"."id"
|
|
131
|
+
# AND NOT ("articles"."title" != 'Test')
|
|
132
|
+
# ) ORDER BY "people"."id" DESC
|
|
133
|
+
#
|
|
134
|
+
# Should have been like
|
|
135
|
+
# SELECT "people".* FROM "people" WHERE "people"."id" NOT IN (
|
|
136
|
+
# SELECT "articles"."person_id" FROM "articles"
|
|
137
|
+
# WHERE "articles"."person_id" = "people"."id"
|
|
138
|
+
# AND "articles"."title" = 'Test' AND "articles"."published" = 't' AND ('default_scope' = 'default_scope')
|
|
139
|
+
# ) ORDER BY "people"."id" DESC
|
|
140
|
+
#
|
|
141
|
+
# With tenanting (eg default_scope with column reference), NOT IN should be like
|
|
142
|
+
# SELECT "people".* FROM "people" WHERE "people"."tenant_id" = 'tenant_id' AND "people"."id" NOT IN (
|
|
143
|
+
# SELECT "articles"."person_id" FROM "articles"
|
|
144
|
+
# WHERE "articles"."person_id" = "people"."id"
|
|
145
|
+
# AND "articles"."tenant_id" = 'tenant_id'
|
|
146
|
+
# AND "articles"."title" = 'Test' AND "articles"."published" = 't' AND ('default_scope' = 'default_scope')
|
|
147
|
+
# ) ORDER BY "people"."id" DESC
|
|
148
|
+
|
|
149
|
+
pending("spec should pass, but I do not know how/where to fix lib code")
|
|
150
|
+
s = Search.new(Person, published_articles_title_not_eq: 'Test')
|
|
151
|
+
expect(s.result.to_sql).to include 'default_scope'
|
|
152
|
+
expect(s.result.to_sql).to include 'published'
|
|
100
153
|
end
|
|
101
154
|
|
|
102
155
|
it 'discards empty conditions' do
|
|
103
|
-
|
|
104
|
-
condition =
|
|
156
|
+
s = Search.new(Person, children_name_eq: '')
|
|
157
|
+
condition = s.base[:children_name_eq]
|
|
105
158
|
expect(condition).to be_nil
|
|
106
159
|
end
|
|
107
160
|
|
|
@@ -111,13 +164,13 @@ module Ransack
|
|
|
111
164
|
end
|
|
112
165
|
|
|
113
166
|
it 'accepts arrays of groupings' do
|
|
114
|
-
|
|
167
|
+
s = Search.new(Person,
|
|
115
168
|
g: [
|
|
116
169
|
{ m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
|
|
117
170
|
{ m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' },
|
|
118
171
|
]
|
|
119
172
|
)
|
|
120
|
-
ors =
|
|
173
|
+
ors = s.groupings
|
|
121
174
|
expect(ors.size).to eq(2)
|
|
122
175
|
or1, or2 = ors
|
|
123
176
|
expect(or1).to be_a Nodes::Grouping
|
|
@@ -126,14 +179,14 @@ module Ransack
|
|
|
126
179
|
expect(or2.combinator).to eq 'or'
|
|
127
180
|
end
|
|
128
181
|
|
|
129
|
-
it 'accepts
|
|
130
|
-
|
|
182
|
+
it 'accepts attributes hashes for groupings' do
|
|
183
|
+
s = Search.new(Person,
|
|
131
184
|
g: {
|
|
132
185
|
'0' => { m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
|
|
133
186
|
'1' => { m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' },
|
|
134
187
|
}
|
|
135
188
|
)
|
|
136
|
-
ors =
|
|
189
|
+
ors = s.groupings
|
|
137
190
|
expect(ors.size).to eq(2)
|
|
138
191
|
or1, or2 = ors
|
|
139
192
|
expect(or1).to be_a Nodes::Grouping
|
|
@@ -142,8 +195,8 @@ module Ransack
|
|
|
142
195
|
expect(or2.combinator).to eq 'or'
|
|
143
196
|
end
|
|
144
197
|
|
|
145
|
-
it 'accepts
|
|
146
|
-
|
|
198
|
+
it 'accepts attributes hashes for conditions' do
|
|
199
|
+
s = Search.new(Person,
|
|
147
200
|
c: {
|
|
148
201
|
'0' => { a: ['name'], p: 'eq', v: ['Ernie'] },
|
|
149
202
|
'1' => {
|
|
@@ -152,7 +205,7 @@ module Ransack
|
|
|
152
205
|
}
|
|
153
206
|
}
|
|
154
207
|
)
|
|
155
|
-
conditions =
|
|
208
|
+
conditions = s.base.conditions
|
|
156
209
|
expect(conditions.size).to eq(2)
|
|
157
210
|
expect(conditions.map { |c| c.class })
|
|
158
211
|
.to eq [Nodes::Condition, Nodes::Condition]
|
|
@@ -163,8 +216,8 @@ module Ransack
|
|
|
163
216
|
config.add_predicate 'ary_pred', wants_array: true
|
|
164
217
|
end
|
|
165
218
|
|
|
166
|
-
|
|
167
|
-
condition =
|
|
219
|
+
s = Search.new(Person, name_ary_pred: ['Ernie', 'Bert'])
|
|
220
|
+
condition = s.base[:name_ary_pred]
|
|
168
221
|
expect(condition).to be_a Nodes::Condition
|
|
169
222
|
expect(condition.predicate.name).to eq 'ary_pred'
|
|
170
223
|
expect(condition.attributes.first.name).to eq 'name'
|
|
@@ -172,14 +225,14 @@ module Ransack
|
|
|
172
225
|
end
|
|
173
226
|
|
|
174
227
|
it 'does not evaluate the query on #inspect' do
|
|
175
|
-
|
|
176
|
-
expect(
|
|
228
|
+
s = Search.new(Person, children_id_in: [1, 2, 3])
|
|
229
|
+
expect(s.inspect).not_to match /ActiveRecord/
|
|
177
230
|
end
|
|
178
231
|
|
|
179
232
|
context 'with an invalid condition' do
|
|
180
233
|
subject { Search.new(Person, unknown_attr_eq: 'Ernie') }
|
|
181
234
|
|
|
182
|
-
context 'when ignore_unknown_conditions is false' do
|
|
235
|
+
context 'when ignore_unknown_conditions configuration option is false' do
|
|
183
236
|
before do
|
|
184
237
|
Ransack.configure { |c| c.ignore_unknown_conditions = false }
|
|
185
238
|
end
|
|
@@ -187,13 +240,39 @@ module Ransack
|
|
|
187
240
|
specify { expect { subject }.to raise_error ArgumentError }
|
|
188
241
|
end
|
|
189
242
|
|
|
190
|
-
context 'when ignore_unknown_conditions is true' do
|
|
243
|
+
context 'when ignore_unknown_conditions configuration option is true' do
|
|
191
244
|
before do
|
|
192
245
|
Ransack.configure { |c| c.ignore_unknown_conditions = true }
|
|
193
246
|
end
|
|
194
247
|
|
|
195
248
|
specify { expect { subject }.not_to raise_error }
|
|
196
249
|
end
|
|
250
|
+
|
|
251
|
+
subject(:with_ignore_unknown_conditions_false) {
|
|
252
|
+
Search.new(Person,
|
|
253
|
+
{ unknown_attr_eq: 'Ernie' },
|
|
254
|
+
{ ignore_unknown_conditions: false }
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
subject(:with_ignore_unknown_conditions_true) {
|
|
259
|
+
Search.new(Person,
|
|
260
|
+
{ unknown_attr_eq: 'Ernie' },
|
|
261
|
+
{ ignore_unknown_conditions: true }
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
context 'when ignore_unknown_conditions search parameter is absent' do
|
|
266
|
+
specify { expect { subject }.not_to raise_error }
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
context 'when ignore_unknown_conditions search parameter is false' do
|
|
270
|
+
specify { expect { with_ignore_unknown_conditions_false }.to raise_error ArgumentError }
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
context 'when ignore_unknown_conditions search parameter is true' do
|
|
274
|
+
specify { expect { with_ignore_unknown_conditions_true }.not_to raise_error }
|
|
275
|
+
end
|
|
197
276
|
end
|
|
198
277
|
|
|
199
278
|
it 'does not modify the parameters' do
|
|
@@ -210,62 +289,86 @@ module Ransack
|
|
|
210
289
|
let(:children_people_name_field) {
|
|
211
290
|
"#{quote_table_name("children_people")}.#{quote_column_name("name")}"
|
|
212
291
|
}
|
|
292
|
+
let(:notable_type_field) {
|
|
293
|
+
"#{quote_table_name("notes")}.#{quote_column_name("notable_type")}"
|
|
294
|
+
}
|
|
213
295
|
it 'evaluates conditions contextually' do
|
|
214
|
-
|
|
215
|
-
expect(
|
|
216
|
-
expect(
|
|
296
|
+
s = Search.new(Person, children_name_eq: 'Ernie')
|
|
297
|
+
expect(s.result).to be_an ActiveRecord::Relation
|
|
298
|
+
expect(s.result.to_sql).to match /#{
|
|
217
299
|
children_people_name_field} = 'Ernie'/
|
|
218
300
|
end
|
|
219
301
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
.
|
|
243
|
-
|
|
244
|
-
|
|
302
|
+
it 'use appropriate table alias' do
|
|
303
|
+
skip "Rails 6 regressed here, but it's fixed in 6-0-stable since https://github.com/rails/rails/commit/f9ba52477ca288e7effa5f6794ae3df3f4e982bc" if ENV["RAILS"] == "v6.0.3"
|
|
304
|
+
|
|
305
|
+
s = Search.new(Person, {
|
|
306
|
+
name_eq: "person_name_query",
|
|
307
|
+
articles_title_eq: "person_article_title_query",
|
|
308
|
+
parent_name_eq: "parent_name_query",
|
|
309
|
+
parent_articles_title_eq: 'parents_article_title_query'
|
|
310
|
+
}).result
|
|
311
|
+
|
|
312
|
+
real_query = remove_quotes_and_backticks(s.to_sql)
|
|
313
|
+
|
|
314
|
+
expect(real_query)
|
|
315
|
+
.to match(%r{LEFT OUTER JOIN articles ON (\('default_scope' = 'default_scope'\) AND )?articles.person_id = people.id})
|
|
316
|
+
expect(real_query)
|
|
317
|
+
.to match(%r{LEFT OUTER JOIN articles articles_people ON (\('default_scope' = 'default_scope'\) AND )?articles_people.person_id = parents_people.id})
|
|
318
|
+
|
|
319
|
+
expect(real_query)
|
|
320
|
+
.to include "people.name = 'person_name_query'"
|
|
321
|
+
expect(real_query)
|
|
322
|
+
.to include "articles.title = 'person_article_title_query'"
|
|
323
|
+
expect(real_query)
|
|
324
|
+
.to include "parents_people.name = 'parent_name_query'"
|
|
325
|
+
expect(real_query)
|
|
326
|
+
.to include "articles_people.title = 'parents_article_title_query'"
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it 'evaluates conditions for multiple `belongs_to` associations to the same table contextually' do
|
|
330
|
+
s = Search.new(
|
|
331
|
+
Recommendation,
|
|
332
|
+
person_name_eq: 'Ernie',
|
|
333
|
+
target_person_parent_name_eq: 'Test'
|
|
334
|
+
).result
|
|
335
|
+
expect(s).to be_an ActiveRecord::Relation
|
|
336
|
+
real_query = remove_quotes_and_backticks(s.to_sql)
|
|
337
|
+
expected_query = <<-SQL
|
|
338
|
+
SELECT recommendations.* FROM recommendations
|
|
339
|
+
LEFT OUTER JOIN people ON people.id = recommendations.person_id
|
|
340
|
+
LEFT OUTER JOIN people target_people_recommendations
|
|
341
|
+
ON target_people_recommendations.id = recommendations.target_person_id
|
|
342
|
+
LEFT OUTER JOIN people parents_people
|
|
343
|
+
ON parents_people.id = target_people_recommendations.parent_id
|
|
344
|
+
WHERE (people.name = 'Ernie' AND parents_people.name = 'Test')
|
|
345
|
+
SQL
|
|
346
|
+
.squish
|
|
347
|
+
expect(real_query).to eq expected_query
|
|
245
348
|
end
|
|
246
349
|
|
|
247
350
|
it 'evaluates compound conditions contextually' do
|
|
248
|
-
|
|
249
|
-
expect(
|
|
250
|
-
expect(
|
|
351
|
+
s = Search.new(Person, children_name_or_name_eq: 'Ernie').result
|
|
352
|
+
expect(s).to be_an ActiveRecord::Relation
|
|
353
|
+
expect(s.to_sql).to match /#{children_people_name_field
|
|
251
354
|
} = 'Ernie' OR #{people_name_field} = 'Ernie'/
|
|
252
355
|
end
|
|
253
356
|
|
|
254
357
|
it 'evaluates polymorphic belongs_to association conditions contextually' do
|
|
255
|
-
|
|
256
|
-
.
|
|
257
|
-
expect(
|
|
258
|
-
expect(
|
|
358
|
+
s = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie').result
|
|
359
|
+
expect(s).to be_an ActiveRecord::Relation
|
|
360
|
+
expect(s.to_sql).to match /#{people_name_field} = 'Ernie'/
|
|
361
|
+
expect(s.to_sql).to match /#{notable_type_field} = 'Person'/
|
|
259
362
|
end
|
|
260
363
|
|
|
261
364
|
it 'evaluates nested conditions' do
|
|
262
|
-
|
|
365
|
+
s = Search.new(Person, children_name_eq: 'Ernie',
|
|
263
366
|
g: [
|
|
264
367
|
{ m: 'or', name_eq: 'Ernie', children_children_name_eq: 'Ernie' }
|
|
265
368
|
]
|
|
266
369
|
).result
|
|
267
|
-
expect(
|
|
268
|
-
first, last =
|
|
370
|
+
expect(s).to be_an ActiveRecord::Relation
|
|
371
|
+
first, last = s.to_sql.split(/ AND /)
|
|
269
372
|
expect(first).to match /#{children_people_name_field} = 'Ernie'/
|
|
270
373
|
expect(last).to match /#{
|
|
271
374
|
people_name_field} = 'Ernie' OR #{
|
|
@@ -274,14 +377,14 @@ module Ransack
|
|
|
274
377
|
end
|
|
275
378
|
|
|
276
379
|
it 'evaluates arrays of groupings' do
|
|
277
|
-
|
|
380
|
+
s = Search.new(Person,
|
|
278
381
|
g: [
|
|
279
382
|
{ m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
|
|
280
383
|
{ m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' }
|
|
281
384
|
]
|
|
282
385
|
).result
|
|
283
|
-
expect(
|
|
284
|
-
first, last =
|
|
386
|
+
expect(s).to be_an ActiveRecord::Relation
|
|
387
|
+
first, last = s.to_sql.split(/ AND /)
|
|
285
388
|
expect(first).to match /#{people_name_field} = 'Ernie' OR #{
|
|
286
389
|
children_people_name_field} = 'Ernie'/
|
|
287
390
|
expect(last).to match /#{people_name_field} = 'Bert' OR #{
|
|
@@ -289,22 +392,24 @@ module Ransack
|
|
|
289
392
|
end
|
|
290
393
|
|
|
291
394
|
it 'returns distinct records when passed distinct: true' do
|
|
292
|
-
|
|
395
|
+
s = Search.new(Person,
|
|
293
396
|
g: [
|
|
294
397
|
{ m: 'or', comments_body_cont: 'e', articles_comments_body_cont: 'e' }
|
|
295
398
|
]
|
|
296
399
|
)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
all_or_load, uniq_or_distinct = :load, :distinct
|
|
301
|
-
end
|
|
302
|
-
expect(search.result.send(all_or_load).size)
|
|
400
|
+
|
|
401
|
+
all_or_load, uniq_or_distinct = :load, :distinct
|
|
402
|
+
expect(s.result.send(all_or_load).size)
|
|
303
403
|
.to eq(9000)
|
|
304
|
-
expect(
|
|
404
|
+
expect(s.result(distinct: true).size)
|
|
305
405
|
.to eq(10)
|
|
306
|
-
expect(
|
|
307
|
-
.to eq
|
|
406
|
+
expect(s.result.send(all_or_load).send(uniq_or_distinct))
|
|
407
|
+
.to eq s.result(distinct: true).send(all_or_load)
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
it 'evaluates joins with belongs_to join' do
|
|
411
|
+
s = Person.joins(:parent).ransack(parent_name_eq: 'Ernie').result(distinct: true)
|
|
412
|
+
expect(s).to be_an ActiveRecord::Relation
|
|
308
413
|
end
|
|
309
414
|
|
|
310
415
|
private
|
|
@@ -428,6 +533,27 @@ module Ransack
|
|
|
428
533
|
@s.sorts = 'id asc'
|
|
429
534
|
expect(@s.result.first.id).to eq 1
|
|
430
535
|
end
|
|
536
|
+
|
|
537
|
+
it "PG's sort option", if: ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" do
|
|
538
|
+
default = Ransack.options.clone
|
|
539
|
+
|
|
540
|
+
s = Search.new(Person, s: 'name asc')
|
|
541
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" ASC"
|
|
542
|
+
|
|
543
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_first }
|
|
544
|
+
s = Search.new(Person, s: 'name asc')
|
|
545
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" ASC NULLS FIRST"
|
|
546
|
+
s = Search.new(Person, s: 'name desc')
|
|
547
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" DESC NULLS LAST"
|
|
548
|
+
|
|
549
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_last }
|
|
550
|
+
s = Search.new(Person, s: 'name asc')
|
|
551
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" ASC NULLS LAST"
|
|
552
|
+
s = Search.new(Person, s: 'name desc')
|
|
553
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" DESC NULLS FIRST"
|
|
554
|
+
|
|
555
|
+
Ransack.options = default
|
|
556
|
+
end
|
|
431
557
|
end
|
|
432
558
|
|
|
433
559
|
describe '#method_missing' do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
require 'machinist/active_record'
|
|
2
|
+
require 'polyamorous/polyamorous.rb'
|
|
2
3
|
require 'sham'
|
|
3
4
|
require 'faker'
|
|
4
5
|
require 'ransack'
|
|
6
|
+
require 'action_controller'
|
|
7
|
+
require 'ransack/helpers'
|
|
5
8
|
require 'pry'
|
|
9
|
+
require 'simplecov'
|
|
10
|
+
require 'byebug'
|
|
6
11
|
|
|
12
|
+
SimpleCov.start
|
|
7
13
|
I18n.enforce_available_locales = false
|
|
8
14
|
Time.zone = 'Eastern Time (US & Canada)'
|
|
9
15
|
I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'support', '*.yml')]
|
|
@@ -35,12 +41,14 @@ RSpec.configure do |config|
|
|
|
35
41
|
line = '=' * message.length
|
|
36
42
|
puts line, message, line
|
|
37
43
|
Schema.create
|
|
44
|
+
SubDB::Schema.create
|
|
38
45
|
end
|
|
39
46
|
|
|
40
47
|
config.before(:all) { Sham.reset(:before_all) }
|
|
41
48
|
config.before(:each) { Sham.reset(:before_each) }
|
|
42
49
|
|
|
43
50
|
config.include RansackHelper
|
|
51
|
+
config.include PolyamorousHelper
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
RSpec::Matchers.define :be_like do |expected|
|