order_as_specified 1.6 → 1.7

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
2
  SHA256:
3
- metadata.gz: 119668cc688124610b87036f0f929c0fbcc35ef4acea5e1c2a1cdc48c1101241
4
- data.tar.gz: a17df8766bfe178cac883311d8ba4b165b4e43a9c4afd1d8e4b8af0e099d5010
3
+ metadata.gz: d928c44adb61e277076bd76af0ac1568b132a0f9ab49050d1b047fee59305714
4
+ data.tar.gz: bcbf4c9b1f4061ae9798535dff306c27c7b845bd827a9cd9f2e0ee7ee195c427
5
5
  SHA512:
6
- metadata.gz: 1a53e19dc18fb420fbf88f1fb535b46a0a5c5b13a84158c237a350243f8cfefa5f78ae048087bcc939ea7ecab12e4b7aec5c62bae7960d921a83704f9a53a45e
7
- data.tar.gz: 0ca1d4697d3634f442edb58173cf4d7f6199571ae1a69415cb6cb2d8b93079ff588023e5549f99ca998979cfeff93ee3ea1f2f0810afd90c8501df829d41e104
6
+ metadata.gz: 58d477da354092f0f3c7e9a034c14a76b04ac80599d46850ce064dd84ce0d172cbef0efd9ac6a3a7c467ba7472250299698aad1aa6311f7f679a4cc44d231483
7
+ data.tar.gz: bcf2ab1b90641f027ea0b9200bc442d77902448764a4f473552d2f6d4ec46c30023ce7bf893ddd678787212858ee2a85a738c0d10008d85fd7911fc3a37f2b17
@@ -0,0 +1,46 @@
1
+ # This is a dependabot configuration file. When this file is seen on github, a
2
+ # dependabot configuration is created for the project. We can use this to
3
+ # control various aspects of the automated dependency checking, such as the
4
+ # frequency and the target_branch.
5
+ #
6
+ # Reference: https://dependabot.com/docs/config-file/
7
+ version: 1
8
+ update_configs:
9
+ # This configures dependency updates for one package manager. In some
10
+ # projects, such as warehouse, where we have Ruby and Python, there can be
11
+ # separate package_manager entries.
12
+ - package_manager: "ruby:bundler"
13
+ directory: "/"
14
+ update_schedule: "weekly"
15
+
16
+ default_labels:
17
+ - "dependencies"
18
+ - "Needs QA"
19
+
20
+ # Dependabot will use a repository's default branch. This will override
21
+ # that.
22
+ # target_branch: "master"
23
+
24
+ allowed_updates:
25
+ - match:
26
+ dependency_type: "direct"
27
+
28
+ automerged_updates:
29
+ # This allows all dependencies that are used for development, e.g., rspec,
30
+ # rspec-mock, vcr, etc, to be automatically updated. This is generally
31
+ # okay because the dependencies are not used in production.
32
+ - match:
33
+ dependency_type: "development"
34
+ update_type: "all"
35
+
36
+ # # This is an example entry to enable automerging of a specific dependency
37
+ # # when the update is only for minor or patch semantic versions.
38
+ # #
39
+ # # The dependency_name can also be a wildcard.
40
+ # #
41
+ # # This is left commented, but whitelisting a dependency for automatic
42
+ # # merging is as simple as creating a new entry that looks like the below.
43
+ # - match:
44
+ # dependency_type: "all"
45
+ # dependency_name: "aws-sdk-s3"
46
+ # update_type: "semver:minor"
@@ -0,0 +1,26 @@
1
+ # This workflow auto-approves pull-requests when the github actor is a
2
+ # dependabot user and it is opening a new pull request.
3
+ #
4
+ # The problem that this workflow solves is that we have branch protection on
5
+ # our repositories that prevent PRs from merging unless there is an
6
+ # approval present. The problem is that this will block PRs that dependabot
7
+ # may want to merge automatically. Auto-approving dependabot PRs will allow
8
+ # the automatic merge to complete. We control what gets automerged through
9
+ # the dependabot configuration.
10
+ #
11
+ # This is a known issue: https://github.com/dependabot/feedback/issues/852
12
+ name: Auto-approve dependabot pull requests
13
+ on:
14
+ pull_request:
15
+ types: [opened]
16
+
17
+ jobs:
18
+ dependabot-triage:
19
+ runs-on: ubuntu-latest
20
+ if: (github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
21
+
22
+ steps:
23
+ - name: Auto-approve for dependabot
24
+ uses: hmarr/auto-approve-action@v2.0.0
25
+ with:
26
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
@@ -0,0 +1,35 @@
1
+ # This workflow removes a "Needs QA" label from a PR when the actor is the
2
+ # dependabot user merging a PR.
3
+ #
4
+ # We need this mechanism to allow for automerging whitelisted dependencies while
5
+ # also allowing for blocking a merge to master for deployment (in the way that
6
+ # our other PRs work). When the automerge script runs in henchman, it looks
7
+ # for `Needs QA` on github pull requests, and if the label is present,
8
+ # blocks the commit from merging.
9
+ name: Remove 'Needs QA' label for auto-merged PRs.
10
+ on:
11
+ pull_request:
12
+ types: [closed]
13
+
14
+ jobs:
15
+ remove-label:
16
+ runs-on: ubuntu-latest
17
+ if: >
18
+ (github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
19
+ && github.event.pull_request.merged
20
+
21
+ steps:
22
+ # Our triage workflow adds 'Needs QA' to the PR in order to block it from
23
+ # merging to production. This removes that label when dependabot is doing
24
+ # the merging.
25
+ - name: Remove QA Label
26
+ uses: actions/github-script@0.4.0
27
+ with:
28
+ github-token: ${{ secrets.GITHUB_TOKEN }}
29
+ script: |
30
+ github.issues.removeLabel({
31
+ issue_number: context.issue.number,
32
+ owner: context.repo.owner,
33
+ repo: context.repo.repo,
34
+ name: 'Needs QA'
35
+ })
@@ -0,0 +1,61 @@
1
+ # based on https://github.com/ruby/setup-ruby/blob/master/README.md
2
+ name: Tests
3
+ on: [push, pull_request]
4
+ jobs:
5
+ ci:
6
+ name: CI
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ ubuntu-latest ]
11
+ ruby: [ 2.5, 2.6, 2.7 ]
12
+ runs-on: ${{ matrix.os }}
13
+ services:
14
+ postgres:
15
+ image: postgres:latest
16
+ env:
17
+ POSTGRES_USER: postgres
18
+ POSTGRES_PASSWORD: postgres
19
+ POSTGRES_DB: order_as_specified_test
20
+ options: >-
21
+ --health-cmd pg_isready
22
+ --health-interval 10s
23
+ --health-timeout 5s
24
+ --health-retries 5
25
+ ports:
26
+ - 5432:5432
27
+ mysql:
28
+ image: mysql:latest
29
+ env:
30
+ MYSQL_USER: mysql
31
+ MYSQL_PASSWORD: mysql
32
+ MYSQL_ROOT_PASSWORD: mysql
33
+ MYSQL_DATABASE: order_as_specified_test
34
+ ports:
35
+ - 3306:3306
36
+ options: >-
37
+ --health-cmd "mysqladmin ping"
38
+ --health-interval 10s
39
+ --health-timeout 5s
40
+ --health-retries 5
41
+ env:
42
+ CI: true
43
+ steps:
44
+ - uses: actions/checkout@v2
45
+ - uses: ruby/setup-ruby@v1
46
+ with:
47
+ ruby-version: ${{ matrix.ruby }}
48
+ - uses: actions/cache@v1
49
+ with:
50
+ path: vendor/bundle
51
+ key: bundle-use-ruby-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/Gemfile.lock') }}
52
+ restore-keys: |
53
+ bundle-use-ruby-${{ matrix.os }}-${{ matrix.ruby }}-
54
+ - run: sudo apt-get install libsqlite3-dev
55
+ - name: bundle install
56
+ run: |
57
+ ruby -v
58
+ bundle config path vendor/bundle
59
+ bundle install --jobs 4 --retry 3
60
+ - run: bundle exec rubocop
61
+ - run: bundle exec rspec
data/.gitignore CHANGED
@@ -13,4 +13,3 @@
13
13
  *.a
14
14
  mkmf.log
15
15
  *.gem
16
- .rubocop-https---raw-githubusercontent-com-panorama-ed-code-conventions-master-rubocop-yml
data/.rubocop.yml CHANGED
@@ -1,5 +1,2 @@
1
- inherit_from:
2
- - https://raw.githubusercontent.com/panorama-ed/code-conventions/master/rubocop.yml
3
-
4
- AllCops:
5
- TargetRubyVersion: 2.4 # Keep this in sync with .travis.yml
1
+ inherit_gem:
2
+ panolint: rubocop.yml
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Unreleased (`master`)
2
2
 
3
+ # 1.7
4
+
5
+ This release adds support for `nil` values in the ordering list. Thanks to
6
+ [yfulmes](https://github.com/yfulmes) for requesting this feature!
7
+
3
8
  # 1.6
4
9
 
5
10
  We are dropping official support for Ruby 2.3 and below, though they may
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at engineering@panoramaed.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- # Specify your gem's dependencies in order_as_specified.gemspec
5
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
6
+
7
+ # Specify your gem's dependencies in unique_attributes.gemspec
6
8
  gemspec
7
9
 
8
- if ENV["TRAVIS"] == "true" && ENV["ACTIVERECORD_VERSION"]
9
- gem "activerecord", ENV["ACTIVERECORD_VERSION"]
10
+ group :development do
11
+ gem "panolint", github: "panorama-ed/panolint", branch: "main"
10
12
  end
data/README.md CHANGED
@@ -142,6 +142,20 @@ TestObject.order_as_specified(language: ["fr", "es"])
142
142
  ]>
143
143
  ```
144
144
 
145
+ The order can also include `nil` attributes:
146
+
147
+ ```ruby
148
+ TestObject.order_as_specified(language: ["es", nil, "fr"])
149
+ => #<ActiveRecord::Relation [
150
+ #<TestObject id: 3, language: "es">,
151
+ #<TestObject id: 1, language: nil>,
152
+ #<TestObject id: 4, language: nil>,
153
+ #<TestObject id: 2, language: "fr">
154
+ ]>
155
+ ```
156
+
157
+ ### `distinct_on`
158
+
145
159
  In databases that support it (such as PostgreSQL), you can also use an option to
146
160
  add a `DISTINCT ON` to your query when you would otherwise have duplicates:
147
161
 
@@ -154,10 +168,20 @@ TestObject.order_as_specified(distinct_on: true, language: ["fr", "en"])
154
168
  ]>
155
169
  ```
