order_as_specified 1.2 → 1.7

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.
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "support/application_record"
1
4
  require "support/test_class"
2
5
  require "support/association_test_class"
3
6
 
@@ -10,7 +13,7 @@ RSpec.shared_examples ".order_as_specified" do
10
13
  end
11
14
 
12
15
  let(:shuffled_objects) do
13
- 5.times.map { |i| TestClass.create(field: "Field #{i}") }.shuffle
16
+ Array.new(5) { |i| TestClass.create(field: "Field #{i}") }.shuffle
14
17
  end
15
18
  let(:shuffled_object_fields) { shuffled_objects.map(&:field) }
16
19
  let(:shuffled_object_ids) { shuffled_objects.map(&:id) }
@@ -50,11 +53,75 @@ RSpec.shared_examples ".order_as_specified" do
50
53
 
51
54
  context "when the order includes nil" do
52
55
  let(:shuffled_objects) do
53
- 5.times.map do |i|
56
+ Array.new(5) do |i|
54
57
  TestClass.create(field: (i == 0 ? nil : "Field #{i}"))
55
58
  end.shuffle
56
59
  end
57
60
 
61
+ it "returns results in the given order" do
62
+ expect(subject.map(&:id)).to eq shuffled_object_ids
63
+ end
64
+ end
65
+ end
66
+
67
+ context "when the order is empty array" do
68
+ subject { TestClass.order_as_specified(field: []) }
69
+
70
+ let(:test_objects) do
71
+ Array.new(5) do |i|
72
+ TestClass.create(field: "Field #{i}")
73
+ end
74
+ end
75
+
76
+ it "keep the original order" do
77
+ test_objects # Build test objects
78
+ expect(subject.map(&:id)).
79
+ to eq test_objects.map(&:id)
80
+ end
81
+ end
82
+
83
+ context "when the order is a range" do
84
+ subject do
85
+ TestClass.order_as_specified(number_field: ranges).order(:number_field)
86
+ end
87
+
88
+ let(:ranges) { [(3..4), (0..2)] }
89
+ let(:numbers) { [0, 1, 2, 3, 4] }
90
+
91
+ let!(:test_objects) do
92
+ numbers.each do |i|
93
+ TestClass.create(number_field: i)
94
+ end
95
+ end
96
+
97
+ it "sorts according to range" do
98
+ expect(subject.map(&:number_field)).to eq [
99
+ *numbers.drop(3),
100
+ *numbers.take(3)
101
+ ]
102
+ end
103
+
104
+ context "when ranges are exclusive" do
105
+ let(:numbers) { [0, 1, 2, 3, 4, 0.9, 1.5] }
106
+
107
+ let(:ranges) { [(1...2), (0...1), (2...5)] }
108
+
109
+ it "sorts according to range" do
110
+ expect(subject.map(&:number_field)).to eq [
111
+ 1,
112
+ 1.5,
113
+ 0,
114
+ 0.9,
115
+ 2,
116
+ 3,
117
+ 4
118
+ ]
119
+ end
120
+ end
121
+
122
+ context "when ranges are in reverse order" do
123
+ let(:ranges) { [(5..0)] }
124
+
58
125
  it "raises an error" do
59
126
  expect { subject }.to raise_error(OrderAsSpecified::Error)
60
127
  end
@@ -96,21 +163,22 @@ RSpec.shared_examples ".order_as_specified" do
96
163
  end
97
164
  end
98
165
 
99
- context "input safety" do
166
+ describe "input safety" do
100
167
  before(:each) do
101
168
  2.times { |i| TestClass.create(field: "foo#{i}") }
102
169
  end
103
170
 
104
171
  it "sanitizes column values" do
105
- # Verify that the result set includes two records when using good column value.
172
+ # Verify that the result set includes two records when using good column
173
+ # value.
106
174
  good_value = "foo"
107
175
  records = TestClass.order_as_specified(field: [good_value]).to_a
108
176
  expect(records.count).to eq(2)
109
177
 
110
178
  # Attempt to inject a LIMIT clause into the query. If the SQL inputs are
111
179
  # properly sanitized, it will be ignored and the returned result set will
112
- # include two records. If not, the LIMIT clause will execute and the result
113
- # set will include just one record.
180
+ # include two records. If not, the LIMIT clause will execute and the
181
+ # result set will include just one record.
114
182
  bad_value = "' LIMIT 1 --"
115
183
  records = TestClass.order_as_specified(field: [bad_value]).to_a
