Skip to content

Commit 0565942

Browse files
authored
Merge pull request #19 from freeletics/fix-ambiguous-column-issue
Fix PG::AmbiguousColumn if we do a join on 2 tables that has the same array_enum col name
2 parents 31144c6 + f5ddfbe commit 0565942

File tree

9 files changed

+139
-104
lines changed

9 files changed

+139
-104
lines changed

.github/workflows/ci-on-merge.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
ruby-version: [2.7, '3.0', 3.1]
13+
ruby-version: [3.0, 3.1, 3.3]
1414

1515
services:
1616
postgres:
@@ -40,10 +40,10 @@ jobs:
4040
psql -c 'create database "array_enum_test";'
4141
4242
- name: Checkout code
43-
uses: actions/checkout@v2
43+
uses: actions/checkout@v4.1.1
4444

4545
- name : Ruby Setup
46-
uses: ruby/setup-ruby@v1
46+
uses: ruby/setup-ruby@v1.173.0
4747
with:
4848
ruby-version: ${{ matrix.ruby-version }}
4949
bundler-cache: true

.github/workflows/ci.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
name: CI
22

3-
on: [pull_request]
3+
on:
4+
- pull_request
5+
- push
46

57
jobs:
68
test:
79
runs-on: ubuntu-latest
810
strategy:
911
matrix:
10-
ruby-version: [2.7, '3.0', 3.1]
12+
ruby-version: [3.0, 3.1, 3.3]
1113

1214
services:
1315
postgres:
@@ -37,10 +39,10 @@ jobs:
3739
psql -c 'create database "array_enum_test";'
3840
3941
- name: Checkout code
40-
uses: actions/checkout@v2
42+
uses: actions/checkout@v4.1.1
4143

4244
- name : Ruby Setup
43-
uses: ruby/setup-ruby@v1
45+
uses: ruby/setup-ruby@v1.173.0
4446
with:
4547
ruby-version: ${{ matrix.ruby-version }}
4648
bundler-cache: true

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
/pkg/
77
/spec/reports/
88
/tmp/
9+
.tool-versions
10+
.byebug_history

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
source "https://rubygems.org"
1+
source 'https://rubygems.org'
22

33
# Specify your gem's dependencies in array_enum.gemspec
44
gemspec

Gemfile.lock

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,36 @@ PATH
77
GEM
88
remote: https://rubygems.org/
99
specs:
10-
activemodel (6.1.3)
11-
activesupport (= 6.1.3)
12-
activerecord (6.1.3)
13-
activemodel (= 6.1.3)
14-
activesupport (= 6.1.3)
15-
activesupport (6.1.3)
10+
activemodel (7.1.3.2)
11+
activesupport (= 7.1.3.2)
12+
activerecord (7.1.3.2)
13+
activemodel (= 7.1.3.2)
14+
activesupport (= 7.1.3.2)
15+
timeout (>= 0.4.0)
16+
activesupport (7.1.3.2)
17+
base64
18+
bigdecimal
1619
concurrent-ruby (~> 1.0, >= 1.0.2)
20+
connection_pool (>= 2.2.5)
21+
drb
1722
i18n (>= 1.6, < 2)
1823
minitest (>= 5.1)
24+
mutex_m
1925
tzinfo (~> 2.0)
20-
zeitwerk (~> 2.3)
21-
concurrent-ruby (1.1.8)
22-
i18n (1.8.9)
26+
base64 (0.2.0)
27+
bigdecimal (3.1.7)
28+
concurrent-ruby (1.2.3)
29+
connection_pool (2.4.1)
30+
drb (2.2.1)
31+
i18n (1.14.4)
2332
concurrent-ruby (~> 1.0)
24-
minitest (5.11.3)
25-
pg (1.1.4)
26-
rake (12.3.3)
27-
tzinfo (2.0.4)
33+
minitest (5.22.3)
34+
mutex_m (0.2.0)
35+
pg (1.5.6)
36+
rake (13.2.0)
37+
timeout (0.4.1)
38+
tzinfo (2.0.6)
2839
concurrent-ruby (~> 1.0)
29-
zeitwerk (2.4.2)
3040

3141
PLATFORMS
3242
ruby
@@ -40,4 +50,4 @@ DEPENDENCIES
4050
rake (>= 10.0)
4151