156
170
 
157
- Note that if a `nil` value is passed in the ordering an error is raised, because
158
- databases do not have good or consistent support for ordering with `NULL` values
159
- in an arbitrary order, so we don't permit this behavior instead of allowing an
160
- unexpected result.
171
+ ### `case_insensitive`
172
+
173
+ If you want objects to come back in an order that is case-insensitive, you can
174
+ pass the `case_insensitive: true` value to the `order_as_specified` call, as in:
175
+
176
+ ```ruby
177
+ TestObject.order_as_specified(case_insensitive: true, language: ["fr", "en"])
178
+ => #<ActiveRecord::Relation [
179
+ #<TestObject language: "fr">
180
+ #<TestObject language: "FR">
181
+ #<TestObject language: "EN">
182
+ #<TestObject language: "en">
183
+ ]>
184
+ ```
161
185
 
162
186
  ## Limitations
163
187
 
data/RELEASING.md CHANGED
@@ -6,9 +6,9 @@
6
6
  1. On the new branch, update the VERSION constant in `lib/order_as_specified/version.rb`.
7
7
  1. Update the Changelog.
8
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
9
  1. Make a PR.
12
10
  1. Merge the PR.
11
+ 1. Add a tag: `git tag -am "vX.X" vX.X`.
12
+ 1. Push the tag: `git push --tags`
13
13
  1. Push to rubygems: `gem build order_as_specified.gemspec && gem push *.gem && rm *.gem`
