order_as_specified 1.2 → 1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.dependabot/config.yml +46 -0
- data/.github/workflows/auto-approve-dependabot.yml +26 -0
- data/.github/workflows/remove-needs-qa.yml +35 -0
- data/.github/workflows/tests.yml +61 -0
- data/.rubocop.yml +2 -260
- data/CHANGELOG.md +34 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -2
- data/README.md +47 -9
- data/RELEASING.md +14 -0
- data/lib/order_as_specified.rb +32 -15
- data/lib/order_as_specified/error.rb +2 -0
- data/lib/order_as_specified/version.rb +3 -1
- data/order_as_specified.gemspec +14 -11
- data/spec/config/database.yml +10 -0
- data/spec/config/test_setup_migration.rb +8 -2
- data/spec/mysql_spec.rb +16 -0
- data/spec/order_as_specified_spec.rb +2 -0
- data/spec/postgresql_spec.rb +26 -14
- data/spec/shared/order_as_specified_examples.rb +107 -7
- data/spec/spec_helper.rb +1 -2
- data/spec/sqlite3_spec.rb +4 -2
- data/spec/support/application_record.rb +5 -0
- data/spec/support/association_test_class.rb +3 -1
- data/spec/support/test_class.rb +3 -1
- metadata +50 -71
- data/.overcommit.yml +0 -8
- data/.travis.yml +0 -20
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
# Unreleased (`master`)
|
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
|
+
|
8
|
+
# 1.6
|
9
|
+
|
10
|
+
We are dropping official support for Ruby 2.3 and below, though they may
|
11
|
+
continue to work.
|
12
|
+
|
13
|
+
This release adds support for ordering by `Range`s. Big thanks to
|
14
|
+
[Karl-Aksel Puulmann](https://github.com/macobo) for adding this functionality!
|
15
|
+
|
16
|
+
# 1.5
|
17
|
+
|
18
|
+
This release improves performance by switching to use `CASE` statements. Huge
|
19
|
+
thanks to [Yen-Nan (Maso) Lin](https://github.com/masolin) for this improvement!
|
20
|
+
|
21
|
+
# 1.4
|
22
|
+
|
23
|
+
This release removes deprecation warnings for ActiveRecord 5.2 users, and drops
|
24
|
+
support for ActiveRecord 4.x. Many thanks to
|
25
|
+
[George Protacio-Karaszi](https://github.com/GeorgeKaraszi) for pointing out
|
26
|
+
this issue!
|
27
|
+
|
28
|
+
# 1.3
|
29
|
+
|
30
|
+
This release adds support for ActiveRecord 5.1. Many thanks to
|
31
|
+
[cohki0305](https://github.com/cohki0305) for identifying the issue,
|
32
|
+
[Billy Ferguson](https://github.com/fergyfresh) for investigating it, and
|
33
|
+
especially to [Alex Heeton](https://github.com/heeton) for fixing it.
|
34
|
+
|
1
35
|
# 1.2
|
2
36
|
|
3
37
|
This release contains an important change: `order_as_specified` is no longer
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -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
@@ -1,6 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
3
|
-
|
5
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
6
|
+
|
7
|
+
# Specify your gem's dependencies in unique_attributes.gemspec
|
4
8
|
gemspec
|
5
9
|
|
6
|
-
|
10
|
+
group :development do
|
11
|
+
gem "panolint", github: "panorama-ed/panolint", branch: "main"
|
12
|
+
end
|
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
[![Code
|
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
|
|
@@ -26,8 +29,8 @@ TestObject.order_as_specified(language: ["es", "en", "fr"])
|
|
26
29
|
|
27
30
|
Other gems like `ranked-model`, `acts_as_sortable`, etc. assume you want the
|
28
31
|
same ordering each time, and store data to keep track of this in the database.
|
29
|
-
They're great at what they do, but if
|
30
|
-
don't always want an ordering, this gem is your friend.
|
32
|
+
They're great at what they do, but if you want to change the ordering, or if
|
33
|
+
you don't always want an ordering, this gem is your friend.
|
31
34
|
|
32
35
|
## Installation
|
33
36
|
|
@@ -139,6 +142,20 @@ TestObject.order_as_specified(language: ["fr", "es"])
|
|
139
142
|
]>
|
140
143
|
```
|
141
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
|
+
|
142
159
|
In databases that support it (such as PostgreSQL), you can also use an option to
|
143
160
|
add a `DISTINCT ON` to your query when you would otherwise have duplicates:
|
144
161
|
|
@@ -151,10 +168,32 @@ TestObject.order_as_specified(distinct_on: true, language: ["fr", "en"])
|
|
151
168
|
]>
|
152
169
|
```
|
153
170
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
+
```
|
185
|
+
|
186
|
+
## Limitations
|
187
|
+
|
188
|
+
Databases may have limitations on the underlying number of fields you can have
|
189
|
+
in an `ORDER BY` clause. For example, in PostgreSQL if you pass in more than
|
190
|
+
1664 list elements you'll [receive this error](https://github.com/panorama-ed/order_as_specified/issues/34):
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
PG::ProgramLimitExceeded: ERROR: target lists can have at most 1664 entries
|
194
|
+
```
|
195
|
+
|
196
|
+
That's a database limitation that this gem cannot avoid, unfortunately.
|
158
197
|
|
159
198
|
## Documentation
|
160
199
|
|
@@ -169,8 +208,7 @@ We have documentation on [RubyDoc](http://www.rubydoc.info/github/panorama-ed/or
|
|
169
208
|
5. Create a new Pull Request
|
170
209
|
|
171
210
|
**Make sure your changes have appropriate tests (`bundle exec rspec`)
|
172
|
-
and conform to the Rubocop style specified.**
|
173
|
-
[overcommit](https://github.com/causes/overcommit) to enforce good code.
|
211
|
+
and conform to the Rubocop style specified.**
|
174
212
|
|
175
213
|
## License
|
176
214
|
|
data/RELEASING.md
ADDED
@@ -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. Make a PR.
|
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
|
+
1. Push to rubygems: `gem build order_as_specified.gemspec && gem push *.gem && rm *.gem`
|
14
|
+
1. Celebrate!
|
data/lib/order_as_specified.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "order_as_specified/version"
|
2
4
|
require "order_as_specified/error"
|
3
5
|
|
@@ -5,31 +7,44 @@ require "order_as_specified/error"
|
|
5
7
|
# the database in an arbitrary order, without having to store anything extra
|
6
8
|
# in the database. Simply `extend` it into your class and then you can use the
|
7
9
|
# `order_as_specified` class method.
|
8
|
-
|
9
10
|
module OrderAsSpecified
|
10
11
|
# @param hash [Hash] the ActiveRecord arguments hash
|
11
12
|
# @return [ActiveRecord::Relation] the objects, ordered as specified
|
12
13
|
def order_as_specified(hash)
|
13
14
|
distinct_on = hash.delete(:distinct_on)
|
15
|
+
case_insensitive = hash.delete(:case_insensitive)
|
16
|
+
|
14
17
|
params = extract_params(hash)
|
18
|
+
return all if params[:values].empty?
|
15
19
|
|
16
|
-
table =
|
17
|
-
|
20
|
+
table = Arel::Table.new(params[:table])
|
21
|
+
node = Arel::Nodes::Case.new
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
24
30
|
|
25
|
-
|
26
|
-
|
31
|
+
attribute.between(value)
|
32
|
+
elsif case_insensitive
|
33
|
+
attribute.matches(value)
|
34
|
+
else
|
35
|
+
attribute.eq(value)
|
36
|
+
end
|
37
|
+
|
38
|
+
node.when(condition).then(index)
|
27
39
|
end
|
28
40
|
|
29
|
-
|
41
|
+
node.else(node.conditions.size)
|
42
|
+
scope = order(Arel::Nodes::Ascending.new(table.grouping(node)))
|
30
43
|
|
31
44
|
if distinct_on
|
32
|
-
|
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}.*"))
|
33
48
|
end
|
34
49
|
|
35
50
|
scope
|
@@ -43,13 +58,15 @@ module OrderAsSpecified
|
|
43
58
|
# @param table [String/Symbol] the name of the table, default: the class table
|
44
59
|
# @param hash [Hash] the ActiveRecord-style arguments, such as:
|
45
60
|
# { other_objects: { id: [1, 5, 3] } }
|
46
|
-
def extract_params(table = table_name
|
47
|
-
|
61
|
+
def extract_params(hash, table = table_name)
|
62
|
+
unless hash.size == 1
|
63
|
+
raise OrderAsSpecified::Error, "Could not parse params"
|
64
|
+
end
|
48
65
|
|
49
66
|
key, val = hash.first
|
50
67
|
|
51
68
|
if val.is_a? Hash
|
52
|
-
extract_params(key,
|
69
|
+
extract_params(hash[key], key)
|
53
70
|
else
|
54
71
|
{
|
55
72
|
table: table,
|
data/order_as_specified.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require "order_as_specified/version"
|
5
6
|
|
@@ -19,14 +20,16 @@ Gem::Specification.new do |spec|
|
|
19
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
21
|
spec.require_paths = ["lib"]
|
21
22
|
|
22
|
-
spec.add_dependency "activerecord", ">=
|
23
|
+
spec.add_dependency "activerecord", ">= 5.0.0"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler"
|
26
|
+
spec.add_development_dependency "mysql2"
|
27
|
+
spec.add_development_dependency "pg"
|
28
|
+
spec.add_development_dependency "rspec"
|
29
|
+
spec.add_development_dependency "rspec-rails"
|
23
30
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
spec.add_development_dependency "
|
28
|
-
spec.add_development_dependency "rspec", "~> 3.2"
|
29
|
-
spec.add_development_dependency "rspec-rails", "~> 3.2"
|
30
|
-
spec.add_development_dependency "rubocop", "~> 0.29"
|
31
|
-
spec.add_development_dependency "sqlite3", ">= 1.3"
|
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
|
data/spec/config/database.yml
CHANGED
@@ -5,5 +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
|
12
|
+
|
13
|
+
mysql_test:
|
14
|
+
adapter: mysql2
|
15
|
+
host: 127.0.0.1
|
16
|
+
encoding: utf8
|
17
|
+
database: order_as_specified_test
|
18
|
+
username: mysql
|
19
|
+
password: mysql
|
@@ -1,9 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
VersionedMigration = ActiveRecord::Migration[ActiveRecord::Migration.current_version] # rubocop:disable Layout/LineLength
|
4
|
+
|
5
|
+
class TestSetupMigration < VersionedMigration
|
2
6
|
def up
|
3
|
-
|
7
|
+
db_connection = ActiveRecord::Base.connection
|
8
|
+
return if db_connection.try(:data_source_exists?, :test_classes)
|
4
9
|
|
5
10
|
create_table :test_classes do |t|
|
6
11
|
t.string :field
|
12
|
+
t.float :number_field
|
7
13
|
end
|
8
14
|
|
9
15
|
create_table :association_test_classes do |t|
|
data/spec/mysql_spec.rb
ADDED
@@ -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 # rubocop:disable RSpec/BeforeAfterAll
|
9
|
+
ActiveRecord::Base.establish_connection(:mysql_test)
|
10
|
+
TestSetupMigration.migrate(:up)
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:all) { ActiveRecord::Base.remove_connection } # rubocop:disable RSpec/BeforeAfterAll
|
14
|
+
|
15
|
+
include_examples ".order_as_specified"
|
16
|
+
end
|
data/spec/postgresql_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 "PostgreSQL" do
|
6
|
-
before :all do
|
8
|
+
before :all do # rubocop:disable RSpec/BeforeAfterAll
|
7
9
|
ActiveRecord::Base.establish_connection(:postgresql_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
|
|
@@ -21,25 +23,28 @@ RSpec.describe "PostgreSQL" do
|
|
21
23
|
end
|
22
24
|
|
23
25
|
let(:shuffled_objects) do
|
24
|
-
fields = 3
|
25
|
-
5
|
26
|
+
fields = Array.new(3) { |i| "Field #{i}" } * 2
|
27
|
+
Array.new(5) { |i| TestClass.create(field: fields[i]) }.shuffle
|
26
28
|
end
|
27
29
|
|
28
30
|
it "returns distinct objects" do
|
29
31
|
expect(subject.length).to eq 3
|
30
32
|
end
|
31
33
|
|
32
|
-
|
34
|
+
describe "input safety" do
|
33
35
|
before(:each) { TestClass.create(field: "foo") }
|
34
36
|
|
35
37
|
it "sanitizes column values" do
|
36
|
-
# Attempt to inject code to add a 'hi' field to each record. If the SQL
|
37
|
-
# are properly sanitized, the code will be ignored and the
|
38
|
-
# instances will not respond to #hi. If not, the code
|
39
|
-
# each of the returned model instances will have a #hi
|
40
|
-
# new field.
|
38
|
+
# Attempt to inject code to add a 'hi' field to each record. If the SQL
|
39
|
+
# inputs are properly sanitized, the code will be ignored and the
|
40
|
+
# returned model instances will not respond to #hi. If not, the code
|
41
|
+
# will execute and each of the returned model instances will have a #hi
|
42
|
+
# method to access the new field.
|
41
43
|
bad_value = "foo') field, 'hi'::varchar AS hi FROM test_classes --"
|
42
|
-
record = TestClass.order_as_specified(
|
44
|
+
record = TestClass.order_as_specified(
|
45
|
+
distinct_on: true,
|
46
|
+
field: [bad_value]
|
47
|
+
).to_a.first
|
43
48
|
expect(record).to_not respond_to(:hi)
|
44
49
|
end
|
45
50
|
|
@@ -48,10 +53,17 @@ RSpec.describe "PostgreSQL" do
|
|
48
53
|
quoted_table = AssociationTestClass.connection.quote_table_name(table)
|
49
54
|
|
50
55
|
column = "id"
|
51
|
-
quoted_column = AssociationTestClass.
|
56
|
+
quoted_column = AssociationTestClass.
|
57
|
+
connection.
|
58
|
+
quote_column_name(column)
|
59
|
+
|
60
|
+
sql = TestClass.order_as_specified(
|
61
|
+
distinct_on: true,
|
62
|
+
table => { column => ["foo"] }
|
63
|
+
).to_sql
|
52
64
|
|
53
|
-
|
54
|
-
expect(sql).to
|
65
|
+
pattern = /DISTINCT ON \(\s*CASE WHEN #{quoted_table}.#{quoted_column}/
|
66
|
+
expect(sql).to match(pattern)
|
55
67
|
end
|
56
68
|
end
|
57
69
|
end
|