4252
BUNDLED WITH
43-
2.2.3
53+
2.5.6

array_enum.gemspec

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,44 @@
1-
2-
lib = File.expand_path("../lib", __FILE__)
1+
lib = File.expand_path('lib', __dir__)
32
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4-
require "array_enum/version"
3+
require 'array_enum/version'
54

65
Gem::Specification.new do |spec|
7-
spec.name = "array_enum"
6+
spec.name = 'array_enum'
87
spec.version = ArrayEnum::VERSION
9-
spec.authors = ["Wojciech Wnętrzak"]
10-
8+
spec.authors = ['Wojciech Wnętrzak']
9+
1110

12-
spec.summary = %q{String to integer mapping for PostgreSQL array columns.}
13-
spec.description = %q{Extension for ActiveRecord that adds support for PostgreSQL array columns, mapping string values to integers.}
14-
spec.homepage = "https://github.com/freeletics/array_enum"
15-
spec.license = "MIT"
11+
spec.summary = 'String to integer mapping for PostgreSQL array columns.'
12+
spec.description = 'Extension for ActiveRecord that adds support for PostgreSQL array columns, mapping string values to integers.'
13+
spec.homepage = 'https://github.com/freeletics/array_enum'
14+
spec.license = 'MIT'
1615

1716
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
1817
# to allow pushing to a single host or delete this section to allow pushing to any host.
1918
if spec.respond_to?(:metadata)
20-
spec.metadata["homepage_uri"] = spec.homepage
21-
spec.metadata["source_code_uri"] = "https://github.com/freeletics/array_enum"
19+
spec.metadata['homepage_uri'] = spec.homepage
20+
spec.metadata['source_code_uri'] = 'https://github.com/freeletics/array_enum'
2221
else
23-
raise "RubyGems 2.0 or newer is required to protect against " \
24-
"public gem pushes."
22+
raise 'RubyGems 2.0 or newer is required to protect against ' \
23+
'public gem pushes.'
2524
end
2625

2726
# Specify which files should be added to the gem when it is released.
2827
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
29-
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
3029
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
3130
end
32-
spec.bindir = "exe"
31+
spec.bindir = 'exe'
3332
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
34-
spec.require_paths = ["lib"]
33+
spec.require_paths = ['lib']
3534

36-
spec.required_ruby_version = ">= 2.3"
35+
spec.required_ruby_version = '>= 3.0'
3736

38-
spec.add_dependency "activemodel"
37+
spec.add_dependency 'activemodel'
3938

40-
spec.add_development_dependency "activerecord"
41-
spec.add_development_dependency "pg"
42-
spec.add_development_dependency "bundler", ">= 1.17"
43-
spec.add_development_dependency "rake", ">= 10.0"
44-
spec.add_development_dependency "minitest", ">= 5.0"
39+
spec.add_development_dependency 'activerecord'
40+
spec.add_development_dependency 'bundler', '>= 1.17'
41+
spec.add_development_dependency 'minitest', '>= 5.0'
42+
spec.add_development_dependency 'pg'
43+
spec.add_development_dependency 'rake', '>= 10.0'
4544
end

lib/array_enum.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
require "array_enum/version"
2-
require "array_enum/subset_validator"
3-
require "array_enum/railtie" if defined?(Rails::Railtie)
4-
require "active_support/hash_with_indifferent_access"
5-
require "active_support/core_ext/string/inflections"
1+
require 'array_enum/version'
2+
require 'array_enum/subset_validator'
3+
require 'array_enum/railtie' if defined?(Rails::Railtie)
4+
require 'active_support/hash_with_indifferent_access'
5+
require 'active_support/core_ext/string/inflections'
66

77
module ArrayEnum
8-
MISSING_VALUE_MESSAGE = "%{value} is not a valid value for %{attr}".freeze
8+
MISSING_VALUE_MESSAGE = '%<value>s is not a valid value for %<attr>s'.freeze
99
private_constant :MISSING_VALUE_MESSAGE
1010

1111
def array_enum(definitions)
@@ -24,9 +24,9 @@ def array_enum(definitions)
2424
}.each do |method_name, comparison_operator|
2525
define_singleton_method(method_name.to_sym) do |values|
2626
db_values = Array(values).map do |value|
27-
mapping_hash[value] || raise(ArgumentError, MISSING_VALUE_MESSAGE % {value: value, attr: attr_name})
27+
mapping_hash[value] || raise(ArgumentError, format(MISSING_VALUE_MESSAGE, value: value, attr: attr_name))
2828
end
29-
where("#{attr_name} #{comparison_operator} ARRAY[:db_values]", db_values: db_values)
29+
where("#{table_name}.#{attr_name} #{comparison_operator} ARRAY[:db_values]", db_values: db_values)
3030
end
3131
end
3232

@@ -36,7 +36,7 @@ def array_enum(definitions)
3636

3737
define_method("#{attr_name}=".to_sym) do |values|
3838
self[attr_symbol] = Array(values).map do |value|
39-
mapping_hash[value] || raise(ArgumentError, MISSING_VALUE_MESSAGE % {value: value, attr: attr_name})
39+
mapping_hash[value] || raise(ArgumentError, format(MISSING_VALUE_MESSAGE, value: value, attr: attr_name))
4040
end.uniq
4141
end
4242
end

test/array_enum_test.rb

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,126 @@
1-
require "test_helper"
1+
require 'test_helper'
22

33
class ArrayEnumTest < Minitest::Test
44
def setup
55
User.delete_all
66
end
77

88
def test_assigning_enum_values
9-
user = User.new(favourite_colors: ["red", "blue"])
10-
assert_equal ["red", "blue"], user.favourite_colors
9+
user = User.new(favourite_colors: %w[red blue])
10+
assert_equal %w[red blue], user.favourite_colors
1111
end
1212

1313
def test_assigning_enum_values_as_symbols
14-
user = User.new(favourite_colors: [:red, :blue])
15-
assert_equal ["red", "blue"], user.favourite_colors
14+
user = User.new(favourite_colors: %i[red blue])
15+
assert_equal %w[red blue], user.favourite_colors
1616
end
1717

1818
def test_raising_error_on_unknown_value
1919
error = assert_raises(ArgumentError) do
20-
User.new(favourite_colors: ["black"])
20+
User.new(favourite_colors: ['black'])
2121
end
2222
assert_match(/black is not a valid value for favourite_colors/, error.message)
2323
end
2424

2525
def test_storing_values_as_integers
26-
user = User.create!(favourite_colors: ["red"])
26+
user = User.create!(favourite_colors: ['red'])
2727
user.reload
28-
assert_equal "{1}", user.read_attribute_before_type_cast("favourite_colors")
28+
assert_equal '{1}', user.read_attribute_before_type_cast('favourite_colors')
2929
end
3030

3131
# with_attr scope
3232
def test_quering_db_with_single_matching_value
33-
user = User.create!(favourite_colors: ["red"])
34-
assert_equal [user], User.with_favourite_colors("red")
33+
user = User.create!(favourite_colors: ['red'])
34+
assert_equal [user], User.with_favourite_colors('red')
3535
end
3636

3737
def test_quering_db_with_single_matching_symbol_value
38-
user = User.create!(favourite_colors: ["red"])
38+
user = User.create!(favourite_colors: ['red'])
3939
assert_equal [user], User.with_favourite_colors(:red)
4040
end
4141

4242
def test_quering_db_by_one_of_matching_value
43-
user = User.create!(favourite_colors: ["red", "blue"])
44-
assert_equal [user], User.with_favourite_colors("red")
43+
user = User.create!(favourite_colors: %w[red blue])
44+
assert_equal [user], User.with_favourite_colors('red')
4545
end
4646

4747
def test_quering_db_by_excluded_value_does_not_return_record
48-
User.create!(favourite_colors: ["red", "blue"])
49-
assert_equal [], User.with_favourite_colors("green")
48+
User.create!(favourite_colors: %w[red blue])
49+
assert_equal [], User.with_favourite_colors('green')
5050
end
5151

5252
def test_quering_db_by_many_values_does_not_return_record_on_excluded_value
53-
User.create!(favourite_colors: ["red", "blue"])
54-
assert_equal [], User.with_favourite_colors(["red", "green"])
53+
User.create!(favourite_colors: %w[red blue])
54+
assert_equal [], User.with_favourite_colors(%w[red green])
5555
end
5656