14
14
  1. Celebrate!
@@ -12,33 +12,39 @@ module OrderAsSpecified
12
12
  # @return [ActiveRecord::Relation] the objects, ordered as specified
13
13
  def order_as_specified(hash)
14
14
  distinct_on = hash.delete(:distinct_on)
15
+ case_insensitive = hash.delete(:case_insensitive)
16
+
15
17
  params = extract_params(hash)
16
18
  return all if params[:values].empty?
17
19
 
18
- table = connection.quote_table_name(params[:table])
19
- attribute = connection.quote_column_name(params[:attribute])
20
+ table = Arel::Table.new(params[:table])
21
+ node = Arel::Nodes::Case.new
20
22
 
21
- conditions = params[:values].map do |value|
22
- raise OrderAsSpecified::Error, "Cannot order by `nil`" if value.nil?
23
+ params[:values].each_with_index do |value, index|
24
+ attribute = table[params[:attribute]]
25
+ condition =
26
+ if value.is_a?(Range)
27
+ if value.first >= value.last
28
+ raise OrderAsSpecified::Error, "Range needs to be increasing"
29
+ end
23
30
 
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
- end
31
+ attribute.between(value)
32
+ elsif case_insensitive
33
+ attribute.matches(value)
34
+ else
35
+ attribute.eq(value)
36
+ end
31
37
 
32
- when_queries = conditions.map.with_index do |cond, index|
33
- "WHEN #{cond} THEN #{index}"
38
+ node.when(condition).then(index)
34
39
  end
35
- case_query = "CASE #{when_queries.join(' ')} ELSE #{conditions.size} END"
36
- scope = order(Arel.sql("#{case_query} ASC"))
40
+
41
+ node.else(node.conditions.size)
42
+ scope = order(Arel::Nodes::Ascending.new(table.grouping(node)))
37
43
 
38
44
  if distinct_on
39
- scope = scope.select(
40
- Arel.sql("DISTINCT ON (#{case_query}) #{table}.*")
41
- )
45
+ distinct = Arel::Nodes::DistinctOn.new(node)
46
+ table_alias = connection.quote_table_name(table.name)
47
+ scope = scope.select(Arel.sql("#{distinct.to_sql} #{table_alias}.*"))
42
48
  end
43
49
 
44
50
  scope
@@ -69,20 +75,4 @@ module OrderAsSpecified
69
75
  }
70
76
  end
71
77
  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
88
78
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OrderAsSpecified
4
- VERSION = "1.6"
4
+ VERSION = "1.7"
5
5
  end
@@ -23,10 +23,13 @@ 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
26
  spec.add_development_dependency "mysql2"
28
27
  spec.add_development_dependency "pg"
29
28
  spec.add_development_dependency "rspec"
30
29
  spec.add_development_dependency "rspec-rails"
31
- spec.add_development_dependency "sqlite3", "~> 1.3.13"
30
+
31
+ # Older versions of Rails locked in the SQLite3 version, so we have to
32
+ # explicitly specify the version here
33
+ sqlite3 = ENV["ACTIVERECORD_VERSION"] == "~> 5.0.0" ? "~> 1.3.13" : "~> 1.4"
34
+ spec.add_development_dependency "sqlite3", sqlite3
32
35
  end
@@ -5,11 +5,15 @@ sqlite3_test:
5
5
 
6
6
  postgresql_test:
7
7
  adapter: postgresql
8
+ host: localhost
8
9
  database: order_as_specified_test
9
10
  username: postgres
11
+ password: postgres
10
12
 
11
13
  mysql_test:
12
14
  adapter: mysql2
13
- database: order_as_specified_test
14
- username: travis
15
+ host: 127.0.0.1
15
16
  encoding: utf8
17
+ database: order_as_specified_test
18
+ username: mysql
19
+ password: mysql
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- VersionedMigration = ActiveRecord::Migration[ActiveRecord::Migration.current_version] # rubocop:disable Metrics/LineLength
3
+ VersionedMigration = ActiveRecord::Migration[ActiveRecord::Migration.current_version] # rubocop:disable Layout/LineLength
4
4
 
5
5
  class TestSetupMigration < VersionedMigration
6
6
  def up
data/spec/mysql_spec.rb CHANGED
@@ -5,12 +5,12 @@ require "shared/order_as_specified_examples"
5
5
  require "config/test_setup_migration"
6
6
 
7
7
  RSpec.describe "MySQL" do
8
- before :all do
8
+ before :all do # rubocop:disable RSpec/BeforeAfterAll
9
9
  ActiveRecord::Base.establish_connection(:mysql_test)
10
10
  TestSetupMigration.migrate(:up)
11
11
  end
12
12
 
