ransack 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codeql.yml +72 -0
  3. data/.github/workflows/deploy.yml +35 -0
  4. data/.github/workflows/test-deploy.yml +29 -0
  5. data/.github/workflows/test.yml +22 -39
  6. data/.rubocop.yml +3 -0
  7. data/CHANGELOG.md +118 -0
  8. data/CONTRIBUTING.md +38 -16
  9. data/Gemfile +10 -10
  10. data/README.md +9 -14
  11. data/bug_report_templates/test-ransacker-arel-present-predicate.rb +4 -0
  12. data/docs/.gitignore +0 -1
  13. data/docs/docs/getting-started/advanced-mode.md +1 -1
  14. data/docs/docs/getting-started/search-matches.md +1 -1
  15. data/docs/docs/getting-started/simple-mode.md +30 -26
  16. data/docs/docs/getting-started/sorting.md +1 -1
  17. data/docs/docs/getting-started/using-predicates.md +1 -1
  18. data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
  19. data/docs/docs/going-further/documentation.md +14 -2
  20. data/docs/docs/going-further/exporting-to-csv.md +2 -2
  21. data/docs/docs/going-further/form-customisation.md +1 -1
  22. data/docs/docs/going-further/i18n.md +3 -3
  23. data/docs/docs/going-further/merging-searches.md +1 -1
  24. data/docs/docs/going-further/other-notes.md +1 -1
  25. data/docs/docs/going-further/polymorphic-search.md +40 -0
  26. data/docs/docs/going-further/saving-queries.md +1 -1
  27. data/docs/docs/going-further/searching-postgres.md +1 -1
  28. data/docs/docs/going-further/wiki-contributors.md +82 -0
  29. data/docs/docs/intro.md +2 -2
  30. data/docs/docusaurus.config.js +16 -4
  31. data/docs/package.json +7 -2
  32. data/docs/yarn.lock +3036 -1917
  33. data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -1
  34. data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
  35. data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
  36. data/lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb +1 -0
  37. data/lib/ransack/adapters/active_record/base.rb +78 -7
  38. data/lib/ransack/adapters/active_record/context.rb +17 -49
  39. data/lib/ransack/configuration.rb +25 -12
  40. data/lib/ransack/constants.rb +125 -3
  41. data/lib/ransack/context.rb +34 -5
  42. data/lib/ransack/helpers/form_builder.rb +3 -3
  43. data/lib/ransack/helpers/form_helper.rb +4 -3
  44. data/lib/ransack/nodes/attribute.rb +2 -2
  45. data/lib/ransack/nodes/condition.rb +80 -7
  46. data/lib/ransack/nodes/grouping.rb +3 -3
  47. data/lib/ransack/nodes/node.rb +1 -1
  48. data/lib/ransack/nodes/value.rb +2 -2
  49. data/lib/ransack/predicate.rb +1 -1
  50. data/lib/ransack/ransacker.rb +1 -1
  51. data/lib/ransack/search.rb +9 -4
  52. data/lib/ransack/translate.rb +2 -2
  53. data/lib/ransack/version.rb +1 -1
  54. data/lib/ransack/visitor.rb +38 -2
  55. data/lib/ransack.rb +3 -6
  56. data/ransack.gemspec +3 -3
  57. data/spec/helpers/polyamorous_helper.rb +2 -8
  58. data/spec/ransack/adapters/active_record/base_spec.rb +73 -0
  59. data/spec/ransack/configuration_spec.rb +9 -9
  60. data/spec/ransack/helpers/form_builder_spec.rb +8 -8
  61. data/spec/ransack/helpers/form_helper_spec.rb +60 -2
  62. data/spec/ransack/nodes/condition_spec.rb +24 -0
  63. data/spec/ransack/nodes/value_spec.rb +115 -0
  64. data/spec/ransack/predicate_spec.rb +36 -1
  65. data/spec/ransack/translate_spec.rb +1 -1
  66. data/spec/support/schema.rb +27 -10
  67. metadata +20 -21
  68. data/docs/package-lock.json +0 -9207
  69. data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -20
  70. data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +0 -79
  71. data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -11
  72. data/lib/polyamorous.rb +0 -1
  73. data/lib/ransack/adapters/active_record/ransack/constants.rb +0 -128
  74. data/lib/ransack/adapters/active_record/ransack/context.rb +0 -56
  75. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +0 -69
  76. data/lib/ransack/adapters/active_record/ransack/translate.rb +0 -8
  77. data/lib/ransack/adapters/active_record/ransack/visitor.rb +0 -47
  78. data/lib/ransack/adapters.rb +0 -64
  79. data/lib/ransack/nodes.rb +0 -8
  80. /data/lib/ransack/{adapters/active_record.rb → active_record.rb} +0 -0
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ module Ransack
4
+ module Nodes
5
+ describe Value do
6
+ let(:context) { Context.for(Person) }
7
+
8
+ subject do
9
+ Value.new(context, raw_value)
10
+ end
11
+
12
+ context "with a date value" do
13
+ let(:raw_value) { "2022-05-23" }
14
+
15
+ [:date].each do |type|
16
+ it "should cast #{type} correctly" do
17
+ result = subject.cast(type)
18
+
19
+ expect(result).to be_a_kind_of(Date)
20
+ expect(result).to eq(Date.parse(raw_value))
21
+ end
22
+ end
23
+ end
24
+
25
+ context "with a timestamp value" do
26
+ let(:raw_value) { "2022-05-23 10:40:02 -0400" }
27
+
28
+ [:datetime, :timestamp, :time, :timestamptz].each do |type|
29
+ it "should cast #{type} correctly" do
30
+ result = subject.cast(type)
31
+
32
+ expect(result).to be_a_kind_of(Time)
33
+ expect(result).to eq(Time.zone.parse(raw_value))
34
+ end
35
+ end
36
+ end
37
+
38
+ Constants::TRUE_VALUES.each do |value|
39
+ context "with a true boolean value (#{value})" do
40
+ let(:raw_value) { value.to_s }
41
+
42
+ it "should cast boolean correctly" do
43
+ result = subject.cast(:boolean)
44
+ expect(result).to eq(true)
45
+ end
46
+ end
47
+ end
48
+
49
+ Constants::FALSE_VALUES.each do |value|
50
+ context "with a false boolean value (#{value})" do
51
+ let(:raw_value) { value.to_s }
52
+
53
+ it "should cast boolean correctly" do
54
+ result = subject.cast(:boolean)
55
+
56
+ expect(result).to eq(false)
57
+ end
58
+ end
59
+ end
60
+
61
+ ["12", "101.5"].each do |value|
62
+ context "with an integer value (#{value})" do
63
+ let(:raw_value) { value }
64
+
65
+ it "should cast #{value} to integer correctly" do
66
+ result = subject.cast(:integer)
67
+
68
+ expect(result).to be_an(Integer)
69
+ expect(result).to eq(value.to_i)
70
+ end
71
+ end
72
+ end
73
+
74
+ ["12", "101.5"].each do |value|
75
+ context "with a float value (#{value})" do
76
+ let(:raw_value) { value }
77
+
78
+ it "should cast #{value} to float correctly" do
79
+ result = subject.cast(:float)
80
+
81
+ expect(result).to be_an(Float)
82
+ expect(result).to eq(value.to_f)
83
+ end
84
+ end
85
+ end
86
+
87
+ ["12", "101.5"].each do |value|
88
+ context "with a decimal value (#{value})" do
89
+ let(:raw_value) { value }
90
+
91
+ it "should cast #{value} to decimal correctly" do
92
+ result = subject.cast(:decimal)
93
+
94
+ expect(result).to be_a(BigDecimal)
95
+ expect(result).to eq(value.to_d)
96
+ end
97
+ end
98
+ end
99
+
100
+ ["12", "101.513"].each do |value|
101
+ context "with a money value (#{value})" do
102
+ let(:raw_value) { value }
103
+
104
+ it "should cast #{value} to money correctly" do
105
+ result = subject.cast(:money)
106
+
107
+ expect(result).to be_a(String)
108
+ expect(result).to eq(value.to_f.to_s)
109
+ end
110
+ end
111
+ end
112
+
113
+ end
114
+ end
115
+ end
@@ -35,6 +35,13 @@ module Ransack
35
35
  @s.awesome_eq = nil
36
36
  expect(@s.result.to_sql).not_to match /WHERE/
37
37
  end
38
+
39
+ it 'generates a = condition with a huge integer value' do
40
+ val = 123456789012345678901
41
+ @s.salary_eq = val
42
+ field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
43
+ expect(@s.result.to_sql).to match /#{field} = #{val}/
44
+ end
38
45
  end
39
46
 
40
47
  describe 'lteq' do
@@ -56,6 +63,13 @@ module Ransack
56
63
  @s.salary_lteq = nil
57
64
  expect(@s.result.to_sql).not_to match /WHERE/
58
65
  end
66
+
67
+ it 'generates a <= condition with a huge integer value' do
68
+ val = 123456789012345678901
69
+ @s.salary_lteq = val
70
+ field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
71
+ expect(@s.result.to_sql).to match /#{field} <= #{val}/
72
+ end
59
73
  end
60
74
 
61
75
  describe 'lt' do
@@ -77,6 +91,13 @@ module Ransack
77
91
  @s.salary_lt = nil
78
92
  expect(@s.result.to_sql).not_to match /WHERE/
79
93
  end
94
+
95
+ it 'generates a = condition with a huge integer value' do
96
+ val = 123456789012345678901
97
+ @s.salary_lt = val
98
+ field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
99
+ expect(@s.result.to_sql).to match /#{field} < #{val}/
100
+ end
80
101
  end