5757
def test_quering_db_only_with_single_matching_value
58-
user = User.create!(favourite_colors: ["red"])
59-
assert_equal [user], User.only_with_favourite_colors(["red"])
58+
user = User.create!(favourite_colors: ['red'])
59+
assert_equal [user], User.only_with_favourite_colors(['red'])
6060
end
6161

6262
def test_quering_db_only_with_single_matching_value_from_many_values_does_not_return_record
63-
User.create!(favourite_colors: ["red", "blue"])
64-
assert_equal [], User.only_with_favourite_colors(["red"])
63+
User.create!(favourite_colors: %w[red blue])
64+
assert_equal [], User.only_with_favourite_colors(['red'])
6565
end
6666

6767
def test_quering_db_by_non_existing_value_raises_error
68-
User.create!(favourite_colors: ["red", "blue"])
68+
User.create!(favourite_colors: %w[red blue])
6969
error = assert_raises(ArgumentError) do
70-
User.with_favourite_colors("black")
70+
User.with_favourite_colors('black')
7171
end
7272
assert_match(/black is not a valid value for favourite_colors/, error.message)
7373
end
7474

7575
# with_any_of_attr scope
7676
def test_with_any_of_attr_matching_value
77-
user = User.create!(favourite_colors: ["red"])
78-
assert_equal [user], User.with_any_of_favourite_colors("red")
77+
user = User.create!(favourite_colors: ['red'])
78+
assert_equal [user], User.with_any_of_favourite_colors('red')
7979
end
8080

8181
def test_with_any_of_attr_matching_symbol_value
82-
user = User.create!(favourite_colors: ["red"])
82+
user = User.create!(favourite_colors: ['red'])
8383
assert_equal [user], User.with_any_of_favourite_colors(:red)
8484
end
8585

8686
def test_with_any_of_attr_one_of_matching_value
87-
user = User.create!(favourite_colors: ["red", "blue"])
88-
assert_equal [user], User.with_any_of_favourite_colors("red")
87+
user = User.create!(favourite_colors: %w[red blue])
88+
assert_equal [user], User.with_any_of_favourite_colors('red')
8989
end
9090

9191
def test_with_any_of_attr_excluded_value_does_not_return_record
92-
User.create!(favourite_colors: ["red", "blue"])
93-
assert_equal [], User.with_any_of_favourite_colors("green")
92+
User.create!(favourite_colors: %w[red blue])
93+
assert_equal [], User.with_any_of_favourite_colors('green')
9494
end
9595

9696
def test_with_any_of_attr_many_value_when_single_match
97-
user = User.create!(favourite_colors: ["red", "blue"])
98-
assert_equal [user], User.with_any_of_favourite_colors(["red", "green"])
97+
user = User.create!(favourite_colors: %w[red blue])
98+
assert_equal [user], User.with_any_of_favourite_colors(%w[red green])
9999
end
100100

101101
def test_with_any_of_attr_by_non_existing_value_raises_error
102-
User.create!(favourite_colors: ["red", "blue"])
102+
User.create!(favourite_colors: %w[red blue])
103103
error = assert_raises(ArgumentError) do
104-
User.with_any_of_favourite_colors("black")
104+
User.with_any_of_favourite_colors('black')
105105
end
106106
assert_match(/black is not a valid value for favourite_colors/, error.message)
107107
end
108108

109-
110109
def test_lists_values
111-
assert_equal User.favourite_colors, {"red"=>1, "blue"=>2, "green"=>3}
110+
assert_equal User.favourite_colors, { 'red' => 1, 'blue' => 2, 'green' => 3 }
112111
end
113112

114113
def test_values_can_be_accessed_indifferently
115114
assert_equal User.favourite_colors[:red], 1
116115
assert_equal User.favourite_colors[:blue], 2
117116
assert_equal User.favourite_colors[:green], 3
118-
assert_equal User.favourite_colors["red"], 1
117+
assert_equal User.favourite_colors['red'], 1
118+
end
119+
120+
def test_user_with_join_table_which_has_same_array_enum_col
121+
user = User.create!(favourite_colors: %w[red blue],
122+
profiles: [Profile.new(slug: 'profile_slug')])
123+
124+
assert_equal [user], User.joins(:profiles).with_any_of_favourite_colors(%w[red])
119125
end
120126
end

0 commit comments

Comments
 (0)