13
- after(:all) { ActiveRecord::Base.remove_connection }
13
+ after(:all) { ActiveRecord::Base.remove_connection } # rubocop:disable RSpec/BeforeAfterAll
14
14
 
15
15
  include_examples ".order_as_specified"
16
16
  end
@@ -5,12 +5,12 @@ require "shared/order_as_specified_examples"
5
5
  require "config/test_setup_migration"
6
6
 
7
7
  RSpec.describe "PostgreSQL" do
8
- before :all do
8
+ before :all do # rubocop:disable RSpec/BeforeAfterAll
9
9
  ActiveRecord::Base.establish_connection(:postgresql_test)
10
10
  TestSetupMigration.migrate(:up)
11
11
  end
12
12
 
13
- after(:all) { ActiveRecord::Base.remove_connection }
13
+ after(:all) { ActiveRecord::Base.remove_connection } # rubocop:disable RSpec/BeforeAfterAll
14
14
 
15
15
  include_examples ".order_as_specified"
16
16
 
@@ -31,7 +31,7 @@ RSpec.describe "PostgreSQL" do
31
31
  expect(subject.length).to eq 3
32
32
  end
33
33
 
34
- context "input safety" do
34
+ describe "input safety" do
35
35
  before(:each) { TestClass.create(field: "foo") }
36
36
 
37
37
  it "sanitizes column values" do
@@ -61,8 +61,9 @@ RSpec.describe "PostgreSQL" do
61
61
  distinct_on: true,
62
62
  table => { column => ["foo"] }
63
63
  ).to_sql
64
- pattern = "DISTINCT ON (CASE WHEN #{quoted_table}.#{quoted_column}"
65
- expect(sql).to include(pattern)
64
+
65
+ pattern = /DISTINCT ON \(\s*CASE WHEN #{quoted_table}.#{quoted_column}/
66
+ expect(sql).to match(pattern)
66
67
  end
67
68
  end
68
69
  end
@@ -58,8 +58,8 @@ RSpec.shared_examples ".order_as_specified" do
58
58
  end.shuffle
59
59
  end
60
60
 
61
- it "raises an error" do
62
- expect { subject }.to raise_error(OrderAsSpecified::Error)
61
+ it "returns results in the given order" do
62
+ expect(subject.map(&:id)).to eq shuffled_object_ids
63
63
  end
64
64
  end
65
65
  end
@@ -101,7 +101,7 @@ RSpec.shared_examples ".order_as_specified" do
101
101
  ]
102
102
  end
103
103
 
104
- context "exclusive ranges" do
104
+ context "when ranges are exclusive" do
105
105
  let(:numbers) { [0, 1, 2, 3, 4, 0.9, 1.5] }
106
106
 
107
107
  let(:ranges) { [(1...2), (0...1), (2...5)] }
@@ -119,7 +119,7 @@ RSpec.shared_examples ".order_as_specified" do
119
119
  end
120
120
  end
121
121
 
122
- context "reverse ranges" do
122
+ context "when ranges are in reverse order" do
123
123
  let(:ranges) { [(5..0)] }
124
124
 
125
125
  it "raises an error" do
@@ -163,7 +163,7 @@ RSpec.shared_examples ".order_as_specified" do
163
163
  end
164
164
  end
165
165
 
166
- context "input safety" do
166
+ describe "input safety" do
167
167
  before(:each) do
168
168
  2.times { |i| TestClass.create(field: "foo#{i}") }
169
169
  end
@@ -192,16 +192,39 @@ RSpec.shared_examples ".order_as_specified" do
192
192
  quoted_column = AssociationTestClass.connection.quote_column_name(column)
193
193
 
194
194
  sql = TestClass.order_as_specified(table => { column => ["foo"] }).to_sql
195
- pattern = "ORDER BY CASE WHEN #{quoted_table}.#{quoted_column}"
195
+ pattern = "ORDER BY (CASE WHEN #{quoted_table}.#{quoted_column}"
196
196
  expect(sql).to include(pattern)
197
197
  end
198
198
  end
199
199
 
200
- context "invalid hash input" do
200
+ context "when hash input is invalid" do
201
201
  subject { TestClass.order_as_specified({}) }
202
202
 
203
203
  it "raises an error" do
204
204
  expect { subject }.to raise_error(OrderAsSpecified::Error)
205
205
  end
206
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])
228
+ end
229
+ end
207
230
  end
data/spec/spec_helper.rb CHANGED
@@ -1,15 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if ENV["TRAVIS"] == "true" && ENV["CODE_COVERAGE"] == "true"
4
- require "simplecov"
5
- require "codecov"
6
- SimpleCov.formatter = SimpleCov::Formatter::Codecov
7
- SimpleCov.start do
8
- # Omit the spec directory from being counted in code coverage calculations.
9
- add_filter "/spec/"
10
- end
11
- end
12
-
13
3
  require "active_record"
14
4
 
15
5
  require "order_as_specified"
data/spec/sqlite3_spec.rb CHANGED
@@ -5,12 +5,12 @@ require "shared/order_as_specified_examples"
5
5
  require "config/test_setup_migration"
6
6
 
7
7
  RSpec.describe "SQLite3" do
8
- before :all do
8
+ before :all do # rubocop:disable RSpec/BeforeAfterAll
9
9
  ActiveRecord::Base.establish_connection(:sqlite3_test)
10
10
  TestSetupMigration.migrate(:up)
11
11
  end
12
12
 
13
- after(:all) { ActiveRecord::Base.remove_connection }
13
+ after(:all) { ActiveRecord::Base.remove_connection } # rubocop:disable RSpec/BeforeAfterAll
14
14
 
15
15
  include_examples ".order_as_specified"
16
16
  end
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.6'
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: 2019-02-11 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
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: codecov
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: mysql2
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +100,14 @@ dependencies:
114
100
  requirements:
115
101
  - - "~>"
116
102
  - !ruby/object:Gem::Version
117
- version: 1.3.13
103
+ version: '1.4'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
- version: 1.3.13
110
+ version: '1.4'
125
111
  description: Obtain ActiveRecord results with a custom ordering with no need to store
126
112
  anything in the database.
127
113
  email:
@@ -130,10 +116,14 @@ executables: []
130
116
  extensions: []
131
117
  extra_rdoc_files: []
132
118
  files:
119
+ - ".dependabot/config.yml"
120
+ - ".github/workflows/auto-approve-dependabot.yml"
121
+ - ".github/workflows/remove-needs-qa.yml"
122
+ - ".github/workflows/tests.yml"
133
123
  - ".gitignore"
134
124
  - ".rubocop.yml"
135
- - ".travis.yml"
136
125
  - CHANGELOG.md
126
+ - CODE_OF_CONDUCT.md
137
127
  - Gemfile
138
128
  - LICENSE.txt
139
129
  - README.md
@@ -157,7 +147,7 @@ homepage: https://github.com/panorama-ed/order_as_specified
157
147
  licenses:
158
148
  - MIT
159
149
  metadata: {}
160
- post_install_message:
150
+ post_install_message:
161
151
  rdoc_options: []
162
152
  require_paths:
163
153
  - lib
@@ -172,9 +162,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
162
  - !ruby/object:Gem::Version
173
163
  version: '0'
174
164
  requirements: []
175
- rubyforge_project:
176
- rubygems_version: 2.7.6
177
- signing_key:
165
+ rubyforge_project:
166
+ rubygems_version: 2.7.6.2
167
+ signing_key:
178
168
  specification_version: 4
179
169
  summary: Add arbitrary ordering to ActiveRecord queries.
180
170
  test_files:
data/.travis.yml DELETED
@@ -1,41 +0,0 @@
1
- language: ruby
2
- rvm:
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.
10
- before_script:
11
- - psql -c 'create database order_as_specified_test;' -U postgres
12
- - mysql -e 'CREATE DATABASE order_as_specified_test;'
13
- script:
14
- - bundle exec rspec
15
- services:
16
- - mysql
17
- - postgresql
18
- env:
19
- matrix:
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
38
- notifications:
39
- email: false
40
- slack:
41
- secure: lVaScxPymqeYlTh+KlprWDK+O18BkQTyNSBTfzsLFzWF3Dy+p1rp2aeh0AhuLVYQDrlmFZ7cDMZ1ZYDyV2Y6lLtt+4ii7rATagI8R9WUVYb90C97tu1M6v5tpIjoTEOLx9hGc66heyvq1hNCKXbTqsqmrD69FYdjuXnOfrIs6J4=