ransack 1.8.4 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/SECURITY.md +12 -0
  4. data/.github/workflows/cronjob.yml +102 -0
  5. data/.github/workflows/deploy.yml +35 -0
  6. data/.github/workflows/rubocop.yml +20 -0
  7. data/.github/workflows/test-deploy.yml +29 -0
  8. data/.github/workflows/test.yml +130 -0
  9. data/.gitignore +3 -0
  10. data/{lib/ransack/adapters/mongoid/3.2/.gitkeep → .nojekyll} +0 -0
  11. data/.rubocop.yml +44 -0
  12. data/CHANGELOG.md +352 -0
  13. data/CONTRIBUTING.md +25 -13
  14. data/Gemfile +26 -27
  15. data/README.md +65 -815
  16. data/Rakefile +1 -22
  17. data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +78 -0
  18. data/bug_report_templates/test-ransacker-arel-present-predicate.rb +71 -0
  19. data/docs/.gitignore +19 -0
  20. data/docs/.nojekyll +0 -0
  21. data/docs/babel.config.js +3 -0
  22. data/docs/blog/2022-03-27-ransack-3.0.0.md +20 -0
  23. data/docs/docs/getting-started/_category_.json +4 -0
  24. data/docs/docs/getting-started/advanced-mode.md +46 -0
  25. data/docs/docs/getting-started/configuration.md +47 -0
  26. data/docs/docs/getting-started/search-matches.md +67 -0
  27. data/docs/docs/getting-started/simple-mode.md +284 -0
  28. data/docs/docs/getting-started/sorting.md +79 -0
  29. data/docs/docs/getting-started/using-predicates.md +282 -0
  30. data/docs/docs/going-further/_category_.json +4 -0
  31. data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
  32. data/docs/docs/going-further/associations.md +70 -0
  33. data/docs/docs/going-further/custom-predicates.md +52 -0
  34. data/docs/docs/going-further/documentation.md +43 -0
  35. data/docs/docs/going-further/exporting-to-csv.md +49 -0
  36. data/docs/docs/going-further/external-guides.md +57 -0
  37. data/docs/docs/going-further/form-customisation.md +63 -0
  38. data/docs/docs/going-further/i18n.md +53 -0
  39. data/docs/docs/going-further/img/create_release.png +0 -0
  40. data/docs/docs/going-further/merging-searches.md +41 -0
  41. data/docs/docs/going-further/other-notes.md +428 -0
  42. data/docs/docs/going-further/polymorphic-search.md +40 -0
  43. data/docs/docs/going-further/ransackers.md +331 -0
  44. data/docs/docs/going-further/release_process.md +36 -0
  45. data/docs/docs/going-further/saving-queries.md +82 -0
  46. data/docs/docs/going-further/searching-postgres.md +57 -0
  47. data/docs/docs/going-further/wiki-contributors.md +82 -0
  48. data/docs/docs/intro.md +99 -0
  49. data/docs/docusaurus.config.js +120 -0
  50. data/docs/package.json +38 -0
  51. data/docs/sidebars.js +31 -0
  52. data/docs/src/components/HomepageFeatures/index.js +64 -0
  53. data/docs/src/components/HomepageFeatures/styles.module.css +11 -0
  54. data/docs/src/css/custom.css +39 -0
  55. data/docs/src/pages/index.module.css +23 -0
  56. data/docs/src/pages/markdown-page.md +7 -0
  57. data/docs/static/.nojekyll +0 -0
  58. data/docs/static/img/docusaurus.png +0 -0
  59. data/docs/static/img/favicon.ico +0 -0
  60. data/docs/static/img/logo.svg +1 -0
  61. data/docs/static/img/tutorial/docsVersionDropdown.png +0 -0
  62. data/docs/static/img/tutorial/localeDropdown.png +0 -0
  63. data/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
  64. data/docs/static/img/undraw_docusaurus_react.svg +170 -0
  65. data/docs/static/img/undraw_docusaurus_tree.svg +40 -0
  66. data/docs/static/logo/ransack-h.png +0 -0
  67. data/docs/static/logo/ransack-h.svg +34 -0
  68. data/docs/static/logo/ransack-v.png +0 -0
  69. data/docs/static/logo/ransack-v.svg +34 -0
  70. data/docs/static/logo/ransack.png +0 -0
  71. data/docs/static/logo/ransack.svg +21 -0
  72. data/docs/yarn.lock +8436 -0
  73. data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +70 -0
  74. data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +92 -0
  75. data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -0
  76. data/lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb +1 -0
  77. data/lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb +1 -0
  78. data/lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb +1 -0
  79. data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
  80. data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
  81. data/lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb +1 -0
  82. data/lib/polyamorous/join.rb +70 -0
  83. data/lib/polyamorous/polyamorous.rb +24 -0
  84. data/lib/polyamorous/swapping_reflection_class.rb +11 -0
  85. data/lib/polyamorous/tree_node.rb +7 -0
  86. data/lib/polyamorous.rb +1 -0
  87. data/lib/ransack/adapters/active_record/base.rb +14 -3
  88. data/lib/ransack/adapters/active_record/context.rb +140 -196
  89. data/lib/ransack/adapters/active_record/ransack/constants.rb +19 -4
  90. data/lib/ransack/adapters/active_record/ransack/context.rb +9 -19
  91. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +7 -7
  92. data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
  93. data/lib/ransack/adapters/active_record/ransack/visitor.rb +23 -0
  94. data/lib/ransack/adapters/active_record.rb +0 -9
  95. data/lib/ransack/adapters.rb +2 -0
  96. data/lib/ransack/configuration.rb +52 -2
  97. data/lib/ransack/constants.rb +1 -5
  98. data/lib/ransack/context.rb +29 -24
  99. data/lib/ransack/helpers/form_builder.rb +12 -6
  100. data/lib/ransack/helpers/form_helper.rb +11 -3
  101. data/lib/ransack/helpers.rb +1 -1
  102. data/lib/ransack/locale/ar.yml +70 -0
  103. data/lib/ransack/locale/az.yml +70 -0
  104. data/lib/ransack/locale/bg.yml +70 -0
  105. data/lib/ransack/locale/ca.yml +70 -0
  106. data/lib/ransack/locale/el.yml +70 -0
  107. data/lib/ransack/locale/es.yml +22 -22
  108. data/lib/ransack/locale/fa.yml +70 -0
  109. data/lib/ransack/locale/fi.yml +71 -0
  110. data/lib/ransack/locale/nl.yml +4 -4
  111. data/lib/ransack/locale/ru.yml +70 -0
  112. data/lib/ransack/locale/sk.yml +70 -0
  113. data/lib/ransack/locale/sv.yml +70 -0
  114. data/lib/ransack/locale/tr.yml +70 -0
  115. data/lib/ransack/locale/zh-CN.yml +12 -12
  116. data/lib/ransack/nodes/attribute.rb +2 -2
  117. data/lib/ransack/nodes/condition.rb +7 -1
  118. data/lib/ransack/nodes/grouping.rb +3 -8
  119. data/lib/ransack/nodes/sort.rb +3 -3
  120. data/lib/ransack/nodes/value.rb +3 -3
  121. data/lib/ransack/predicate.rb +13 -20
  122. data/lib/ransack/search.rb +7 -4
  123. data/lib/ransack/translate.rb +115 -115
  124. data/lib/ransack/version.rb +1 -1
  125. data/lib/ransack/visitor.rb +1 -12
  126. data/lib/ransack.rb +7 -5
  127. data/ransack.gemspec +9 -25
  128. data/spec/blueprints/articles.rb +1 -1
  129. data/spec/blueprints/comments.rb +1 -1
  130. data/spec/blueprints/notes.rb +1 -1
  131. data/spec/blueprints/tags.rb +1 -1
  132. data/spec/console.rb +5 -5
  133. data/spec/helpers/polyamorous_helper.rb +13 -0
  134. data/spec/helpers/ransack_helper.rb +1 -1
  135. data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
  136. data/spec/polyamorous/join_association_spec.rb +30 -0
  137. data/spec/polyamorous/join_dependency_spec.rb +81 -0
  138. data/spec/polyamorous/join_spec.rb +19 -0
  139. data/spec/ransack/adapters/active_record/base_spec.rb +105 -11
  140. data/spec/ransack/adapters/active_record/context_spec.rb +63 -24
  141. data/spec/ransack/configuration_spec.rb +24 -0
  142. data/spec/ransack/helpers/form_builder_spec.rb +3 -15
  143. data/spec/ransack/helpers/form_helper_spec.rb +135 -168
  144. data/spec/ransack/nodes/condition_spec.rb +13 -0
  145. data/spec/ransack/nodes/grouping_spec.rb +2 -2
  146. data/spec/ransack/nodes/value_spec.rb +115 -0
  147. data/spec/ransack/predicate_spec.rb +54 -2
  148. data/spec/ransack/search_spec.rb +266 -36
  149. data/spec/spec_helper.rb +14 -5
  150. data/spec/support/schema.rb +99 -21
  151. metadata +117 -187
  152. data/.travis.yml +0 -86
  153. data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
  154. data/lib/ransack/adapters/active_record/3.0/context.rb +0 -203
  155. data/lib/ransack/adapters/active_record/3.1/context.rb +0 -212
  156. data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
  157. data/lib/ransack/adapters/active_record/compat.rb +0 -14
  158. data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
  159. data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
  160. data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
  161. data/lib/ransack/adapters/mongoid/base.rb +0 -134
  162. data/lib/ransack/adapters/mongoid/context.rb +0 -212
  163. data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
  164. data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
  165. data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -60
  166. data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -27
  167. data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
  168. data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -24
  169. data/lib/ransack/adapters/mongoid/table.rb +0 -35
  170. data/lib/ransack/adapters/mongoid.rb +0 -15
  171. data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -314
  172. data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
  173. data/spec/mongoid/configuration_spec.rb +0 -162
  174. data/spec/mongoid/dependencies_spec.rb +0 -8
  175. data/spec/mongoid/helpers/ransack_helper.rb +0 -11
  176. data/spec/mongoid/nodes/condition_spec.rb +0 -49
  177. data/spec/mongoid/nodes/grouping_spec.rb +0 -13
  178. data/spec/mongoid/predicate_spec.rb +0 -155
  179. data/spec/mongoid/search_spec.rb +0 -445
  180. data/spec/mongoid/support/mongoid.yml +0 -11
  181. data/spec/mongoid/support/schema.rb +0 -135
  182. data/spec/mongoid/translate_spec.rb +0 -14
  183. data/spec/mongoid_spec_helper.rb +0 -63
  184. data/spec/ransack/dependencies_spec.rb +0 -12
@@ -1,445 +0,0 @@
1
- require 'mongoid_spec_helper'
2
-
3
- module Ransack
4
- describe Search do
5
- describe '#initialize' do
6
- it "removes empty conditions before building" do
7
- expect_any_instance_of(Search).to receive(:build).with({})
8
- Search.new(Person, :name_eq => '')
9
- end
10
-
11
- it "keeps conditions with a false value before building" do
12
- expect_any_instance_of(Search).to receive(:build).with({"name_eq" => false})
13
- Search.new(Person, :name_eq => false)
14
- end
15
-
16
- it "keeps conditions with a value before building" do
17
- expect_any_instance_of(Search).to receive(:build).with({"name_eq" => 'foobar'})
18
- Search.new(Person, :name_eq => 'foobar')
19
- end
20
-
21
- it "removes empty suffixed conditions before building" do
22
- expect_any_instance_of(Search).to receive(:build).with({})
23
- Search.new(Person, :name_eq_any => [''])
24
- end
25
-
26
- it "keeps suffixed conditions with a false value before building" do
27
- expect_any_instance_of(Search).to receive(:build).with({"name_eq_any" => [false]})
28
- Search.new(Person, :name_eq_any => [false])
29
- end
30
-
31
- it "keeps suffixed conditions with a value before building" do
32
- expect_any_instance_of(Search).to receive(:build).with({"name_eq_any" => ['foobar']})
33
- Search.new(Person, :name_eq_any => ['foobar'])
34
- end
35
-
36
- it 'does not raise exception for string :params argument' do
37
- expect { Search.new(Person, '') }.not_to raise_error
38
- end
39
- end
40
-
41
- describe '#build' do
42
- it 'creates conditions for top-level attributes' do
43
- search = Search.new(Person, :name_eq => 'Ernie')
44
- condition = search.base[:name_eq]
45
- expect(condition).to be_a Nodes::Condition
46
- expect(condition.predicate.name).to eq 'eq'
47
- expect(condition.attributes.first.name).to eq 'name'
48
- expect(condition.value).to eq 'Ernie'
49
- end
50
-
51
- context 'joins' do
52
- before { pending 'not implemented for mongoid' }
53
-
54
- it 'creates conditions for association attributes' do
55
- search = Search.new(Person, :children_name_eq => 'Ernie')
56
- condition = search.base[:children_name_eq]
57
- expect(condition).to be_a Nodes::Condition
58
- expect(condition.predicate.name).to eq 'eq'
59
- expect(condition.attributes.first.name).to eq 'children_name'
60
- expect(condition.value).to eq 'Ernie'
61
- end
62
-
63
- it 'creates conditions for polymorphic belongs_to association attributes' do
64
- search = Search.new(Note, :notable_of_Person_type_name_eq => 'Ernie')
65
- condition = search.base[:notable_of_Person_type_name_eq]
66
- expect(condition).to be_a Nodes::Condition
67
- expect(condition.predicate.name).to eq 'eq'
68
- expect(condition.attributes.first.name).to eq 'notable_of_Person_type_name'
69
- expect(condition.value).to eq 'Ernie'
70
- end
71
-
72
- it 'creates conditions for multiple polymorphic belongs_to association attributes' do
73
- search = Search.new(Note,
74
- :notable_of_Person_type_name_or_notable_of_Article_type_title_eq => 'Ernie')
75
- condition = search.
76
- base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
77
- expect(condition).to be_a Nodes::Condition
78
- expect(condition.predicate.name).to eq 'eq'
79
- expect(condition.attributes.first.name).to eq 'notable_of_Person_type_name'
80
- expect(condition.attributes.last.name).to eq 'notable_of_Article_type_title'
81
- expect(condition.value).to eq 'Ernie'
82
- end
83
- before { skip }
84
- it 'accepts arrays of groupings with joins' do
85
- search = Search.new(Person,
86
- g: [
87
- { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
88
- { :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
89
- ]
90
- )
91
- ors = search.groupings
92
- expect(ors.size).to eq(2)
93
- or1, or2 = ors
94
- expect(or1).to be_a Nodes::Grouping
95
- expect(or1.combinator).to eq 'or'
96
- expect(or2).to be_a Nodes::Grouping
97
- expect(or2.combinator).to eq 'or'
98
- end
99
-
100
- it 'accepts "attributes" hashes for groupings' do
101
- search = Search.new(Person,
102
- g: {
103
- '0' => { m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
104
- '1' => { m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' },
105
- }
106
- )
107
- ors = search.groupings
108
- expect(ors.size).to eq(2)
109
- or1, or2 = ors
110
- expect(or1).to be_a Nodes::Grouping
111
- expect(or1.combinator).to eq 'or'
112
- expect(or2).to be_a Nodes::Grouping
113
- expect(or2.combinator).to eq 'or'
114
- end
115
-
116
- it 'accepts "attributes" hashes for conditions' do
117
- search = Search.new(Person,
118
- :c => {
119
- '0' => { :a => ['name'], :p => 'eq', :v => ['Ernie'] },
120
- '1' => { :a => ['children_name', 'parent_name'],
121
- :p => 'eq', :v => ['Ernie'], :m => 'or' }
122
- }
123
- )
124
- conditions = search.base.conditions
125
- expect(conditions.size).to eq(2)
126
- expect(conditions.map { |c| c.class })
127
- .to eq [Nodes::Condition, Nodes::Condition]
128
- end
129
-
130
- before { skip }
131
- it 'does not evaluate the query on #inspect' do
132
- search = Search.new(Person, :children_id_in => [1, 2, 3])
133
- expect(search.inspect).not_to match /ActiveRecord/
134
- end
135
- end
136
-
137
- it 'discards empty conditions' do
138
- search = Search.new(Person, :children_name_eq => '')
139
- condition = search.base[:children_name_eq]
140
- expect(condition).to be_nil
141
- end
142
-
143
- it 'accepts arrays of groupings' do
144
- search = Search.new(Person,
145
- g: [
146
- { :m => 'or', :name_eq => 'Ernie', :email_eq => 'ernie@example.org' },
147
- { :m => 'or', :name_eq => 'Bert', :email_eq => 'bert@example.org' },
148
- ]
149
- )
150
- ors = search.groupings
151
- expect(ors.size).to eq(2)
152
- or1, or2 = ors
153
- expect(or1).to be_a Nodes::Grouping
154
- expect(or1.combinator).to eq 'or'
155
- expect(or2).to be_a Nodes::Grouping
156
- expect(or2.combinator).to eq 'or'
157
- end
158
-
159
- it 'creates conditions for custom predicates that take arrays' do
160
- Ransack.configure do |config|
161
- config.add_predicate 'ary_pred', :wants_array => true
162
- end
163
-
164
- search = Search.new(Person, :name_ary_pred => ['Ernie', 'Bert'])
165
- condition = search.base[:name_ary_pred]
166
- expect(condition).to be_a Nodes::Condition
167
- expect(condition.predicate.name).to eq 'ary_pred'
168
- expect(condition.attributes.first.name).to eq 'name'
169
- expect(condition.value).to eq ['Ernie', 'Bert']
170
- end
171
-
172
- context 'with an invalid condition' do
173
- subject { Search.new(Person, :unknown_attr_eq => 'Ernie') }
174
-
175
- context "when ignore_unknown_conditions is false" do
176
- before do
177
- Ransack.configure { |c| c.ignore_unknown_conditions = false }
178
- end
179
-
180
- specify { expect { subject }.to raise_error ArgumentError }
181
- end
182
-
183
- context "when ignore_unknown_conditions is true" do
184
- before do
185
- Ransack.configure { |c| c.ignore_unknown_conditions = true }
186
- end
187
-
188
- specify { expect { subject }.not_to raise_error }
189
- end
190
- end
191
- end
192
-
193
- describe '#result' do
194
- let(:people_name_field) {
195
- "#{quote_table_name("people")}.#{quote_column_name("name")}"
196
- }
197
- # let(:children_people_name_field) {
198
- # "#{quote_table_name("children_people")}.#{quote_column_name("name")}"
199
- # }
200
-
201
- it 'evaluates arrays of groupings' do
202
- search = Search.new(Person,
203
- :g => [
204
- { :m => 'or', :name_eq => 'Ernie', :email_eq => 'ernie@example.org' },
205
- { :m => 'or', :name_eq => 'Bert', :email_eq => 'bert@example.org' }
206
- ]
207
- )
208
- expect(search.result).to be_an Mongoid::Criteria
209
- selector = search.result.selector
210
- expect(selector.keys).to eq ['$and']
211
- first, second = selector.values.first
212
- expect(first).to eq({ '$or' => [ { 'name' => 'Ernie' }, { 'email' => 'ernie@example.org' } ] })
213
- expect(second).to eq({ '$or' => [ { 'name' => 'Bert' }, { 'email' => 'bert@example.org' } ] })
214
- end
215
-
216
- context 'with joins' do
217
- before { pending 'not implemented for mongoid' }
218
-
219
- it 'evaluates conditions contextually' do
220
- search = Search.new(Person, :children_name_eq => 'Ernie')
221
- expect(search.result).to be_an ActiveRecord::Relation
222
- where = search.result.where_values.first
223
- expect(where.to_sql).to match /#{children_people_name_field} = 'Ernie'/
224
- end
225
-
226
- it 'evaluates compound conditions contextually' do
227
- search = Search.new(Person, :children_name_or_name_eq => 'Ernie')
228
- expect(search.result).to be_an ActiveRecord::Relation
229
- where = search.result.where_values.first
230
- expect(where.to_sql).to match /#{children_people_name_field
231
- } = 'Ernie' OR #{people_name_field} = 'Ernie'/
232
- end
233
-
234
- it 'evaluates polymorphic belongs_to association conditions contextually' do
235
- search = Search.new(Note, :notable_of_Person_type_name_eq => 'Ernie')
236
- expect(search.result).to be_an ActiveRecord::Relation
237
- where = search.result.where_values.first
238
- expect(where.to_sql).to match /#{people_name_field} = 'Ernie'/
239
- end
240
-
241
- it 'evaluates nested conditions' do
242
- search = Search.new(Person, :children_name_eq => 'Ernie',
243
- :g => [
244
- { :m => 'or',
245
- :name_eq => 'Ernie',
246
- :children_children_name_eq => 'Ernie'
247
- }
248
- ]
249
- )
250
- expect(search.result).to be_an ActiveRecord::Relation
251
- where = search.result.where_values.first
252
- expect(where.to_sql).to match /#{children_people_name_field} = 'Ernie'/
253
- expect(where.to_sql).to match /#{people_name_field} = 'Ernie'/
254
- expect(where.to_sql).to match /#{quote_table_name("children_people_2")
255
- }.#{quote_column_name("name")} = 'Ernie'/
256
- end
257
-
258
- it 'evaluates arrays of groupings' do
259
- search = Search.new(Person,
260
- :g => [
261
- { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
262
- { :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' }
263
- ]
264
- )
265
- expect(search.result).to be_an ActiveRecord::Relation
266
- where = search.result.where_values.first
267
- sql = where.to_sql
268
- first, second = sql.split(/ AND /)
269
- expect(first).to match /#{people_name_field} = 'Ernie'/
270
- expect(first).to match /#{children_people_name_field} = 'Ernie'/
271
- expect(second).to match /#{people_name_field} = 'Bert'/
272
- expect(second).to match /#{children_people_name_field} = 'Bert'/
273
- end
274
-
275
- it 'returns distinct records when passed :distinct => true' do
276
- search = Search.new(
277
- Person, :g => [
278
- { :m => 'or',
279
- :comments_body_cont => 'e',
280
- :articles_comments_body_cont => 'e'
281
- }
282
- ]
283
- )
284
- if ActiveRecord::VERSION::MAJOR == 3
285
- all_or_load, uniq_or_distinct = :all, :uniq
286
- else
287
- all_or_load, uniq_or_distinct = :load, :distinct
288
- end
289
- expect(search.result.send(all_or_load).size).
290
- to eq(9000)
291
- expect(search.result(:distinct => true).size).
292
- to eq(10)
293
- expect(search.result.send(all_or_load).send(uniq_or_distinct)).
294
- to eq search.result(:distinct => true).send(all_or_load)
295
- end
296
- end
297
- end
298
-
299
- describe '#sorts=' do
300
- before do
301
- @s = Search.new(Person)
302
- end
303
-
304
- it 'creates sorts based on a single attribute/direction' do
305
- @s.sorts = 'id desc'
306
- expect(@s.sorts.size).to eq(1)
307
- sort = @s.sorts.first
308
- expect(sort).to be_a Nodes::Sort
309
- expect(sort.name).to eq 'id'
310
- expect(sort.dir).to eq 'desc'
311
- expect(@s.result.options).to eq({ :sort => { '_id' => -1 } })
312
- end
313
-
314
- it 'creates sorts based on a single attribute and uppercase direction' do
315
- @s.sorts = 'id DESC'
316
- expect(@s.sorts.size).to eq(1)
317
- sort = @s.sorts.first
318
- expect(sort).to be_a Nodes::Sort
319
- expect(sort.name).to eq 'id'
320
- expect(sort.dir).to eq 'desc'
321
- expect(@s.result.options).to eq({ :sort => { '_id' => -1 } })
322
- end
323
-
324
- it 'creates sorts based on a single attribute and without direction' do
325
- @s.sorts = 'id'
326
- expect(@s.sorts.size).to eq(1)
327
- sort = @s.sorts.first
328
- expect(sort).to be_a Nodes::Sort
329
- expect(sort.name).to eq 'id'
330
- expect(sort.dir).to eq 'asc'
331
- expect(@s.result.options).to eq({ :sort => { '_id' => 1 } })
332
- end
333
-
334
- it 'creates sorts based on multiple attributes/directions in array format' do
335
- @s.sorts = ['id desc', { :name => 'name', :dir => 'asc' }]
336
- expect(@s.sorts.size).to eq(2)
337
- sort1, sort2 = @s.sorts
338
- expect(sort1).to be_a Nodes::Sort
339
- expect(sort1.name).to eq 'id'
340
- expect(sort1.dir).to eq 'desc'
341
- expect(sort2).to be_a Nodes::Sort
342
- expect(sort2.name).to eq 'name'
343
- expect(sort2.dir).to eq 'asc'
344
- expect(@s.result.options).to eq({ :sort=>{"_id"=>-1, "name"=>1} })
345
- end
346
-
347
- it 'creates sorts based on multiple attributes and uppercase directions in array format' do
348
- @s.sorts = ['id DESC', { :name => 'name', :dir => 'ASC' }]
349
- expect(@s.sorts.size).to eq(2)
350
- sort1, sort2 = @s.sorts
351
- expect(sort1).to be_a Nodes::Sort
352
- expect(sort1.name).to eq 'id'
353
- expect(sort1.dir).to eq 'desc'
354
- expect(sort2).to be_a Nodes::Sort
355
- expect(sort2.name).to eq 'name'
356
- expect(sort2.dir).to eq 'asc'
357
- expect(@s.result.options).to eq({ :sort=>{"_id"=>-1, "name"=>1} })
358
- end
359
-
360
- it 'creates sorts based on multiple attributes and different directions in array format' do
361
- @s.sorts = ['id DESC', { name: 'name', dir: nil }]
362
- expect(@s.sorts.size).to eq(2)
363
- sort1, sort2 = @s.sorts
364
- expect(sort1).to be_a Nodes::Sort
365
- expect(sort1.name).to eq 'id'
366
- expect(sort1.dir).to eq 'desc'
367
- expect(sort2).to be_a Nodes::Sort
368
- expect(sort2.name).to eq 'name'
369
- expect(sort2.dir).to eq 'asc'
370
- expect(@s.result.options).to eq({ :sort=>{"_id"=>-1, "name"=>1} })
371
- end
372
-
373
- it 'creates sorts based on multiple attributes/directions in hash format' do
374
- @s.sorts = {
375
- '0' => { :name => 'id', :dir => 'desc' },
376
- '1' => { :name => 'name', :dir => 'asc' }
377
- }
378
- expect(@s.sorts.size).to eq(2)
379
- expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
380
- id_sort = @s.sorts.detect { |s| s.name == 'id' }
381
- name_sort = @s.sorts.detect { |s| s.name == 'name' }
382
- expect(id_sort.dir).to eq 'desc'
383
- expect(name_sort.dir).to eq 'asc'
384
- expect(@s.result.options).to eq({ :sort=>{"_id"=>-1, "name"=>1} })
385
- end
386
-
387
- it 'creates sorts based on multiple attributes and uppercase directions in hash format' do
388
- @s.sorts = {
389
- '0' => { :name => 'id', :dir => 'DESC' },
390
- '1' => { :name => 'name', :dir => 'ASC' }
391
- }
392
- expect(@s.sorts.size).to eq(2)
393
- expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
394
- id_sort = @s.sorts.detect { |s| s.name == 'id' }
395
- name_sort = @s.sorts.detect { |s| s.name == 'name' }
396
- expect(id_sort.dir).to eq 'desc'
397
- expect(name_sort.dir).to eq 'asc'
398
- expect(@s.result.options).to eq({ :sort=>{"_id"=>-1, "name"=>1} })
399
- end
400
-
401
- it 'creates sorts based on multiple attributes and different directions in hash format' do
402
- @s.sorts = {
403
- '0' => { :name => 'id', :dir => 'DESC' },
404
- '1' => { :name => 'name', :dir => nil }
405
- }
406
- expect(@s.sorts.size).to eq(2)
407
- expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
408
- id_sort = @s.sorts.detect { |s| s.name == 'id' }
409
- name_sort = @s.sorts.detect { |s| s.name == 'name' }
410
- expect(id_sort.dir).to eq 'desc'
411
- expect(name_sort.dir).to eq 'asc'
412
- expect(@s.result.options).to eq({ :sort=>{"_id"=>-1, "name"=>1} })
413
- end
414
-
415
- it 'overrides existing sort' do
416
- @s.sorts = 'id asc'
417
- expect(@s.result.first.id.to_s).to eq Person.min(:id).to_s
418
- end
419
- end
420
-
421
- describe '#method_missing' do
422
- before do
423
- @s = Search.new(Person)
424
- end
425
-
426
- it 'raises NoMethodError when sent an invalid attribute' do
427
- expect { @s.blah }.to raise_error NoMethodError
428
- end
429
-
430
- it 'sets condition attributes when sent valid attributes' do
431
- @s.name_eq = 'Ernie'
432
- expect(@s.name_eq).to eq 'Ernie'
433
- end
434
-
435
- context 'with joins' do
436
- it 'allows chaining to access nested conditions' do
437
- @s.groupings = [
438
- { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' }
439
- ]
440
- expect(@s.groupings.first.children_name_eq).to eq 'Ernie'
441
- end
442
- end
443
- end
444
- end
445
- end
@@ -1,11 +0,0 @@
1
- test:
2
- clients:
3
- default:
4
- database: ransack_mongoid_test
5
- hosts:
6
- - localhost:27017
7
- sessions:
8
- default:
9
- database: ransack_mongoid_test
10
- hosts:
11
- - localhost:27017
@@ -1,135 +0,0 @@
1
- require 'mongoid'
2
-
3
- Mongoid.load!(File.expand_path("../mongoid.yml", __FILE__), :test)
4
- Mongo::Logger.logger.level = Logger::WARN if defined?(Mongo)
5
- Mongoid.purge!
6
-
7
- class Person
8
- include Mongoid::Document
9
- include Mongoid::Timestamps
10
-
11
- field :name, type: String
12
- field :email, type: String
13
- field :only_search, type: String
14
- field :only_sort, type: String
15
- field :only_admin, type: String
16
- field :salary, type: Integer
17
- field :awesome, type: Boolean, default: false
18
-
19
- belongs_to :parent, :class_name => 'Person', inverse_of: :children
20
- has_many :children, :class_name => 'Person', inverse_of: :parent
21
-
22
- has_many :articles
23
- has_many :comments
24
-
25
- ransack_alias :term, :name_or_email
26
-
27
- # has_many :authored_article_comments, :through => :articles,
28
- # :source => :comments, :foreign_key => :person_id
29
-
30
- has_many :notes, :as => :notable
31
-
32
- default_scope -> { order(id: :desc) }
33
-
34
- scope :restricted, lambda { where(restricted: 1) }
35
- scope :active, lambda { where(active: 1) }
36
- scope :over_age, lambda { |y| where(:age.gt => y) }
37
-
38
- ransacker :reversed_name, :formatter => proc { |v| v.reverse } do |parent|
39
- parent.table[:name]
40
- end
41
-
42
- ransacker :doubled_name do |parent|
43
- # Arel::Nodes::InfixOperation.new(
44
- # '||', parent.table[:name], parent.table[:name]
45
- # )
46
- parent.table[:name]
47
- end
48
-
49
- def self.ransackable_attributes(auth_object = nil)
50
- if auth_object == :admin
51
- all_ransackable_attributes - ['only_sort']
52
- else
53
- all_ransackable_attributes - ['only_sort', 'only_admin']
54
- end
55
- end
56
-
57
- def self.ransortable_attributes(auth_object = nil)
58
- if auth_object == :admin
59
- all_ransackable_attributes - ['only_search']
60
- else
61
- all_ransackable_attributes - ['only_search', 'only_admin']
62
- end
63
- end
64
- end
65
-
66
- class Musician < Person
67
- end
68
-
69
- class Article
70
- include Mongoid::Document
71
-
72
- field :title, type: String
73
- field :body, type: String
74
-
75
- belongs_to :person
76
- has_many :comments
77
- # has_and_belongs_to_many :tags
78
- has_many :notes, :as => :notable
79
- end
80
-
81
- module Namespace
82
- class Article < ::Article
83
-
84
- end
85
- end
86
-
87
- class Comment
88
- include Mongoid::Document
89
-
90
- field :body, type: String
91
-
92
-
93
- belongs_to :article
94
- belongs_to :person
95
- end
96
-
97
- class Tag
98
- include Mongoid::Document
99
-
100
- field :name, type: String
101
-
102
- # has_and_belongs_to_many :articles
103
- end
104
-
105
- class Note
106
- include Mongoid::Document
107
-
108
- field :note, type: String
109
-
110
- belongs_to :notable, :polymorphic => true
111
- end
112
-
113
- module Schema
114
- def self.create
115
- 10.times do
116
- person = Person.make.save!
117
- Note.make.save!(:notable => person)
118
- 3.times do
119
- article = Article.create!(:person => person)
120
- 3.times do
121
- # article.tags = [Tag.make.save!, Tag.make.save!, Tag.make.save!]
122
- end
123
- Note.create.save!(:notable => article)
124
- 10.times do
125
- Comment.create.save!(:article => article, :person => person)
126
- end
127
- end
128
- end
129
-
130
- Comment.create!(
131
- :body => 'First post!',
132
- :article => Article.create!(:title => 'Hello, world!')
133
- )
134
- end
135
- end
@@ -1,14 +0,0 @@
1
- require 'mongoid_spec_helper'
2
-
3
- module Ransack
4
- describe Translate do
5
-
6
- describe '.attribute' do
7
- it 'translate namespaced attribute like AR does' do
8
- ar_translation = ::Namespace::Article.human_attribute_name(:title)
9
- ransack_translation = Ransack::Translate.attribute(:title, :context => ::Namespace::Article.search.context)
10
- expect(ransack_translation).to eq ar_translation
11
- end
12
- end
13
- end
14
- end
@@ -1,63 +0,0 @@
1
- require 'machinist/object'
2
- require 'sham'
3
- require 'faker'
4
- require 'pry'
5
- require 'mongoid'
6
- require 'ransack'
7
-
8
- I18n.enforce_available_locales = false
9
- Time.zone = 'Eastern Time (US & Canada)'
10
- I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'support', '*.yml')]
11
-
12
- Dir[File.expand_path('../{mongoid/helpers,mongoid/support,blueprints}/*.rb',
13
- __FILE__)]
14
- .each { |f| require f }
15
-
16
- Sham.define do
17
- name { Faker::Name.name }
18
- title { Faker::Lorem.sentence }
19
- body { Faker::Lorem.paragraph }
20
- salary { |index| 30000 + (index * 1000) }
21
- tag_name { Faker::Lorem.words(3).join(' ') }
22
- note { Faker::Lorem.words(7).join(' ') }
23
- only_admin { Faker::Lorem.words(3).join(' ') }
24
- only_search { Faker::Lorem.words(3).join(' ') }
25
- only_sort { Faker::Lorem.words(3).join(' ') }
26
- notable_id { |id| id }
27
- end
28
-
29
- RSpec.configure do |config|
30
- config.alias_it_should_behave_like_to :it_has_behavior, 'has behavior'
31
-
32
- config.before(:suite) do
33
- if ENV['DB'] == 'mongoid4'
34
- message = "Running Ransack specs with #{Mongoid.default_session.inspect
35
- }, Mongoid #{Mongoid::VERSION}, Moped #{Moped::VERSION
36
- }, Origin #{Origin::VERSION} and Ruby #{RUBY_VERSION}"
37
- else
38
- message = "Running Ransack specs with #{Mongoid.default_client.inspect
39
- }, Mongoid #{Mongoid::VERSION}, Mongo driver #{Mongo::VERSION}"
40
- end
41
- line = '=' * message.length
42
- puts line, message, line
43
- Schema.create
44
- end
45
-
46
- config.before(:all) { Sham.reset(:before_all) }
47
- config.before(:each) { Sham.reset(:before_each) }
48
-
49
- config.include RansackHelper
50
- end
51
-
52
- RSpec::Matchers.define :be_like do |expected|
53
- match do |actual|
54
- actual.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip ==
55
- expected.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip
56
- end
57
- end
58
-
59
- RSpec::Matchers.define :have_attribute_method do |expected|
60
- match do |actual|
61
- actual.attribute_method?(expected)
62
- end
63
- end
@@ -1,12 +0,0 @@
1
- =begin
2
- rails = ::ActiveRecord::VERSION::STRING.first(3)
3
-
4
- if %w(3.2 4.0 4.1).include?(rails) || rails == '3.1' && RUBY_VERSION < '2.2'
5
- describe 'Ransack' do
6
- it 'can be required without errors' do
7
- output = `bundle exec ruby -e "require 'ransack'" 2>&1`
8
- expect(output).to be_empty
9
- end
10
- end
11
- end
12
- =end