81
102
 
82
103
  describe 'gteq' do
@@ -98,6 +119,13 @@ module Ransack
98
119
  @s.salary_gteq = nil
99
120
  expect(@s.result.to_sql).not_to match /WHERE/
100
121
  end
122
+
123
+ it 'generates a >= condition with a huge integer value' do
124
+ val = 123456789012345678901
125
+ @s.salary_gteq = val
126
+ field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
127
+ expect(@s.result.to_sql).to match /#{field} >= #{val}/
128
+ end
101
129
  end
102
130
 
103
131
  describe 'gt' do
@@ -119,6 +147,13 @@ module Ransack
119
147
  @s.salary_gt = nil
120
148
  expect(@s.result.to_sql).not_to match /WHERE/
121
149
  end
150
+
151
+ it 'generates a > condition with a huge integer value' do
152
+ val = 123456789012345678901
153
+ @s.salary_gt = val
154
+ field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
155
+ expect(@s.result.to_sql).to match /#{field} > #{val}/
156
+ end
122
157
  end
123
158
 
124
159
  describe 'cont' do
@@ -368,7 +403,7 @@ module Ransack
368
403
  expect(@s.result.to_sql).to match /#{field} IS NULL/
369
404
  end
370
405
 
371
- describe 'with association qeury' do
406
+ describe 'with association query' do
372
407
  it 'generates a value IS NOT NULL query' do
373
408
  @s.comments_id_not_null = true
374
409
  sql = @s.result.to_sql
@@ -8,7 +8,7 @@ module Ransack
8
8
  ar_translation = ::Namespace::Article.human_attribute_name(:title)
9
9
  ransack_translation = Ransack::Translate.attribute(
10
10
  :title,
11
- :context => ::Namespace::Article.ransack.context
11
+ context: ::Namespace::Article.ransack.context
12
12
  )
13
13
  expect(ransack_translation).to eq ar_translation
14
14
  end
@@ -28,7 +28,24 @@ else
28
28
  )
29
29
  end
30
30
 
31
- class Person < ActiveRecord::Base
31
+ # This is just a test app with no sensitive data, so we explicitly allowlist all
32
+ # attributes and associations for search. In general, end users should
33
+ # explicitly authorize each model, but this shows a way to configure the
34
+ # unrestricted default behavior of versions prior to Ransack 4.
35
+ #
36
+ class ApplicationRecord < ActiveRecord::Base
37
+ self.abstract_class = true
38
+
39
+ def self.ransackable_attributes(auth_object = nil)
40
+ authorizable_ransackable_attributes
41
+ end
42
+
43
+ def self.ransackable_associations(auth_object = nil)
44
+ authorizable_ransackable_associations
45
+ end
46
+ end
47
+
48
+ class Person < ApplicationRecord
32
49
  default_scope { order(id: :desc) }
33
50
  belongs_to :parent, class_name: 'Person', foreign_key: :parent_id
34
51
  has_many :children, class_name: 'Person', foreign_key: :parent_id
@@ -111,9 +128,9 @@ class Person < ActiveRecord::Base
111
128
 
112
129
  def self.ransackable_attributes(auth_object = nil)
113
130
  if auth_object == :admin
114
- super - ['only_sort']
131
+ authorizable_ransackable_attributes - ['only_sort']
115
132
  else
116
- super - ['only_sort', 'only_admin']
133
+ authorizable_ransackable_attributes - ['only_sort', 'only_admin']
117
134
  end
118
135
  end
119
136
 
@@ -129,7 +146,7 @@ end
129
146
  class Musician < Person
130
147
  end
131
148
 
132
- class Article < ActiveRecord::Base
149
+ class Article < ApplicationRecord
133
150
  belongs_to :person
134
151
  has_many :comments
135
152
  has_and_belongs_to_many :tags
@@ -182,7 +199,7 @@ end
182
199
  class StoryArticle < Article
183
200
  end
184
201
 
185
- class Recommendation < ActiveRecord::Base
202
+ class Recommendation < ApplicationRecord
186
203
  belongs_to :person
187
204
  belongs_to :target_person, class_name: 'Person'
188
205
  belongs_to :article
@@ -200,22 +217,22 @@ module Namespace
200
217
  end
201
218
  end
202
219
 
203
- class Comment < ActiveRecord::Base
220
+ class Comment < ApplicationRecord
204
221
  belongs_to :article
205
222
  belongs_to :person
206
223
 
207
224
  default_scope { where(disabled: false) }
208
225
  end
209
226
 
210
- class Tag < ActiveRecord::Base
227
+ class Tag < ApplicationRecord
211
228
  has_and_belongs_to_many :articles
212
229
  end
213
230
 
214
- class Note < ActiveRecord::Base
231
+ class Note < ApplicationRecord
215
232
  belongs_to :notable, polymorphic: true
216
233
  end
217
234
 
218
- class Account < ActiveRecord::Base
235
+ class Account < ApplicationRecord
219
236
  belongs_to :agent_account, class_name: "Account"
220
237
  belongs_to :trade_account, class_name: "Account"
221
238
  end
@@ -308,7 +325,7 @@ module Schema
308
325
  end
309
326
 
310
327
  module SubDB
311
- class Base < ActiveRecord::Base
328
+ class Base < ApplicationRecord
312
329
  self.abstract_class = true
313
330
  establish_connection(
314
331
  adapter: 'sqlite3',
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ransack
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ernie Miller
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2022-03-30 00:00:00.000000000 Z
15
+ date: 2023-02-09 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activerecord
@@ -20,28 +20,28 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 6.0.4
23
+ version: 6.1.5
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
28
  - - ">="
29
29
  - !ruby/object:Gem::Version
30
- version: 6.0.4
30
+ version: 6.1.5
31
31
  - !ruby/object:Gem::Dependency
32
32
  name: activesupport
33
33
  requirement: !ruby/object:Gem::Requirement
34
34
  requirements:
35
35
  - - ">="
36
36
  - !ruby/object:Gem::Version
37
- version: 6.0.4
37
+ version: 6.1.5
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  requirements:
42
42
  - - ">="
43
43
  - !ruby/object:Gem::Version
44
- version: 6.0.4
44
+ version: 6.1.5
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: i18n
47
47
  requirement: !ruby/object:Gem::Requirement
@@ -69,8 +69,11 @@ extra_rdoc_files: []
69
69
  files:
70
70
  - ".github/FUNDING.yml"
71
71
  - ".github/SECURITY.md"
72
+ - ".github/workflows/codeql.yml"
72
73
  - ".github/workflows/cronjob.yml"
74
+ - ".github/workflows/deploy.yml"
73
75
  - ".github/workflows/rubocop.yml"
76
+ - ".github/workflows/test-deploy.yml"
74
77
  - ".github/workflows/test.yml"
75
78
  - ".gitignore"
76
79
  - ".nojekyll"
@@ -95,6 +98,7 @@ files:
95
98
  - docs/docs/getting-started/sorting.md
96
99
  - docs/docs/getting-started/using-predicates.md
97
100
  - docs/docs/going-further/_category_.json
101
+ - docs/docs/going-further/acts-as-taggable-on.md
98
102
  - docs/docs/going-further/associations.md
99
103
  - docs/docs/going-further/custom-predicates.md
100
104
  - docs/docs/going-further/documentation.md
@@ -105,13 +109,14 @@ files:
105
109
  - docs/docs/going-further/img/create_release.png
106
110
  - docs/docs/going-further/merging-searches.md
107
111
  - docs/docs/going-further/other-notes.md
112
+ - docs/docs/going-further/polymorphic-search.md
108
113
  - docs/docs/going-further/ransackers.md
109
114
  - docs/docs/going-further/release_process.md
110
115
  - docs/docs/going-further/saving-queries.md
111
116
  - docs/docs/going-further/searching-postgres.md
117
+ - docs/docs/going-further/wiki-contributors.md
112
118
  - docs/docs/intro.md
113
119
  - docs/docusaurus.config.js
114
- - docs/package-lock.json
115
120
  - docs/package.json
116
121
  - docs/sidebars.js
117
122
  - docs/src/components/HomepageFeatures/index.js
@@ -135,30 +140,23 @@ files:
135
140
  - docs/static/logo/ransack.png
136
141
  - docs/static/logo/ransack.svg
137
142
  - docs/yarn.lock
138
- - lib/polyamorous.rb
139
- - lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb
140
- - lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb
141
- - lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb
142
143
  - lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb
143
144
  - lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb
144
145
  - lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb
145
146
  - lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb
146
147
  - lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb
147
148
  - lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb
149
+ - lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb
150
+ - lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb
151
+ - lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb
148
152
  - lib/polyamorous/join.rb
149
153
  - lib/polyamorous/polyamorous.rb
150
154
  - lib/polyamorous/swapping_reflection_class.rb
151
155
  - lib/polyamorous/tree_node.rb
152
156
  - lib/ransack.rb
153
- - lib/ransack/adapters.rb
154
- - lib/ransack/adapters/active_record.rb
157
+ - lib/ransack/active_record.rb
155
158
  - lib/ransack/adapters/active_record/base.rb
156
159
  - lib/ransack/adapters/active_record/context.rb
157
- - lib/ransack/adapters/active_record/ransack/constants.rb
158
- - lib/ransack/adapters/active_record/ransack/context.rb
159
- - lib/ransack/adapters/active_record/ransack/nodes/condition.rb
160
- - lib/ransack/adapters/active_record/ransack/translate.rb
161
- - lib/ransack/adapters/active_record/ransack/visitor.rb
162
160
  - lib/ransack/configuration.rb
163
161
  - lib/ransack/constants.rb
164
162
  - lib/ransack/context.rb
@@ -192,7 +190,6 @@ files:
192
190
  - lib/ransack/locale/zh-CN.yml
193
191
  - lib/ransack/locale/zh-TW.yml
194
192
  - lib/ransack/naming.rb
195
- - lib/ransack/nodes.rb
196
193
  - lib/ransack/nodes/attribute.rb
197
194
  - lib/ransack/nodes/bindable.rb
198
195
  - lib/ransack/nodes/condition.rb
@@ -226,6 +223,7 @@ files:
226
223
  - spec/ransack/helpers/form_helper_spec.rb
227
224
  - spec/ransack/nodes/condition_spec.rb
228
225
  - spec/ransack/nodes/grouping_spec.rb
226
+ - spec/ransack/nodes/value_spec.rb
229
227
  - spec/ransack/predicate_spec.rb
230
228
  - spec/ransack/search_spec.rb
231
229
  - spec/ransack/translate_spec.rb
@@ -244,14 +242,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
244
242
  requirements:
245
243
  - - ">="
246
244
  - !ruby/object:Gem::Version
247
- version: '2.6'
245
+ version: '2.7'
248
246
  required_rubygems_version: !ruby/object:Gem::Requirement
249
247
  requirements:
250
248
  - - ">="
251
249
  - !ruby/object:Gem::Version
252
250
  version: '0'
253
251
  requirements: []
254
- rubygems_version: 3.2.32
252
+ rubygems_version: 3.4.6
255
253
  signing_key:
256
254
  specification_version: 4
257
255
  summary: Object-based searching for Active Record.
@@ -275,6 +273,7 @@ test_files:
275
273
  - spec/ransack/helpers/form_helper_spec.rb
276
274
  - spec/ransack/nodes/condition_spec.rb
277
275
  - spec/ransack/nodes/grouping_spec.rb
276
+ - spec/ransack/nodes/value_spec.rb
278
277
  - spec/ransack/predicate_spec.rb
279
278
  - spec/ransack/search_spec.rb
280
279
  - spec/ransack/translate_spec.rb