mini-fast-sys 0.0.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 +7 -0
- data/mini-fast-sys.gemspec +12 -0
- data/ransack-4.4.1/LICENSE +20 -0
- data/ransack-4.4.1/README.md +101 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/join_association.rb +70 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/join_association_7_2.rb +55 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/join_dependency.rb +102 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/reflection.rb +11 -0
- data/ransack-4.4.1/lib/polyamorous/join.rb +70 -0
- data/ransack-4.4.1/lib/polyamorous/polyamorous.rb +27 -0
- data/ransack-4.4.1/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/ransack-4.4.1/lib/polyamorous/tree_node.rb +7 -0
- data/ransack-4.4.1/lib/ransack/active_record.rb +14 -0
- data/ransack-4.4.1/lib/ransack/adapters/active_record/base.rb +152 -0
- data/ransack-4.4.1/lib/ransack/adapters/active_record/context.rb +373 -0
- data/ransack-4.4.1/lib/ransack/configuration.rb +209 -0
- data/ransack-4.4.1/lib/ransack/constants.rb +176 -0
- data/ransack-4.4.1/lib/ransack/context.rb +190 -0
- data/ransack-4.4.1/lib/ransack/helpers/form_builder.rb +277 -0
- data/ransack-4.4.1/lib/ransack/helpers/form_helper.rb +311 -0
- data/ransack-4.4.1/lib/ransack/helpers.rb +2 -0
- data/ransack-4.4.1/lib/ransack/invalid_search_error.rb +3 -0
- data/ransack-4.4.1/lib/ransack/locale/ar.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/az.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/bg.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ca.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/cs.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/da.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/de.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/el.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/en.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/es.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/fa.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/fi.yml +71 -0
- data/ransack-4.4.1/lib/ransack/locale/fr.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/hu.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/id.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/it.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ja.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ko.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/nl.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/pt-BR.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ro.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ru.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/sk.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/sv.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/tr.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/uk.yml +72 -0
- data/ransack-4.4.1/lib/ransack/locale/zh-CN.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/zh-TW.yml +70 -0
- data/ransack-4.4.1/lib/ransack/naming.rb +58 -0
- data/ransack-4.4.1/lib/ransack/nodes/attribute.rb +59 -0
- data/ransack-4.4.1/lib/ransack/nodes/bindable.rb +52 -0
- data/ransack-4.4.1/lib/ransack/nodes/condition.rb +399 -0
- data/ransack-4.4.1/lib/ransack/nodes/grouping.rb +206 -0
- data/ransack-4.4.1/lib/ransack/nodes/node.rb +34 -0
- data/ransack-4.4.1/lib/ransack/nodes/sort.rb +54 -0
- data/ransack-4.4.1/lib/ransack/nodes/value.rb +115 -0
- data/ransack-4.4.1/lib/ransack/predicate.rb +75 -0
- data/ransack-4.4.1/lib/ransack/ransacker.rb +24 -0
- data/ransack-4.4.1/lib/ransack/search.rb +195 -0
- data/ransack-4.4.1/lib/ransack/translate.rb +156 -0
- data/ransack-4.4.1/lib/ransack/version.rb +3 -0
- data/ransack-4.4.1/lib/ransack/visitor.rb +87 -0
- data/ransack-4.4.1/lib/ransack.rb +33 -0
- data/ransack-4.4.1/spec/console.rb +13 -0
- data/ransack-4.4.1/spec/factories/articles.rb +7 -0
- data/ransack-4.4.1/spec/factories/comments.rb +7 -0
- data/ransack-4.4.1/spec/factories/notes.rb +13 -0
- data/ransack-4.4.1/spec/factories/people.rb +10 -0
- data/ransack-4.4.1/spec/factories/tags.rb +5 -0
- data/ransack-4.4.1/spec/helpers/polyamorous_helper.rb +13 -0
- data/ransack-4.4.1/spec/helpers/ransack_helper.rb +9 -0
- data/ransack-4.4.1/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/ransack-4.4.1/spec/polyamorous/join_association_spec.rb +29 -0
- data/ransack-4.4.1/spec/polyamorous/join_dependency_spec.rb +80 -0
- data/ransack-4.4.1/spec/polyamorous/join_spec.rb +19 -0
- data/ransack-4.4.1/spec/ransack/adapters/active_record/base_spec.rb +943 -0
- data/ransack-4.4.1/spec/ransack/adapters/active_record/context_spec.rb +219 -0
- data/ransack-4.4.1/spec/ransack/configuration_spec.rb +201 -0
- data/ransack-4.4.1/spec/ransack/helpers/form_builder_spec.rb +169 -0
- data/ransack-4.4.1/spec/ransack/helpers/form_helper_spec.rb +1075 -0
- data/ransack-4.4.1/spec/ransack/invalid_search_error_spec.rb +27 -0
- data/ransack-4.4.1/spec/ransack/nodes/condition_spec.rb +333 -0
- data/ransack-4.4.1/spec/ransack/nodes/grouping_spec.rb +111 -0
- data/ransack-4.4.1/spec/ransack/nodes/value_spec.rb +126 -0
- data/ransack-4.4.1/spec/ransack/predicate_spec.rb +504 -0
- data/ransack-4.4.1/spec/ransack/ransacker_spec.rb +69 -0
- data/ransack-4.4.1/spec/ransack/search_spec.rb +821 -0
- data/ransack-4.4.1/spec/ransack/translate_spec.rb +16 -0
- data/ransack-4.4.1/spec/spec_helper.rb +52 -0
- data/ransack-4.4.1/spec/support/en.yml +18 -0
- data/ransack-4.4.1/spec/support/schema.rb +419 -0
- metadata +133 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Ransack
|
|
4
|
+
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
|
|
5
|
+
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
|
|
6
|
+
|
|
7
|
+
describe Predicate do
|
|
8
|
+
before do
|
|
9
|
+
@s = Search.new(Person)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
shared_examples 'wildcard escaping' do |method, regexp|
|
|
13
|
+
it 'automatically converts integers to strings' do
|
|
14
|
+
subject.parent_id_cont = 1
|
|
15
|
+
expect { subject.result }.to_not raise_error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "escapes '%', '.', '_' and '\\\\' in value" do
|
|
19
|
+
subject.send(:"#{method}=", '%._\\')
|
|
20
|
+
expect(subject.result.to_sql).to match(regexp)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe 'eq' do
|
|
25
|
+
it 'generates an equality condition for boolean true values' do
|
|
26
|
+
test_boolean_equality_for(true)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'generates an equality condition for boolean false values' do
|
|
30
|
+
test_boolean_equality_for(false)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'does not generate a condition for nil' do
|
|
34
|
+
@s.awesome_eq = nil
|
|
35
|
+
expect(@s.result.to_sql).not_to match /WHERE/
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'generates a = condition with a huge integer value' do
|
|
39
|
+
val = 123456789012345678901
|
|
40
|
+
@s.salary_eq = val
|
|
41
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
42
|
+
expect(@s.result.to_sql).to match /#{field} = #{val}/
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe 'lteq' do
|
|
47
|
+
it 'generates a <= condition with an integer column' do
|
|
48
|
+
val = 1000
|
|
49
|
+
@s.salary_lteq = val
|
|
50
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
51
|
+
expect(@s.result.to_sql).to match /#{field} <= #{val}/
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'generates a <= condition with a string column' do
|
|
55
|
+
val = 'jane@doe.com'
|
|
56
|
+
@s.email_lteq = val
|
|
57
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("email")}"
|
|
58
|
+
expect(@s.result.to_sql).to match /#{field} <= '#{val}'/
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'does not generate a condition for nil' do
|
|
62
|
+
@s.salary_lteq = nil
|
|
63
|
+
expect(@s.result.to_sql).not_to match /WHERE/
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'generates a <= condition with a huge integer value' do
|
|
67
|
+
val = 123456789012345678901
|
|
68
|
+
@s.salary_lteq = val
|
|
69
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
70
|
+
expect(@s.result.to_sql).to match /#{field} <= #{val}/
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe 'lt' do
|
|
75
|
+
it 'generates a < condition with an integer column' do
|
|
76
|
+
val = 2000
|
|
77
|
+
@s.salary_lt = val
|
|
78
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
79
|
+
expect(@s.result.to_sql).to match /#{field} < #{val}/
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'generates a < condition with a string column' do
|
|
83
|
+
val = 'jane@doe.com'
|
|
84
|
+
@s.email_lt = val
|
|
85
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("email")}"
|
|
86
|
+
expect(@s.result.to_sql).to match /#{field} < '#{val}'/
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'does not generate a condition for nil' do
|
|
90
|
+
@s.salary_lt = nil
|
|
91
|
+
expect(@s.result.to_sql).not_to match /WHERE/
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'generates a = condition with a huge integer value' do
|
|
95
|
+
val = 123456789012345678901
|
|
96
|
+
@s.salary_lt = val
|
|
97
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
98
|
+
expect(@s.result.to_sql).to match /#{field} < #{val}/
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe 'gteq' do
|
|
103
|
+
it 'generates a >= condition with an integer column' do
|
|
104
|
+
val = 300
|
|
105
|
+
@s.salary_gteq = val
|
|
106
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
107
|
+
expect(@s.result.to_sql).to match /#{field} >= #{val}/
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'generates a >= condition with a string column' do
|
|
111
|
+
val = 'jane@doe.com'
|
|
112
|
+
@s.email_gteq = val
|
|
113
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("email")}"
|
|
114
|
+
expect(@s.result.to_sql).to match /#{field} >= '#{val}'/
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'does not generate a condition for nil' do
|
|
118
|
+
@s.salary_gteq = nil
|
|
119
|
+
expect(@s.result.to_sql).not_to match /WHERE/
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'generates a >= condition with a huge integer value' do
|
|
123
|
+
val = 123456789012345678901
|
|
124
|
+
@s.salary_gteq = val
|
|
125
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
126
|
+
expect(@s.result.to_sql).to match /#{field} >= #{val}/
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe 'gt' do
|
|
131
|
+
it 'generates a > condition with an integer column' do
|
|
132
|
+
val = 400
|
|
133
|
+
@s.salary_gt = val
|
|
134
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
135
|
+
expect(@s.result.to_sql).to match /#{field} > #{val}/
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'generates a > condition with a string column' do
|
|
139
|
+
val = 'jane@doe.com'
|
|
140
|
+
@s.email_gt = val
|
|
141
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("email")}"
|
|
142
|
+
expect(@s.result.to_sql).to match /#{field} > '#{val}'/
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'does not generate a condition for nil' do
|
|
146
|
+
@s.salary_gt = nil
|
|
147
|
+
expect(@s.result.to_sql).not_to match /WHERE/
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'generates a > condition with a huge integer value' do
|
|
151
|
+
val = 123456789012345678901
|
|
152
|
+
@s.salary_gt = val
|
|
153
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
|
154
|
+
expect(@s.result.to_sql).to match /#{field} > #{val}/
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
describe 'cont' do
|
|
159
|
+
it_has_behavior 'wildcard escaping', :name_cont,
|
|
160
|
+
(case ActiveRecord::Base.connection.adapter_name
|
|
161
|
+
when "PostGIS", "PostgreSQL"
|
|
162
|
+
/"people"."name" ILIKE '%\\%\\.\\_\\\\%'/
|
|
163
|
+
when "Mysql2"
|
|
164
|
+
/`people`.`name` LIKE '%\\\\%.\\\\_\\\\\\\\%'/
|
|
165
|
+
else
|
|
166
|
+
/"people"."name" LIKE '%%._\\%'/
|
|
167
|
+
end) do
|
|
168
|
+
subject { @s }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'generates a LIKE query with value surrounded by %' do
|
|
172
|
+
@s.name_cont = 'ric'
|
|
173
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
174
|
+
expect(@s.result.to_sql).to match /#{field} I?LIKE '%ric%'/
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
describe 'not_cont' do
|
|
179
|
+
it_has_behavior 'wildcard escaping', :name_not_cont,
|
|
180
|
+
(case ActiveRecord::Base.connection.adapter_name
|
|
181
|
+
when "PostGIS", "PostgreSQL"
|
|
182
|
+
/"people"."name" NOT ILIKE '%\\%\\.\\_\\\\%'/
|
|
183
|
+
when "Mysql2"
|
|
184
|
+
/`people`.`name` NOT LIKE '%\\\\%.\\\\_\\\\\\\\%'/
|
|
185
|
+
else
|
|
186
|
+
/"people"."name" NOT LIKE '%%._\\%'/
|
|
187
|
+
end) do
|
|
188
|
+
subject { @s }
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'generates a NOT LIKE query with value surrounded by %' do
|
|
192
|
+
@s.name_not_cont = 'ric'
|
|
193
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
194
|
+
expect(@s.result.to_sql).to match /#{field} NOT I?LIKE '%ric%'/
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
describe 'i_cont' do
|
|
199
|
+
it_has_behavior 'wildcard escaping', :name_i_cont,
|
|
200
|
+
(case ActiveRecord::Base.connection.adapter_name
|
|
201
|
+
when "PostGIS"
|
|
202
|
+
/LOWER\("people"."name"\) ILIKE '%\\%\\.\\_\\\\%'/
|
|
203
|
+
when "PostgreSQL"
|
|
204
|
+
/"people"."name" ILIKE '%\\%\\.\\_\\\\%'/
|
|
205
|
+
when "Mysql2"
|
|
206
|
+
/LOWER\(`people`.`name`\) LIKE '%\\\\%.\\\\_\\\\\\\\%'/
|
|
207
|
+
else
|
|
208
|
+
/LOWER\("people"."name"\) LIKE '%%._\\%'/
|
|
209
|
+
end) do
|
|
210
|
+
subject { @s }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it 'generates a LIKE query with LOWER(column) and value surrounded by %' do
|
|
214
|
+
@s.name_i_cont = 'Ric'
|
|
215
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
216
|
+
expect(@s.result.to_sql).to match /[LOWER\(]?#{field}\)? I?LIKE '%ric%'/
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
describe 'not_i_cont' do
|
|
221
|
+
it_has_behavior 'wildcard escaping', :name_not_i_cont,
|
|
222
|
+
(case ActiveRecord::Base.connection.adapter_name
|
|
223
|
+
when "PostGIS"
|
|
224
|
+
/LOWER\("people"."name"\) NOT ILIKE '%\\%\\.\\_\\\\%'/
|
|
225
|
+
when "PostgreSQL"
|
|
226
|
+
/"people"."name" NOT ILIKE '%\\%\\.\\_\\\\%'/
|
|
227
|
+
when "Mysql2"
|
|
228
|
+
/LOWER\(`people`.`name`\) NOT LIKE '%\\\\%.\\\\_\\\\\\\\%'/
|
|
229
|
+
else
|
|
230
|
+
/LOWER\("people"."name"\) NOT LIKE '%%._\\%'/
|
|
231
|
+
end) do
|
|
232
|
+
subject { @s }
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it 'generates a NOT LIKE query with LOWER(column) and value surrounded by %' do
|
|
236
|
+
@s.name_not_i_cont = 'Ric'
|
|
237
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
238
|
+
expect(@s.result.to_sql).to match /[LOWER\(]?#{field}\)? NOT I?LIKE '%ric%'/
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
describe 'start' do
|
|
243
|
+
it 'generates a LIKE query with value followed by %' do
|
|
244
|
+
@s.name_start = 'Er'
|
|
245
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
246
|
+
expect(@s.result.to_sql).to match /#{field} I?LIKE 'Er%'/
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it "works with attribute names ending with '_start'" do
|
|
250
|
+
@s.new_start_start = 'hEy'
|
|
251
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("new_start")}"
|
|
252
|
+
expect(@s.result.to_sql).to match /#{field} I?LIKE 'hEy%'/
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "works with attribute names ending with '_end'" do
|
|
256
|
+
@s.stop_end_start = 'begin'
|
|
257
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("stop_end")}"
|
|
258
|
+
expect(@s.result.to_sql).to match /#{field} I?LIKE 'begin%'/
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
describe 'not_start' do
|
|
263
|
+
it 'generates a NOT LIKE query with value followed by %' do
|
|
264
|
+
@s.name_not_start = 'Eri'
|
|
265
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
266
|
+
expect(@s.result.to_sql).to match /#{field} NOT I?LIKE 'Eri%'/
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "works with attribute names ending with '_start'" do
|
|
270
|
+
@s.new_start_not_start = 'hEy'
|
|
271
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("new_start")}"
|
|
272
|
+
expect(@s.result.to_sql).to match /#{field} NOT I?LIKE 'hEy%'/
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
it "works with attribute names ending with '_end'" do
|
|
276
|
+
@s.stop_end_not_start = 'begin'
|
|
277
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("stop_end")}"
|
|
278
|
+
expect(@s.result.to_sql).to match /#{field} NOT I?LIKE 'begin%'/
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
describe 'end' do
|
|
283
|
+
it 'generates a LIKE query with value preceded by %' do
|
|
284
|
+
@s.name_end = 'Miller'
|
|
285
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
286
|
+
expect(@s.result.to_sql).to match /#{field} I?LIKE '%Miller'/
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "works with attribute names ending with '_start'" do
|
|
290
|
+
@s.new_start_end = 'finish'
|
|
291
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("new_start")}"
|
|
292
|
+
expect(@s.result.to_sql).to match /#{field} I?LIKE '%finish'/
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it "works with attribute names ending with '_end'" do
|
|
296
|
+
@s.stop_end_end = 'Ending'
|
|
297
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("stop_end")}"
|
|
298
|
+
expect(@s.result.to_sql).to match /#{field} I?LIKE '%Ending'/
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
describe 'not_end' do
|
|
303
|
+
it 'generates a NOT LIKE query with value preceded by %' do
|
|
304
|
+
@s.name_not_end = 'Miller'
|
|
305
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
306
|
+
expect(@s.result.to_sql).to match /#{field} NOT I?LIKE '%Miller'/
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it "works with attribute names ending with '_start'" do
|
|
310
|
+
@s.new_start_not_end = 'finish'
|
|
311
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("new_start")}"
|
|
312
|
+
expect(@s.result.to_sql).to match /#{field} NOT I?LIKE '%finish'/
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "works with attribute names ending with '_end'" do
|
|
316
|
+
@s.stop_end_not_end = 'Ending'
|
|
317
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("stop_end")}"
|
|
318
|
+
expect(@s.result.to_sql).to match /#{field} NOT I?LIKE '%Ending'/
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
describe 'true' do
|
|
323
|
+
it 'generates an equality condition for boolean true' do
|
|
324
|
+
@s.awesome_true = true
|
|
325
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
326
|
+
expect(@s.result.to_sql).to match /#{field} = #{
|
|
327
|
+
ActiveRecord::Base.connection.quoted_true}/
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
it 'generates an inequality condition for boolean true' do
|
|
331
|
+
@s.awesome_true = false
|
|
332
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
333
|
+
expect(@s.result.to_sql).to match /#{field} != #{
|
|
334
|
+
ActiveRecord::Base.connection.quoted_true}/
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
describe 'not_true' do
|
|
339
|
+
it 'generates an inequality condition for boolean true' do
|
|
340
|
+
@s.awesome_not_true = true
|
|
341
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
342
|
+
expect(@s.result.to_sql).to match /#{field} != #{
|
|
343
|
+
ActiveRecord::Base.connection.quoted_true}/
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
it 'generates an equality condition for boolean true' do
|
|
347
|
+
@s.awesome_not_true = false
|
|
348
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
349
|
+
expect(@s.result.to_sql).to match /#{field} = #{
|
|
350
|
+
ActiveRecord::Base.connection.quoted_true}/
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
describe 'false' do
|
|
355
|
+
it 'generates an equality condition for boolean false' do
|
|
356
|
+
@s.awesome_false = true
|
|
357
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
358
|
+
expect(@s.result.to_sql).to match /#{field} = #{
|
|
359
|
+
ActiveRecord::Base.connection.quoted_false}/
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
it 'generates an inequality condition for boolean false' do
|
|
363
|
+
@s.awesome_false = false
|
|
364
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
365
|
+
expect(@s.result.to_sql).to match /#{field} != #{
|
|
366
|
+
ActiveRecord::Base.connection.quoted_false}/
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
describe 'not_false' do
|
|
371
|
+
it 'generates an inequality condition for boolean false' do
|
|
372
|
+
@s.awesome_not_false = true
|
|
373
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
374
|
+
expect(@s.result.to_sql).to match /#{field} != #{
|
|
375
|
+
ActiveRecord::Base.connection.quoted_false}/
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
it 'generates an equality condition for boolean false' do
|
|
379
|
+
@s.awesome_not_false = false
|
|
380
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
|
381
|
+
expect(@s.result.to_sql).to match /#{field} = #{
|
|
382
|
+
ActiveRecord::Base.connection.quoted_false}/
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
describe 'null' do
|
|
387
|
+
it 'generates a value IS NULL query' do
|
|
388
|
+
@s.name_null = true
|
|
389
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
390
|
+
expect(@s.result.to_sql).to match /#{field} IS NULL/
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it 'generates a value IS NOT NULL query when assigned false' do
|
|
394
|
+
@s.name_null = false
|
|
395
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
396
|
+
expect(@s.result.to_sql).to match /#{field} IS NOT NULL/
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
describe 'not_null' do
|
|
401
|
+
it 'generates a value IS NOT NULL query' do
|
|
402
|
+
@s.name_not_null = true
|
|
403
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
404
|
+
expect(@s.result.to_sql).to match /#{field} IS NOT NULL/
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it 'generates a value IS NULL query when assigned false' do
|
|
408
|
+
@s.name_not_null = false
|
|
409
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
410
|
+
expect(@s.result.to_sql).to match /#{field} IS NULL/
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
describe 'with association query' do
|
|
414
|
+
it 'generates a value IS NOT NULL query' do
|
|
415
|
+
@s.comments_id_not_null = true
|
|
416
|
+
sql = @s.result.to_sql
|
|
417
|
+
parent_field = "#{quote_table_name("people")}.#{quote_column_name("id")}"
|
|
418
|
+
expect(sql).to match /#{parent_field} IN/
|
|
419
|
+
field = "#{quote_table_name("comments")}.#{quote_column_name("id")}"
|
|
420
|
+
expect(sql).to match /#{field} IS NOT NULL/
|
|
421
|
+
expect(sql).not_to match /AND NOT/
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it 'generates a value IS NULL query when assigned false' do
|
|
425
|
+
@s.comments_id_not_null = false
|
|
426
|
+
sql = @s.result.to_sql
|
|
427
|
+
parent_field = "#{quote_table_name("people")}.#{quote_column_name("id")}"
|
|
428
|
+
expect(sql).to match /#{parent_field} NOT IN/
|
|
429
|
+
field = "#{quote_table_name("comments")}.#{quote_column_name("id")}"
|
|
430
|
+
expect(sql).to match /#{field} IS NULL/
|
|
431
|
+
expect(sql).to match /AND NOT/
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
describe 'present' do
|
|
437
|
+
it %q[generates a value IS NOT NULL AND value != '' query] do
|
|
438
|
+
@s.name_present = true
|
|
439
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
440
|
+
expect(@s.result.to_sql).to match /#{field} IS NOT NULL AND #{field} != ''/
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
it %q[generates a value IS NULL OR value = '' query when assigned false] do
|
|
444
|
+
@s.name_present = false
|
|
445
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
446
|
+
expect(@s.result.to_sql).to match /#{field} IS NULL OR #{field} = ''/
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
describe 'blank' do
|
|
451
|
+
it %q[generates a value IS NULL OR value = '' query] do
|
|
452
|
+
@s.name_blank = true
|
|
453
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
454
|
+
expect(@s.result.to_sql).to match /#{field} IS NULL OR #{field} = ''/
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
it %q[generates a value IS NOT NULL AND value != '' query when assigned false] do
|
|
458
|
+
@s.name_blank = false
|
|
459
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
460
|
+
expect(@s.result.to_sql).to match /#{field} IS NOT NULL AND #{field} != ''/
|
|
461
|
+
end
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
context "defining custom predicates" do
|
|
465
|
+
describe "with 'not_in' arel predicate" do
|
|
466
|
+
before do
|
|
467
|
+
Ransack.configure { |c| c.add_predicate "not_in_csv", arel_predicate: "not_in", formatter: proc { |v| v.split(",") } }
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
it 'generates a value IS NOT NULL query' do
|
|
471
|
+
@s.name_not_in_csv = ["a", "b"]
|
|
472
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
473
|
+
expect(@s.result.to_sql).to match /#{field} NOT IN \('a', 'b'\)/
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
private
|
|
479
|
+
|
|
480
|
+
def test_boolean_equality_for(boolean_value)
|
|
481
|
+
query = expected_query(boolean_value)
|
|
482
|
+
test_values_for(boolean_value).each do |value|
|
|
483
|
+
s = Search.new(Person, awesome_eq: value)
|
|
484
|
+
expect(s.result.to_sql).to match query
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def test_values_for(boolean_value)
|
|
489
|
+
case boolean_value
|
|
490
|
+
when true
|
|
491
|
+
TRUE_VALUES
|
|
492
|
+
when false
|
|
493
|
+
FALSE_VALUES
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
def expected_query(value, attribute = 'awesome', operator = '=')
|
|
498
|
+
field = "#{quote_table_name("people")}.#{quote_column_name(attribute)}"
|
|
499
|
+
quoted_value = ActiveRecord::Base.connection.quote(value)
|
|
500
|
+
/#{field} #{operator} #{quoted_value}/
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Ransack
|
|
4
|
+
describe Ransacker do
|
|
5
|
+
let(:klass) { Person }
|
|
6
|
+
let(:name) { :test_ransacker }
|
|
7
|
+
let(:opts) { {} }
|
|
8
|
+
|
|
9
|
+
describe '#initialize' do
|
|
10
|
+
context 'with minimal options' do
|
|
11
|
+
subject { Ransacker.new(klass, name, opts) }
|
|
12
|
+
|
|
13
|
+
it 'sets the name' do
|
|
14
|
+
expect(subject.name).to eq(name)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'sets default type to string' do
|
|
18
|
+
expect(subject.type).to eq(:string)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'sets default args to [:parent]' do
|
|
22
|
+
expect(subject.args).to eq([:parent])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with custom options' do
|
|
27
|
+
let(:opts) { { type: :integer, args: [:parent, :custom_arg], formatter: proc { |v| v.to_i } } }
|
|
28
|
+
|
|
29
|
+
subject { Ransacker.new(klass, name, opts) }
|
|
30
|
+
|
|
31
|
+
it 'sets the custom type' do
|
|
32
|
+
expect(subject.type).to eq(:integer)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'sets the custom args' do
|
|
36
|
+
expect(subject.args).to eq([:parent, :custom_arg])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'sets the formatter' do
|
|
40
|
+
expect(subject.formatter).to eq(opts[:formatter])
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'with callable option' do
|
|
45
|
+
let(:callable) { proc { |parent| parent.table[:id] } }
|
|
46
|
+
let(:opts) { { callable: callable } }
|
|
47
|
+
|
|
48
|
+
subject { Ransacker.new(klass, name, opts) }
|
|
49
|
+
|
|
50
|
+
it 'initializes successfully' do
|
|
51
|
+
expect(subject).to be_a(Ransacker)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe 'basic functionality' do
|
|
57
|
+
subject { Ransacker.new(klass, name, opts) }
|
|
58
|
+
|
|
59
|
+
it 'responds to required methods' do
|
|
60
|
+
expect(subject).to respond_to(:name)
|
|
61
|
+
expect(subject).to respond_to(:type)
|
|
62
|
+
expect(subject).to respond_to(:args)
|
|
63
|
+
expect(subject).to respond_to(:formatter)
|
|
64
|
+
expect(subject).to respond_to(:attr_from)
|
|
65
|
+
expect(subject).to respond_to(:call)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|