116
184
  expect(records.count).to eq(2)
@@ -124,7 +192,39 @@ RSpec.shared_examples ".order_as_specified" do
124
192
  quoted_column = AssociationTestClass.connection.quote_column_name(column)
125
193
 
126
194
  sql = TestClass.order_as_specified(table => { column => ["foo"] }).to_sql
127
- expect(sql).to include("ORDER BY #{quoted_table}.#{quoted_column}")
195
+ pattern = "ORDER BY (CASE WHEN #{quoted_table}.#{quoted_column}"
196
+ expect(sql).to include(pattern)
197
+ end
198
+ end
199
+
200
+ context "when hash input is invalid" do
201
+ subject { TestClass.order_as_specified({}) }
202
+
203
+ it "raises an error" do
204
+ expect { subject }.to raise_error(OrderAsSpecified::Error)
205
+ end
206
+ end
207
+
208
+ context "when case insensitive option is used" do
209
+ subject do
210
+ TestClass.
211
+ order_as_specified(field: %w[abc def], case_insensitive: true).
212
+ pluck(TestClass.arel_table[:field].lower)
213
+ end
214
+
215
+ before :each do
216
+ TestClass.create!(
217
+ [
218
+ { field: "dEf" },
219
+ { field: "aBc" },
220
+ { field: "ABC" },
221
+ { field: "DEF" }
222
+ ]
223
+ )
224
+ end
225
+
226
+ it "orders in a case insensitive manner" do
227
+ expect(subject).to eq(%w[abc abc def def])
128
228
  end
129
229
  end
130
230
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,4 @@
1
- require "codeclimate-test-reporter"
2
- CodeClimate::TestReporter.start
1
+ # frozen_string_literal: true
3
2
 
4
3
  require "active_record"
5
4
 
data/spec/sqlite3_spec.rb CHANGED
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
  require "shared/order_as_specified_examples"
3
5
  require "config/test_setup_migration"
4
6
 
5
7
  RSpec.describe "SQLite3" do
6
- before :all do
8
+ before :all do # rubocop:disable RSpec/BeforeAfterAll
7
9
  ActiveRecord::Base.establish_connection(:sqlite3_test)
8
10
  TestSetupMigration.migrate(:up)
9
11
  end
10
12
 
11
- after(:all) { ActiveRecord::Base.remove_connection }
13
+ after(:all) { ActiveRecord::Base.remove_connection } # rubocop:disable RSpec/BeforeAfterAll
12
14
 
13
15
  include_examples ".order_as_specified"
14
16
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
@@ -1,4 +1,6 @@
1
- class AssociationTestClass < ActiveRecord::Base
1
+ # frozen_string_literal: true
2
+
3
+ class AssociationTestClass < ApplicationRecord
2
4
  extend OrderAsSpecified
3
5
 
4
6
  belongs_to :test_class
@@ -1,4 +1,6 @@
1
- class TestClass < ActiveRecord::Base
1
+ # frozen_string_literal: true
2
+
3
+ class TestClass < ApplicationRecord
2
4
  extend OrderAsSpecified
3
5
 
4
6
  has_one :association_test_class
metadata CHANGED
@@ -1,141 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: order_as_specified
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.2'
4
+ version: '1.7'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Evelyn
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-13 00:00:00.000000000 Z
11
+ date: 2021-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.1
19
+ version: 5.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.1
26
+ version: 5.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.7'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.7'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: codeclimate-test-reporter
42
+ name: mysql2
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0.4'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0.4'
55
- - !ruby/object:Gem::Dependency
56
- name: overcommit
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '0.23'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ~>
67
- - !ruby/object:Gem::Version
68
- version: '0.23'
54
+ version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: pg
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
- - - '>='
59
+ - - ">="
74
60
  - !ruby/object:Gem::Version
75
- version: '0.18'
61
+ version: '0'
76
62
  type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
- - - '>='
66
+ - - ">="
81
67
  - !ruby/object:Gem::Version
82
- version: '0.18'
68
+ version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: rspec
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
- - - ~>
73
+ - - ">="
88
74
  - !ruby/object:Gem::Version
89
- version: '3.2'
75
+ version: '0'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
- - - ~>
80
+ - - ">="
95
81
  - !ruby/object:Gem::Version
96
- version: '3.2'
82
+ version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rspec-rails
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
- - - ~>
102
- - !ruby/object:Gem::Version
103
- version: '3.2'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ~>
109
- - !ruby/object:Gem::Version
110
- version: '3.2'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ~>
87
+ - - ">="
116
88
  - !ruby/object:Gem::Version
117
- version: '0.29'
89
+ version: '0'
118
90
  type: :development
119
91
  prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
93
  requirements:
122
- - - ~>
94
+ - - ">="
123
95
  - !ruby/object:Gem::Version
124
- version: '0.29'
96
+ version: '0'
125
97
  - !ruby/object:Gem::Dependency
126
98
  name: sqlite3
127
99
  requirement: !ruby/object:Gem::Requirement
128
100
  requirements:
129
- - - '>='
101
+ - - "~>"
130
102
  - !ruby/object:Gem::Version
131
- version: '1.3'
103
+ version: '1.4'
132
104
  type: :development
133
105
  prerelease: false
134
106
  version_requirements: !ruby/object:Gem::Requirement
135
107
  requirements:
136
- - - '>='
108
+ - - "~>"
137
109
  - !ruby/object:Gem::Version
138
- version: '1.3'
110
+ version: '1.4'
139
111
  description: Obtain ActiveRecord results with a custom ordering with no need to store
140
112
  anything in the database.
141
113
  email:
@@ -144,59 +116,66 @@ executables: []
144
116
  extensions: []
145
117
  extra_rdoc_files: []
146
118
  files:
147
- - .gitignore
148
- - .overcommit.yml
149
- - .rubocop.yml
150
- - .travis.yml
119
+ - ".dependabot/config.yml"
120
+ - ".github/workflows/auto-approve-dependabot.yml"
121
+ - ".github/workflows/remove-needs-qa.yml"
122
+ - ".github/workflows/tests.yml"
123
+ - ".gitignore"
124
+ - ".rubocop.yml"
151
125
  - CHANGELOG.md
126
+ - CODE_OF_CONDUCT.md
152
127
  - Gemfile
153
128
  - LICENSE.txt
154
129
  - README.md
130
+ - RELEASING.md
155
131
  - lib/order_as_specified.rb
156
132
  - lib/order_as_specified/error.rb
157
133
  - lib/order_as_specified/version.rb
158
134
  - order_as_specified.gemspec
159
135
  - spec/config/database.yml
160
136
  - spec/config/test_setup_migration.rb
137
+ - spec/mysql_spec.rb
161
138
  - spec/order_as_specified_spec.rb
162
139
  - spec/postgresql_spec.rb
163
140
  - spec/shared/order_as_specified_examples.rb
164
141
  - spec/spec_helper.rb
165
142
  - spec/sqlite3_spec.rb
143
+ - spec/support/application_record.rb
166
144
  - spec/support/association_test_class.rb
167
145
  - spec/support/test_class.rb
168
146
  homepage: https://github.com/panorama-ed/order_as_specified
169
147
  licenses:
170
148
  - MIT
171
149
  metadata: {}
172
- post_install_message:
150
+ post_install_message:
173
151
  rdoc_options: []
174
152
  require_paths:
175
153
  - lib
176
154
  required_ruby_version: !ruby/object:Gem::Requirement
177
155
  requirements:
178
- - - '>='
156
+ - - ">="
179
157
  - !ruby/object:Gem::Version
180
158
  version: '0'
181
159
  required_rubygems_version: !ruby/object:Gem::Requirement
182
160
  requirements:
183
- - - '>='
161
+ - - ">="
184
162
  - !ruby/object:Gem::Version
185
163
  version: '0'
186
164
  requirements: []
187
- rubyforge_project:
188
- rubygems_version: 2.2.2
189
- signing_key:
165
+ rubyforge_project:
166
+ rubygems_version: 2.7.6.2
167
+ signing_key:
190
168
  specification_version: 4
191
169
  summary: Add arbitrary ordering to ActiveRecord queries.
192
170
  test_files:
193
171
  - spec/config/database.yml
194
172
  - spec/config/test_setup_migration.rb
173
+ - spec/mysql_spec.rb
195
174
  - spec/order_as_specified_spec.rb
196
175
  - spec/postgresql_spec.rb
197
176
  - spec/shared/order_as_specified_examples.rb
198
177
  - spec/spec_helper.rb
199
178
  - spec/sqlite3_spec.rb
179
+ - spec/support/application_record.rb
200
180
  - spec/support/association_test_class.rb
201
181
  - spec/support/test_class.rb
202
- has_rdoc: