order_query 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 01cd918d06d860206e938baf5f500446132bdbd6
4
- data.tar.gz: 39882d3d3d1fb272f88597ed281973618b6f293c
2
+ SHA256:
3
+ metadata.gz: 140bea826457d9ad046a701da89e0073ca15f6631d3e996b5b44ba01fc7a7910
4
+ data.tar.gz: aae7c51f4c0c607455b92efa36ca71c2df86b0b7b49c022a94bb209452a6bc4e
5
5
  SHA512:
6
- metadata.gz: 8b23735d7393e0bc5e8842e644deb06f22618b50e68ed5537c1755c3e6dd88858189104d18cef2279d15fa9fc158dc8a3470570f980b13f929187e80be30d5d8
7
- data.tar.gz: a40ec816d36f311647c37515adf8866151505a4205b5c46e0d42f22f47c1f9ef7816a290df711876157bfefe25849065ddb86aff1d5bf4b3f1967ae1d187560e
6
+ metadata.gz: f3c6db46a213cd3acc4cddc7f9f35247ec7ac6c986005b2d4e9185128b2f8c12ec585230c879e5a911c9c4ff097b00eda7dd530f04f78e242715c0bcda27ed5d
7
+ data.tar.gz: 6171c2a35660bb8595bfae88e159cb65cafb93039ebd032b8257d5564e99dbedf51c6044d78df8382497b1d74c6a2493a155647ba7c68115c925a6fb2bf1a8a1
data/CHANGES.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.5.0
2
+
3
+ * Rails 6 now supported.
4
+ * Fixes support for `nil`s with explicit order, when a `nil` is neither
5
+ the first nor the last element of the explicit order,
6
+ e.g. `status: ['assigned', nil, 'fixed']`.
7
+ [#93b08877](https://github.com/glebm/order_query/commit/93b08877790a0ff02eea0d835def6ff3c40a83da)
8
+
1
9
  ## 0.4.1
2
10
 
3
11
  * If a column had a `nulls:` option and there were multiple records with `NULL`,
data/Gemfile CHANGED
@@ -2,11 +2,5 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gemspec
6
-
7
- # TODO: remove these lines and update spec/gemfiles/rails_5_2.gemfile once
8
- # Rails 5.2 is out.
9
- gem 'activerecord', '~> 5.2.0.rc1'
10
- gem 'activesupport', '~> 5.2.0.rc1'
11
-
12
- eval_gemfile './shared.gemfile'
5
+ eval_gemfile 'spec/gemfiles/rails_6_0.gemfile'
6
+ eval_gemfile 'rubocop.gemfile'
data/README.md CHANGED
@@ -11,7 +11,7 @@ This gem finds the next or previous record(s) relative to the current one effici
11
11
  Add to Gemfile:
12
12
 
13
13
  ```ruby
14
- gem 'order_query', '~> 0.4.1'
14
+ gem 'order_query', '~> 0.5.0'
15
15
  ```
16
16
 
17
17
  ## Usage
@@ -38,8 +38,9 @@ module OrderQuery
38
38
  "extra arguments: #{vals_and_or_dir.map(&:inspect) * ', '}"
39
39
  end
40
40
  @unique = unique.nil? ? (name.to_s == scope.primary_key) : unique
41
- if @order_enum && (@order_enum[0].nil? || @order_enum[-1].nil?)
41
+ if @order_enum&.include?(nil)
42
42
  fail ArgumentError, '`nulls` cannot be set if a value is null' if nulls
43
+
43
44
  @nullable = true
44
45
  @nulls = if @order_enum[0].nil?
45
46
  @direction == :desc ? :first : :last
@@ -87,7 +88,7 @@ module OrderQuery
87
88
  # @example for [:difficulty, ['Easy', 'Normal', 'Hard']]:
88
89
  # enum_side('Normal', :after) #=> ['Hard']
89
90
  # enum_side('Normal', :after, false) #=> ['Normal', 'Hard']
90
- def enum_side(value, side, strict = true)
91
+ def enum_side(value, side, strict = true) # rubocop:disable Metrics/AbcSize
91
92
  ord = order_enum
92
93
  pos = ord.index(value)
93
94
  if pos
@@ -22,6 +22,7 @@ module OrderQuery
22
22
  if @columns.detect(&:unique?)
23
23
  fail ArgumentError, 'Unique column must be last'
24
24
  end
25
+
25
26
  @columns << Column.new(base_scope, base_scope.primary_key)
26
27
  end
27
28
  @order_by_sql = SQL::OrderBy.new(@columns)
@@ -51,6 +51,7 @@ module OrderQuery
51
51
  if optimize_enum_bools_nil?(col)
52
52
  return optimize_enum_bools_nil(col, reverse)
53
53
  end
54
+
54
55
  clauses = []
55
56
  with_nulls = false
56
57
  if col.order_enum.include?(nil)
@@ -69,6 +70,7 @@ module OrderQuery
69
70
  def needs_null_sort?(col, reverse,
70
71
  nulls_direction = col.nulls_direction(reverse))
71
72
  return false unless col.nullable?
73
+
72
74
  nulls_direction != col.default_nulls_direction(reverse)
73
75
  end
74
76
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OrderQuery
4
- VERSION = '0.4.1'
4
+ VERSION = '0.5.0'
5
5
  end
@@ -4,7 +4,18 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec path: '../../'
6
6
 
7
- gem 'activerecord', '~> 5.0.5'
8
- gem 'activesupport', '~> 5.0.5'
7
+ gem 'activerecord', '~> 5.0.6'
8
+ gem 'activesupport', '~> 5.0.6'
9
+
10
+ platforms :mri, :rbx do
11
+ # https://github.com/rails/rails/blob/v5.0.6/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L4
12
+ gem 'mysql2', '< 0.5'
13
+
14
+ # https://github.com/rails/rails/blob/v5.0.6/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L2
15
+ gem 'pg', '~> 0.18'
16
+
17
+ # https://github.com/rails/rails/blob/v5.0.6/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L7
18
+ gem 'sqlite3', '~> 1.3.6'
19
+ end
9
20
 
10
21
  eval_gemfile '../../shared.gemfile'
@@ -7,4 +7,15 @@ gemspec path: '../../'
7
7
  gem 'activerecord', '~> 5.1.3'
8
8
  gem 'activesupport', '~> 5.1.3'
9
9
 
10
+ platforms :mri, :rbx do
11
+ # https://github.com/rails/rails/blob/v5.1.5/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L4
12
+ gem 'mysql2', '< 0.5'
13
+
14
+ # https://github.com/rails/rails/blob/v5.1.5/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L2
15
+ gem 'pg', '>= 0.18', '< 2.0'
16
+
17
+ # https://github.com/rails/rails/blob/v5.1.5/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L10
18
+ gem 'sqlite3', '~> 1.3.6'
19
+ end
20
+
10
21
  eval_gemfile '../../shared.gemfile'
@@ -4,7 +4,18 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec path: '../../'
6
6
 
7
- gem 'activerecord', '~> 5.2.0.rc1'
8
- gem 'activesupport', '~> 5.2.0.rc1'
7
+ gem 'activerecord', '~> 5.2.3'
8
+ gem 'activesupport', '~> 5.2.3'
9
+
10
+ platforms :mri, :rbx do
11
+ # https://github.com/rails/rails/blob/v5.2.3/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6
12
+ gem 'mysql2', '>= 0.4.4', '< 0.6.0'
13
+
14
+ # https://github.com/rails/rails/blob/v5.2.3/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4
15
+ gem 'pg', '>= 0.18', '< 2.0'
16
+
17
+ # https://github.com/rails/rails/blob/v5.2.3/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L12
18
+ gem 'sqlite3', '~> 1.3', '>= 1.3.6'
19
+ end
9
20
 
10
21
  eval_gemfile '../../shared.gemfile'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec path: '../../'
6
+
7
+ gem 'activerecord', '~> 5.2.3'
8
+ gem 'activesupport', '~> 5.2.3'
9
+
10
+ platforms :mri, :rbx do
11
+ # https://github.com/rails/rails/blob/v6.0.0/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13
12
+ gem 'sqlite3', '~> 1.4'
13
+
14
+ # https://github.com/rails/rails/blob/v6.0.0/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4
15
+ gem 'pg', '>= 0.18', '< 2.0'
16
+
17
+ # https://github.com/rails/rails/blob/v6.0.0/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6
18
+ gem 'mysql2', '>= 0.4.4'
19
+ end
20
+
21
+ eval_gemfile '../../shared.gemfile'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ eval_gemfile '../../rubocop.gemfile'
@@ -221,20 +221,27 @@ RSpec.describe 'OrderQuery' do
221
221
  end
222
222
 
223
223
  context 'nil in string enum' do
224
+ display = ->(issue) { "##{issue.id}-#{issue.priority || 'NULL'}" }
224
225
  priorities = [nil, 'low', 'medium', 'high']
225
- let!(:issues) { priorities.map { |p| create_issue(priority: p) } }
226
- priorities.permutation do |p|
227
- it "works for #{p} (desc)" do
228
- scope = Issue.seek([:priority, p]).scope
229
- actual = scope.all.map(&:priority)
230
- expected = p
231
- expect(actual).to eq(expected), scope.to_sql
226
+ let!(:issues) do
227
+ priorities.flat_map do |p|
228
+ [create_issue(priority: p), create_issue(priority: p)]
232
229
  end
233
- it "works for #{p} (asc)" do
234
- scope = Issue.seek([:priority, p, :asc]).scope
235
- actual = scope.all.map(&:priority)
236
- expected = p.reverse
237
- expect(actual).to eq(expected), scope.to_sql
230
+ end
231
+ priorities.permutation do |perm|
232
+ it "works for #{perm} (desc)" do
233
+ expect_order(
234
+ Issue.seek([:priority, perm]),
235
+ issues.sort_by { |x| [perm.index(x.priority), x.id] },
236
+ &display
237
+ )
238
+ end
239
+ it "works for #{perm} (asc)" do
240
+ expect_order(
241
+ Issue.seek([:priority, perm, :asc]),
242
+ issues.sort_by { |x| [perm.index(x.priority), -x.id] }.reverse,
243
+ &display
244
+ )
238
245
  end
239
246
  end
240
247
  end
@@ -340,69 +347,33 @@ RSpec.describe 'OrderQuery' do
340
347
  end
341
348
 
342
349
  context 'nil in boolean enum' do
350
+ display = ->(post) { "##{post.id}-#{post.pinned || 'NULL'}" }
343
351
  states = [nil, false, true]
344
- let!(:posts) { states.map { |state| create_post(pinned: state) } }
345
- states.permutation do |p|
346
- it "works for #{p} (desc)" do
347
- scope = Post.seek([:pinned, p]).scope
348
- actual = scope.all.map(&:pinned)
349
- expected = p
350
- expect(actual).to eq(expected), scope.to_sql
352
+ let!(:posts) do
353
+ states.flat_map do |state|
354
+ [create_post(pinned: state), create_post(pinned: state)]
355
+ end
356
+ end
357
+ states.permutation do |perm|
358
+ it "works for #{perm} (desc)" do
359
+ expect_order(
360
+ Post.seek([:pinned, perm]),
361
+ posts.sort_by { |x| [perm.index(x.pinned), x.id] },
362
+ &display
363
+ )
351
364
  end
352
- it "works for #{p} (asc)" do
353
- scope = Post.seek([:pinned, p, :asc]).scope
354
- actual = scope.all.map(&:pinned)
355
- expected = p.reverse
356
- expect(actual).to eq(expected), scope.to_sql
365
+ it "works for #{perm} (asc)" do
366
+ expect_order(
367
+ Post.seek([:pinned, perm, :asc]),
368
+ posts.sort_by { |x| [-perm.index(x.pinned), x.id] },
369
+ &display
370
+ )
357
371
  end
358
372
  end
359
373
  end
360
374
 
361
375
  context 'nil published_at' do
362
- # rubocop:disable Metrics/AbcSize
363
-
364
- def expect_next(space, post, next_post)
365
- point = space.at(post)
366
- actual = point.next
367
- failure_message =
368
- "expected: #{post.title}.next == #{next_post.title}\n" \
369
- " got: #{actual ? actual.title : 'nil'}\n" \
370
- " all: #{space.scope.all.map(&:title)}\n" \
371
- " sql: #{space.at(post).after.limit(1).to_sql}"
372
- expect(actual ? actual.title : nil).to eq(next_post.title),
373
- failure_message
374
- end
375
-
376
- def expect_prev(space, post, prev_post)
377
- point = space.at(post)
378
- actual = point.previous
379
- failure_message =
380
- "expected: #{post.title}.previous == #{prev_post.title}\n" \
381
- " got: #{actual ? actual.title : 'nil'}\n" \
382
- " all: #{space.scope.all.map(&:title)}\n" \
383
- " sql: #{space.at(post).before.limit(1).to_sql}"
384
- expect(actual ? actual.title : nil).to eq(prev_post.title),
385
- failure_message
386
- end
387
-
388
- def expect_order(space, ordered)
389
- actual = space.scope.all.map(&:title)
390
- expected = ordered.map(&:title)
391
- failure_message =
392
- "expected: #{expected * ', '}\n"\
393
- " got: #{actual * ', '}\n"\
394
- " sql: #{space.scope.to_sql}"
395
- expect(actual).to eq(expected), failure_message
396
-
397
- ordered.each_cons(2) do |post, next_post|
398
- expect_next space, post, next_post
399
- expect_prev space, next_post, post
400
- end
401
- expect_next space, ordered.last, ordered.first
402
- expect_prev space, ordered.first, ordered.last
403
- end
404
-
405
- # rubocop:enable Metrics/AbcSize
376
+ display = ->(post) { post.title }
406
377
 
407
378
  let! :null_1 do
408
379
  Post.create!(title: 'null_1', published_at: nil).reload
@@ -419,22 +390,22 @@ RSpec.describe 'OrderQuery' do
419
390
 
420
391
  it 'orders nulls first (desc)' do
421
392
  space = Post.seek([:published_at, :desc, nulls: :first])
422
- expect_order space, [null_1, null_2, older, newer]
393
+ expect_order space, [null_1, null_2, older, newer], &display
423
394
  end
424
395
 
425
396
  it 'orders nulls first (asc)' do
426
397
  space = Post.seek([:published_at, :asc, nulls: :first])
427
- expect_order space, [null_1, null_2, newer, older]
398
+ expect_order space, [null_1, null_2, newer, older], &display
428
399
  end
429
400
 
430
401
  it 'orders nulls last (desc)' do
431
402
  space = Post.seek([:published_at, :desc, nulls: :last])
432
- expect_order space, [older, newer, null_1, null_2]
403
+ expect_order space, [older, newer, null_1, null_2], &display
433
404
  end
434
405
 
435
406
  it 'orders nulls last (asc)' do
436
407
  space = Post.seek([:published_at, :asc, nulls: :last])
437
- expect_order space, [newer, older, null_1, null_2]
408
+ expect_order space, [newer, older, null_1, null_2], &display
438
409
  end
439
410
  end
440
411
 
@@ -8,7 +8,7 @@ if ENV['COVERAGE'] && !%w[rbx jruby].include?(RUBY_ENGINE)
8
8
  end
9
9
  require 'order_query'
10
10
 
11
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
11
+ require_relative './support/order_expectation'
12
12
 
13
13
  require 'fileutils'
14
14
  FileUtils.mkpath 'log' unless File.directory? 'log'
@@ -35,3 +35,7 @@ else
35
35
  fail "Unknown DB adapter #{adapter}. "\
36
36
  'Valid adapters are: mysql2, postgresql, sqlite3.'
37
37
  end
38
+
39
+ RSpec.configure do |c|
40
+ c.include OrderExpectations
41
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrderExpectations
4
+ # rubocop:disable Metrics/AbcSize
5
+
6
+ def expect_next(space, record, next_record, &display)
7
+ point = space.at(record)
8
+ actual = point.next
9
+ failure_message =
10
+ "expected: next(#{display[record]}) == #{display[next_record]}\n" \
11
+ " got: #{actual ? display[actual] : 'nil'}\n" \
12
+ " all: #{space.scope.all.map(&display)}\n" \
13
+ " sql: #{space.at(record).after.limit(1).to_sql}"
14
+ expect(actual ? display[actual] : nil).to eq(display[next_record]),
15
+ failure_message
16
+ end
17
+
18
+ def expect_prev(space, record, prev_record, &display)
19
+ point = space.at(record)
20
+ actual = point.previous
21
+ failure_message =
22
+ "expected: previous(#{display[record]}) == #{display[prev_record]}\n" \
23
+ " got: #{actual ? display[actual] : 'nil'}\n" \
24
+ " all: #{space.scope.all.map(&display)}\n" \
25
+ " sql: #{space.at(record).before.limit(1).to_sql}"
26
+ expect(actual ? display[actual] : nil).to eq(display[prev_record]),
27
+ failure_message
28
+ end
29
+
30
+ def expect_order(space, ordered, &display)
31
+ all_actual = space.scope.all.map(&display)
32
+ all_expected = ordered.map(&display)
33
+ failure_message =
34
+ "expected: #{all_expected * ', '}\n"\
35
+ " got: #{all_actual * ', '}\n"\
36
+ " sql: #{space.scope.to_sql}"
37
+ expect(all_actual).to eq(all_expected), failure_message
38
+
39
+ ordered.each_cons(2) do |record, next_record|
40
+ expect_next space, record, next_record, &display
41
+ expect_prev space, next_record, record, &display
42
+ end
43
+ expect_next space, ordered.last, ordered.first, &display
44
+ expect_prev space, ordered.first, ordered.last, &display
45
+ end
46
+
47
+ # rubocop:enable Metrics/AbcSize
48
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: order_query
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gleb Mazovetskiy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-21 00:00:00.000000000 Z
11
+ date: 2019-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '5.0'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '6.0'
22
+ version: '7.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '5.0'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '6.0'
32
+ version: '7.0'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: '5.0'
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '6.0'
42
+ version: '7.0'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: '5.0'
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '6.0'
52
+ version: '7.0'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: rake
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -78,20 +78,6 @@ dependencies:
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
80
  version: '3.4'
81
- - !ruby/object:Gem::Dependency
82
- name: rubocop
83
- requirement: !ruby/object:Gem::Requirement
84
- requirements:
85
- - - "~>"
86
- - !ruby/object:Gem::Version
87
- version: 0.53.0
88
- type: :development
89
- prerelease: false
90
- version_requirements: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - "~>"
93
- - !ruby/object:Gem::Version
94
- version: 0.53.0
95
81
  - !ruby/object:Gem::Dependency
96
82
  name: simplecov
97
83
  requirement: !ruby/object:Gem::Requirement
@@ -131,8 +117,11 @@ files:
131
117
  - spec/gemfiles/rails_5_0.gemfile
132
118
  - spec/gemfiles/rails_5_1.gemfile
133
119
  - spec/gemfiles/rails_5_2.gemfile
120
+ - spec/gemfiles/rails_6_0.gemfile
121
+ - spec/gemfiles/rubocop.gemfile
134
122
  - spec/order_query_spec.rb
135
123
  - spec/spec_helper.rb
124
+ - spec/support/order_expectation.rb
136
125
  homepage: https://github.com/glebm/order_query
137
126
  licenses:
138
127
  - MIT
@@ -146,21 +135,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
135
  requirements:
147
136
  - - ">="
148
137
  - !ruby/object:Gem::Version
149
- version: '0'
138
+ version: 2.3.0
150
139
  required_rubygems_version: !ruby/object:Gem::Requirement
151
140
  requirements:
152
141
  - - ">="
153
142
  - !ruby/object:Gem::Version
154
143
  version: '0'
155
144
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.6.13
145
+ rubygems_version: 3.0.6
158
146
  signing_key:
159
147
  specification_version: 4
160
148
  summary: Find next / previous Active Record(s) in one query
161
149
  test_files:
162
150
  - spec/order_query_spec.rb
163
151
  - spec/spec_helper.rb
152
+ - spec/support/order_expectation.rb
164
153
  - spec/gemfiles/rails_5_1.gemfile
165
154
  - spec/gemfiles/rails_5_2.gemfile
155
+ - spec/gemfiles/rubocop.gemfile
166
156
  - spec/gemfiles/rails_5_0.gemfile
157
+ - spec/gemfiles/rails_6_0.gemfile