order_as_specified 1.5 → 1.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c11fb5ed7165ea2a50cdab0cdb421ac0faa8a187539b0c1f661d6f64fe8107ed
4
- data.tar.gz: 975e533ab7a733c8f3f68c7b6363dab96ac1d90a08f4223ba7bcc067443d21a8
3
+ metadata.gz: 119668cc688124610b87036f0f929c0fbcc35ef4acea5e1c2a1cdc48c1101241
4
+ data.tar.gz: a17df8766bfe178cac883311d8ba4b165b4e43a9c4afd1d8e4b8af0e099d5010
5
5
  SHA512:
6
- metadata.gz: 8b56240f7f9527be2dfb266583ffcccd7aa8992da08139e1824f19c1ea2b82266b5a88bcbbe87db740571d07cd53b4c20bad5d67d4bd4c56d2d3fa0fc132c0cc
7
- data.tar.gz: cc12430e2ef88f18225235de1900a0e1662a908da3f2f411cb64fcf9336a82f6fad886ceb99f840c718d140b832002f47aafaebc807844cdcd5cfe51ba1e8a90
6
+ metadata.gz: 1a53e19dc18fb420fbf88f1fb535b46a0a5c5b13a84158c237a350243f8cfefa5f78ae048087bcc939ea7ecab12e4b7aec5c62bae7960d921a83704f9a53a45e
7
+ data.tar.gz: 0ca1d4697d3634f442edb58173cf4d7f6199571ae1a69415cb6cb2d8b93079ff588023e5549f99ca998979cfeff93ee3ea1f2f0810afd90c8501df829d41e104
data/.gitignore CHANGED
@@ -13,3 +13,4 @@
13
13
  *.a
14
14
  mkmf.log
15
15
  *.gem
16
+ .rubocop-https---raw-githubusercontent-com-panorama-ed-code-conventions-master-rubocop-yml
@@ -1,17 +1,5 @@
1
- require:
2
- - rubocop/rspec/focused
1
+ inherit_from:
2
+ - https://raw.githubusercontent.com/panorama-ed/code-conventions/master/rubocop.yml
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 2.3
6
-
7
- AbcSize:
8
- Enabled: false
9
-
10
- DotPosition:
11
- EnforcedStyle: trailing
12
-
13
- MethodLength:
14
- Enabled: false
15
-
16
- StringLiterals:
17
- EnforcedStyle: double_quotes
5
+ TargetRubyVersion: 2.4 # Keep this in sync with .travis.yml
@@ -1,28 +1,41 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.5
4
- - 2.5.1
3
+ - 2.6
4
+ - 2.5
5
+ - 2.4 # Keep this in sync with .rubocop.yml
6
+ # We test up to the latest version of Ruby here, and test these Ruby versions
7
+ # against all support ActiveRecord versions. One test will be "duplicated"
8
+ # below when we calculate code coverage, but I don't know how to avoid that and
9
+ # still test all combinations of Ruby and ActiveRecord.
5
10
  before_script:
6
- - psql -c 'create database order_as_specified_test;' -U postgres
7
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
8
- - chmod +x ./cc-test-reporter
9
- - ./cc-test-reporter before-build
11
+ - psql -c 'create database order_as_specified_test;' -U postgres
12
+ - mysql -e 'CREATE DATABASE order_as_specified_test;'
10
13
  script:
11
- - bundle exec rspec
12
- - bundle exec rubocop
13
- after_script:
14
- - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
15
- addons:
16
- postgresql: "9.3"
14
+ - bundle exec rspec
15
+ services:
16
+ - mysql
17
+ - postgresql
17
18
  env:
18
- global:
19
- CC_TEST_REPORTER_ID=781c439d68cbb928316deaec1c7136f98423e1db87238f99cbc95183de94df9e
20
19
  matrix:
21
- - AR_VERSION="~> 5.0.0"
22
- - AR_VERSION="~> 5.1.0"
23
- - AR_VERSION="~> 5.2.0"
20
+ - ACTIVERECORD_VERSION="~> 5.2.0"
21
+ - ACTIVERECORD_VERSION="~> 5.1.0"
22
+ - ACTIVERECORD_VERSION="~> 5.0.0"
23
+ matrix:
24
+ include:
25
+ - rvm: 2.6
26
+ script:
27
+ - bundle exec rspec
28
+ - gem install --no-document rubocop rubocop-rspec-focused && rubocop
29
+ env:
30
+ - CODE_COVERAGE=true
31
+ - ACTIVERECORD_VERSION="~> 5.2.0"
32
+ branches:
33
+ only:
34
+ # We always run tests for PRs. This prevents running PR tests twice (once "for
35
+ # the PR" and once "for the branch"), though we do want tests to run always
36
+ # run on master.
37
+ - master
24
38
  notifications:
25
39
  email: false
26
- hipchat:
27
- rooms:
28
- secure: pLL6WXsWnvigZNgcYYwr0el3AG3WbRXOV4zAoBx/pAD/y51/KOjWboUO5szOqIicdSBJTIY5el7wK4uUi5elseumjl1jvOQSG7izvCGzDekuJuOTj9f6MdLtigbIaWO5/NWtXw0/JGHDQJpB4HyOv1mGAjQ3Y6MKxMNv+RUsgRI=
40
+ slack:
41
+ secure: lVaScxPymqeYlTh+KlprWDK+O18BkQTyNSBTfzsLFzWF3Dy+p1rp2aeh0AhuLVYQDrlmFZ7cDMZ1ZYDyV2Y6lLtt+4ii7rATagI8R9WUVYb90C97tu1M6v5tpIjoTEOLx9hGc66heyvq1hNCKXbTqsqmrD69FYdjuXnOfrIs6J4=
@@ -1,3 +1,13 @@
1
+ # Unreleased (`master`)
2
+
3
+ # 1.6
4
+
5
+ We are dropping official support for Ruby 2.3 and below, though they may
6
+ continue to work.
7
+
8
+ This release adds support for ordering by `Range`s. Big thanks to
9
+ [Karl-Aksel Puulmann](https://github.com/macobo) for adding this functionality!
10
+
1
11
  # 1.5
2
12
 
3
13
  This release improves performance by switching to use `CASE` statements. Huge
data/Gemfile CHANGED
@@ -5,4 +5,6 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in order_as_specified.gemspec
6
6
  gemspec
7
7
 
8
- gem "activerecord", ENV["AR_VERSION"] if ENV["AR_VERSION"]
8
+ if ENV["TRAVIS"] == "true" && ENV["ACTIVERECORD_VERSION"]
9
+ gem "activerecord", ENV["ACTIVERECORD_VERSION"]
10
+ end
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
- [![Code Climate](https://codeclimate.com/github/panorama-ed/order_as_specified/badges/gpa.svg)](https://codeclimate.com/github/panorama-ed/order_as_specified) [![Test Coverage](https://codeclimate.com/github/panorama-ed/order_as_specified/badges/coverage.svg)](https://codeclimate.com/github/panorama-ed/order_as_specified) [![Build Status](https://travis-ci.org/panorama-ed/order_as_specified.svg)](https://travis-ci.org/panorama-ed/order_as_specified) [![Inline docs](http://inch-ci.org/github/panorama-ed/order_as_specified.png)](http://inch-ci.org/github/panorama-ed/order_as_specified) [![Gem Version](https://badge.fury.io/rb/order_as_specified.svg)](http://badge.fury.io/rb/order_as_specified)
1
+ [![Code Coverage](https://codecov.io/gh/panorama-ed/order_as_specified/branch/master/graph/badge.svg)](https://codecov.io/gh/panorama-ed/order_as_specified)
2
+ [![Build Status](https://travis-ci.com/panorama-ed/order_as_specified.svg)](https://travis-ci.com/panorama-ed/order_as_specified)
3
+ [![Inline docs](http://inch-ci.org/github/panorama-ed/order_as_specified.png)](http://inch-ci.org/github/panorama-ed/order_as_specified)
4
+ [![Gem Version](https://badge.fury.io/rb/order_as_specified.svg)](http://badge.fury.io/rb/order_as_specified)
2
5
 
3
6
  # OrderAsSpecified
4
7
 
@@ -0,0 +1,14 @@
1
+ # Releasing
2
+
3
+ ## These are steps for the maintainer to take to release a new version of this gem.
4
+
5
+ 1. Create a new branch for bumping the version.
6
+ 1. On the new branch, update the VERSION constant in `lib/order_as_specified/version.rb`.
7
+ 1. Update the Changelog.
8
+ 1. Commit the change: `git add -A && git commit -m 'Bump to vX.X'`.
9
+ 1. Add a tag: `git tag -am "vX.X" vX.X`.
10
+ 1. Push the branch and tag: `git push --follow-tags`
11
+ 1. Make a PR.
12
+ 1. Merge the PR.
13
+ 1. Push to rubygems: `gem build order_as_specified.gemspec && gem push *.gem && rm *.gem`
14
+ 1. Celebrate!
@@ -18,15 +18,15 @@ module OrderAsSpecified
18
18
  table = connection.quote_table_name(params[:table])
19
19
  attribute = connection.quote_column_name(params[:attribute])
20
20
 
21
- # We have to explicitly quote for now because SQL sanitization for ORDER BY
22
- # queries isn't in less current versions of Rails.
23
- # See: https://github.com/rails/rails/pull/13008
24
- db_connection = ActiveRecord::Base.connection
25
21
  conditions = params[:values].map do |value|
26
22
  raise OrderAsSpecified::Error, "Cannot order by `nil`" if value.nil?
27
23
 
28
- # Sanitize each value to reduce the risk of SQL injection.
29
- "#{table}.#{attribute}=#{db_connection.quote(value)}"
24
+ if value.is_a? Range
25
+ range_clause("#{table}.#{attribute}", value)
26
+ else
27
+ # Sanitize each value to reduce the risk of SQL injection.
28
+ "#{table}.#{attribute}=#{quote(value)}"
29
+ end
30
30
  end
31
31
 
32
32
  when_queries = conditions.map.with_index do |cond, index|
@@ -53,7 +53,9 @@ module OrderAsSpecified
53
53
  # @param hash [Hash] the ActiveRecord-style arguments, such as:
54
54
  # { other_objects: { id: [1, 5, 3] } }
55
55
  def extract_params(hash, table = table_name)
56
- raise "Could not parse params" unless hash.size == 1
56
+ unless hash.size == 1
57
+ raise OrderAsSpecified::Error, "Could not parse params"
58
+ end
57
59
 
58
60
  key, val = hash.first
59
61
 
@@ -67,4 +69,20 @@ module OrderAsSpecified
67
69
  }
68
70
  end
69
71
  end
72
+
73
+ def range_clause(col, range)
74
+ if range.first >= range.last
75
+ raise OrderAsSpecified::Error, "Range needs to be increasing"
76
+ end
77
+
78
+ op = range.exclude_end? ? "<" : "<="
79
+ "#{col} >= #{quote(range.first)} AND #{col} #{op} #{quote(range.last)}"
80
+ end
81
+
82
+ def quote(value)
83
+ # We have to explicitly quote for now because SQL sanitization for ORDER BY
84
+ # queries isn't in less current versions of Rails.
85
+ # See: https://github.com/rails/rails/pull/13008
86
+ ActiveRecord::Base.connection.quote(value)
87
+ end
70
88
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OrderAsSpecified
4
- VERSION = "1.5"
4
+ VERSION = "1.6"
5
5
  end
@@ -23,11 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "activerecord", ">= 5.0.0"
24
24
 
25
25
  spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "codecov"
27
+ spec.add_development_dependency "mysql2"
26
28
  spec.add_development_dependency "pg"
27
29
  spec.add_development_dependency "rspec"
28
30
  spec.add_development_dependency "rspec-rails"
29
- spec.add_development_dependency "rubocop"
30
- spec.add_development_dependency "rubocop-rspec-focused"
31
- spec.add_development_dependency "simplecov"
32
- spec.add_development_dependency "sqlite3"
31
+ spec.add_development_dependency "sqlite3", "~> 1.3.13"
33
32
  end
@@ -7,3 +7,9 @@ postgresql_test:
7
7
  adapter: postgresql
8
8
  database: order_as_specified_test
9
9
  username: postgres
10
+
11
+ mysql_test:
12
+ adapter: mysql2
13
+ database: order_as_specified_test
14
+ username: travis
15
+ encoding: utf8
@@ -9,6 +9,7 @@ class TestSetupMigration < VersionedMigration
9
9
 
10
10
  create_table :test_classes do |t|
11
11
  t.string :field
12
+ t.float :number_field
12
13
  end
13
14
 
14
15
  create_table :association_test_classes do |t|
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "shared/order_as_specified_examples"
5
+ require "config/test_setup_migration"
6
+
7
+ RSpec.describe "MySQL" do
8
+ before :all do
9
+ ActiveRecord::Base.establish_connection(:mysql_test)
10
+ TestSetupMigration.migrate(:up)
11
+ end
12
+
13
+ after(:all) { ActiveRecord::Base.remove_connection }
14
+
15
+ include_examples ".order_as_specified"
16
+ end
@@ -4,7 +4,6 @@ require "spec_helper"
4
4
  require "shared/order_as_specified_examples"
5
5
  require "config/test_setup_migration"
6
6
 
7
- # rubocop:disable Metrics/BlockLength
8
7
  RSpec.describe "PostgreSQL" do
9
8
  before :all do
10
9
  ActiveRecord::Base.establish_connection(:postgresql_test)
@@ -68,4 +67,3 @@ RSpec.describe "PostgreSQL" do
68
67
  end
69
68
  end
70
69
  end
71
- # rubocop:enable Metrics/BlockLength
@@ -4,7 +4,6 @@ require "support/application_record"
4
4
  require "support/test_class"
5
5
  require "support/association_test_class"
6
6
 
7
- # rubocop:disable Metrics/BlockLength
8
7
  RSpec.shared_examples ".order_as_specified" do
9
8
  # Clean up after each test. This is a lot lighter for these few tests than
10
9
  # trying to wrangle with RSpec-Rails to get transactional tests to work.
@@ -81,6 +80,54 @@ RSpec.shared_examples ".order_as_specified" do
81
80
  end
82
81
  end
83
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 "exclusive ranges" 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 "reverse ranges" do
123
+ let(:ranges) { [(5..0)] }
124
+
125
+ it "raises an error" do
126
+ expect { subject }.to raise_error(OrderAsSpecified::Error)
127
+ end
128
+ end
129
+ end
130
+
84
131
  context "with another table name specified" do
85
132
  subject do
86
133
  TestClass.
@@ -149,5 +196,12 @@ RSpec.shared_examples ".order_as_specified" do
149
196
  expect(sql).to include(pattern)
150
197
  end
151
198
  end
199
+
200
+ context "invalid hash input" 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
152
207
  end
153
- # rubocop:enable Metrics/BlockLength
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if ENV["TRAVIS"] == "true"
3
+ if ENV["TRAVIS"] == "true" && ENV["CODE_COVERAGE"] == "true"
4
4
  require "simplecov"
5
- SimpleCov.start
5
+ require "codecov"
6
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
6
7
  SimpleCov.start do
7
8
  # Omit the spec directory from being counted in code coverage calculations.
8
9
  add_filter "/spec/"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: order_as_specified
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.5'
4
+ version: '1.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Evelyn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-01 00:00:00.000000000 Z
11
+ date: 2019-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: pg
42
+ name: codecov
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: mysql2
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,21 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec-rails
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop
70
+ name: pg
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - ">="
@@ -95,7 +81,7 @@ dependencies:
95
81
  - !ruby/object:Gem::Version
96
82
  version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
- name: rubocop-rspec-focused
84
+ name: rspec
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - ">="
@@ -109,7 +95,7 @@ dependencies:
109
95
  - !ruby/object:Gem::Version
110
96
  version: '0'
111
97
  - !ruby/object:Gem::Dependency
112
- name: simplecov
98
+ name: rspec-rails
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
101
  - - ">="
@@ -126,16 +112,16 @@ dependencies:
126
112
  name: sqlite3
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
- - - ">="
115
+ - - "~>"
130
116
  - !ruby/object:Gem::Version
131
- version: '0'
117
+ version: 1.3.13
132
118
  type: :development
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
- - - ">="
122
+ - - "~>"
137
123
  - !ruby/object:Gem::Version
138
- version: '0'
124
+ version: 1.3.13
139
125
  description: Obtain ActiveRecord results with a custom ordering with no need to store
140
126
  anything in the database.
141
127
  email:
@@ -151,12 +137,14 @@ files:
151
137
  - Gemfile
152
138
  - LICENSE.txt
153
139
  - README.md
140
+ - RELEASING.md
154
141
  - lib/order_as_specified.rb
155
142
  - lib/order_as_specified/error.rb
156
143
  - lib/order_as_specified/version.rb
157
144
  - order_as_specified.gemspec
158
145
  - spec/config/database.yml
159
146
  - spec/config/test_setup_migration.rb
147
+ - spec/mysql_spec.rb
160
148
  - spec/order_as_specified_spec.rb
161
149
  - spec/postgresql_spec.rb
162
150
  - spec/shared/order_as_specified_examples.rb
@@ -192,6 +180,7 @@ summary: Add arbitrary ordering to ActiveRecord queries.
192
180
  test_files:
193
181
  - spec/config/database.yml
194
182
  - spec/config/test_setup_migration.rb
183
+ - spec/mysql_spec.rb
195
184
  - spec/order_as_specified_spec.rb
196
185
  - spec/postgresql_spec.rb
197
186
  - spec/shared/order_as_specified_examples.rb