order_as_specified 1.2 → 1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: