ransack 1.8.4 → 3.2.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.
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