active_record_union 1.3.0 → 1.4.0
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 +5 -5
- data/.github/workflows/testing.yml +70 -0
- data/Gemfile +4 -0
- data/README.md +8 -3
- data/Rakefile +4 -4
- data/active_record_union.gemspec +2 -5
- data/bin/create-db-users +44 -0
- data/lib/active_record_union/active_record/relation/union.rb +4 -37
- data/lib/active_record_union/version.rb +1 -1
- data/rails_6.0.gemfile +16 -0
- data/rails_6.1.gemfile +16 -0
- data/rails_7.0.gemfile +17 -0
- data/rails_7.1.gemfile +17 -0
- data/rails_7.2.gemfile +17 -0
- data/rails_8.0.gemfile +17 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/databases.rb +28 -5
- data/spec/union_spec.rb +38 -22
- metadata +22 -60
- data/.travis.yml +0 -11
- data/rails_4_2.gemfile +0 -11
- data/rails_5_0.gemfile +0 -11
- data/rails_5_1.gemfile +0 -11
- data/rails_5_2.gemfile +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b321a0fac09cf1cc331b5526f907b8dd78844796ed473093396dc08297997415
|
4
|
+
data.tar.gz: 020d7aca83f28ecfbf9455c48049f70c7fa0389ec72904c743fd724fd314ad05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35cb47fc2d57a16a74dbad2995cd90b87eecdea1a5aca340d8543cb504b73cd2a9cbbdb0e0c6cc4b71b416fcc04f3aa884f588067c316a0cc03dd60e9b5b376d
|
7
|
+
data.tar.gz: d0dff7b05b27f31b82d00ffe2f8cb5537b5c91a345ec31b02015cb31d020ace156277f8a9f6a8bac3c326f3890f5202213c909ec94435aac46a8be7a169b0ba9
|
@@ -0,0 +1,70 @@
|
|
1
|
+
name: RSpec Test Matrix
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
pull_request:
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
test:
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
|
10
|
+
services:
|
11
|
+
postgresql:
|
12
|
+
image: postgres
|
13
|
+
ports:
|
14
|
+
- 5432:5432
|
15
|
+
options: >-
|
16
|
+
--health-cmd pg_isready
|
17
|
+
--health-interval 10s
|
18
|
+
--health-timeout 5s
|
19
|
+
--health-retries 5
|
20
|
+
env:
|
21
|
+
POSTGRES_DB: active_record_union
|
22
|
+
POSTGRES_USER: active_record_union
|
23
|
+
POSTGRES_PASSWORD: active_record_union
|
24
|
+
|
25
|
+
mysql2:
|
26
|
+
image: mysql:8.0
|
27
|
+
env:
|
28
|
+
MYSQL_DATABASE: active_record_union
|
29
|
+
MYSQL_ROOT_PASSWORD: active_record_union
|
30
|
+
options: >-
|
31
|
+
--health-cmd "mysqladmin ping"
|
32
|
+
--health-interval 10s
|
33
|
+
--health-timeout 5s
|
34
|
+
ports:
|
35
|
+
- "3306:3306"
|
36
|
+
|
37
|
+
strategy:
|
38
|
+
fail-fast: false
|
39
|
+
matrix:
|
40
|
+
# just define specific versions for each rails version
|
41
|
+
include:
|
42
|
+
- ruby: 2.6
|
43
|
+
rails: "6.0"
|
44
|
+
- ruby: "3.0"
|
45
|
+
rails: 6.1
|
46
|
+
- ruby: 3.1
|
47
|
+
rails: "7.0"
|
48
|
+
- ruby: 3.2
|
49
|
+
rails: 7.1
|
50
|
+
- ruby: 3.2
|
51
|
+
rails: 7.2
|
52
|
+
- ruby: 3.3
|
53
|
+
rails: "8.0"
|
54
|
+
|
55
|
+
env:
|
56
|
+
BUNDLE_GEMFILE: "rails_${{ matrix.rails }}.gemfile"
|
57
|
+
DB_HOST: 127.0.0.1
|
58
|
+
MYSQL_ROOT_HOST: "%"
|
59
|
+
MYSQL_DB: active_record_union
|
60
|
+
MYSQL_USER: root
|
61
|
+
MYSQL_PASSWORD: active_record_union
|
62
|
+
steps:
|
63
|
+
- uses: actions/checkout@v4
|
64
|
+
|
65
|
+
- uses: ruby/setup-ruby@v1
|
66
|
+
with:
|
67
|
+
ruby-version: ${{ matrix.ruby }}
|
68
|
+
bundler-cache: true # install gems and cache
|
69
|
+
|
70
|
+
- run: bundle exec rspec --force-color --format d
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -17,7 +17,9 @@ user_1.posts.union(user_2.posts).union(Post.published)
|
|
17
17
|
user_1.posts.union_all(user_2.posts)
|
18
18
|
```
|
19
19
|
|
20
|
-
ActiveRecordUnion is tested against Rails
|
20
|
+
ActiveRecordUnion is tested against Rails 6.0, 6.1, 7.0, 7.1, 7.2 and 8.0.
|
21
|
+
|
22
|
+
If you are using Postgres, you might alternatively check out [ActiveRecordExtended](https://github.com/georgekaraszi/ActiveRecordExtended) which includes support for unions as well as other goodies.
|
21
23
|
|
22
24
|
## Installation
|
23
25
|
|
@@ -186,6 +188,9 @@ This is a gem not a Rails pull request because the standard of code quality for
|
|
186
188
|
|
187
189
|
## Changelog
|
188
190
|
|
191
|
+
**1.4.0** - October 1, 2025
|
192
|
+
- Ready for Rails 8.0! Support for Rails < 6 dropped. Updates provided by [@timdiggins](https://github.com/frederikspang) and [@frederikspang](https://github.com/frederikspang).
|
193
|
+
|
189
194
|
**1.3.0** - January 14, 2018
|
190
195
|
- Ready for Rails 5.2! Updates provided by [@glebm](https://github.com/glebm).
|
191
196
|
|
@@ -214,9 +219,9 @@ This public domain dedication follows the the CC0 1.0 at https://creativecommons
|
|
214
219
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
215
220
|
3. Run the tests:
|
216
221
|
1. Install MySQL and PostgreSQL.
|
217
|
-
2. You need to be able to connect to a local MySQL and Postgres database as the default user, so the specs can create a `test_active_record_union` database.
|
222
|
+
2. You need to be able to connect to a local MySQL and Postgres database as the default user, so the specs can create a `test_active_record_union` database. To set up the users this test expects, execute `bin/create-db-users` (or set the environment variables referenced in `spec/support/databases.rb`).
|
218
223
|
3. Run `rake` to test with all supported Rails versions. All needed dependencies will be installed via Bundler (`gem install bundler` if you happen not to have Bundler yet).
|
219
|
-
4. Run `rake
|
224
|
+
4. Run `rake test_rails_8_0` or `rake test_rails_7_2` etc. to test a specific Rails version.
|
220
225
|
4. There is also a `bin/console` command to load up a REPL for playing around
|
221
226
|
5. Commit your changes (`git commit -am 'Add some feature'`)
|
222
227
|
6. Push to the branch (`git push origin my-new-feature`)
|
data/Rakefile
CHANGED
@@ -51,11 +51,11 @@ end
|
|
51
51
|
|
52
52
|
|
53
53
|
TestTasks.gemfiles.each do |gemfile|
|
54
|
-
|
54
|
+
rails_version = gemfile[/rails_(.+)\.gemfile/, 1]
|
55
55
|
|
56
|
-
desc "Test Rails #{
|
57
|
-
task :"test_rails_#{
|
56
|
+
desc "Test Rails #{rails_version}"
|
57
|
+
task :"test_rails_#{rails_version.gsub(".", "_")}" do
|
58
58
|
env = { 'BUNDLE_GEMFILE' => gemfile }
|
59
59
|
TestTasks.run_one(env)
|
60
60
|
end
|
61
|
-
end
|
61
|
+
end
|
data/active_record_union.gemspec
CHANGED
@@ -18,13 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.files.grep(%r{^bin/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "activerecord", ">=
|
21
|
+
spec.add_dependency "activerecord", ">= 6.0"
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler"
|
23
|
+
spec.add_development_dependency "bundler"
|
24
24
|
spec.add_development_dependency "rake"
|
25
25
|
spec.add_development_dependency "rspec", "~> 3.0"
|
26
26
|
spec.add_development_dependency "pry"
|
27
|
-
spec.add_development_dependency "sqlite3"
|
28
|
-
spec.add_development_dependency "pg"
|
29
|
-
spec.add_development_dependency "mysql2"
|
30
27
|
end
|
data/bin/create-db-users
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
GREEN='\033[0;32m'
|
4
|
+
RESET_COLOR='\033[0m'
|
5
|
+
|
6
|
+
if [ -n "$1" ]; then cat <<'HELP'; exit; fi
|
7
|
+
Usage: bin/create-db-users
|
8
|
+
Create the active_record_union database users for all the supported databases.
|
9
|
+
If the `DB` environment variable is set, do the above only for that database.
|
10
|
+
HELP
|
11
|
+
|
12
|
+
USER='active_record_union'
|
13
|
+
PASS='active_record_union'
|
14
|
+
|
15
|
+
set -e
|
16
|
+
log() { if [ -t 1 ]; then echo -e >&2 "${GREEN}create-db-users: $@${RESET_COLOR}"; else echo >&2 "$@"; fi }
|
17
|
+
|
18
|
+
create_mysql_user() {
|
19
|
+
if mysql -s -u"$USER" -p"$PASS" -e '' 2>/dev/null; then return; fi
|
20
|
+
log "Creating MySQL '$USER' user. MySQL root password required."
|
21
|
+
mysql --verbose -uroot -p <<SQL
|
22
|
+
CREATE USER '$USER'@'localhost' IDENTIFIED BY '$PASS';
|
23
|
+
GRANT ALL PRIVILEGES ON \`test_active_record_union\`.* TO '$USER'@'localhost';
|
24
|
+
SQL
|
25
|
+
}
|
26
|
+
|
27
|
+
create_postgresql_user() {
|
28
|
+
if PGPASSWORD="$PASS" psql -h 127.0.0.1 postgres -U $USER -c ''; then return; fi
|
29
|
+
log "Creating Postgres '$USER' user."
|
30
|
+
local cmd='psql postgres'
|
31
|
+
if ! $cmd -c '' 2>/dev/null; then
|
32
|
+
log "sudo required:"
|
33
|
+
cmd="sudo -u ${PG_DAEMON_USER:-postgres} psql postgres"
|
34
|
+
fi
|
35
|
+
# need to also create database first time
|
36
|
+
$cmd --echo-all <<SQL
|
37
|
+
CREATE ROLE $USER LOGIN PASSWORD '$PASS';
|
38
|
+
ALTER ROLE $USER CREATEDB;
|
39
|
+
CREATE DATABASE active_record_union;
|
40
|
+
SQL
|
41
|
+
}
|
42
|
+
|
43
|
+
[ -z "$DB" -o "$DB" = 'mysql2' ] && create_mysql_user
|
44
|
+
[ -z "$DB" -o "$DB" = 'postgresql' ] && create_postgresql_user
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
other = if args.empty? && relation_or_where_arg.is_a?(Relation)
|
22
22
|
relation_or_where_arg
|
23
23
|
else
|
24
|
-
|
24
|
+
self.klass.where(relation_or_where_arg, *args)
|
25
25
|
end
|
26
26
|
|
27
27
|
verify_relations_for_set_operation!(operation, self, other)
|
@@ -37,45 +37,12 @@ module ActiveRecord
|
|
37
37
|
end
|
38
38
|
|
39
39
|
set = SET_OPERATION_TO_AREL_CLASS[operation].new(left, right)
|
40
|
-
from = Arel::Nodes::TableAlias.new(set,
|
40
|
+
from = Arel::Nodes::TableAlias.new(set, self.klass.arel_table.name)
|
41
41
|
build_union_relation(from, other)
|
42
42
|
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
def build_union_relation(arel_table_alias, _other)
|
47
|
-
@klass.unscoped.from(arel_table_alias)
|
48
|
-
end
|
49
|
-
elsif ActiveRecord::VERSION::MAJOR >= 5
|
50
|
-
# In Rails >= 5.0, < 5.2, binds are maintained only in ActiveRecord
|
51
|
-
# relations and clauses.
|
52
|
-
def build_union_relation(arel_table_alias, other)
|
53
|
-
relation = @klass.unscoped.spawn
|
54
|
-
relation.from_clause =
|
55
|
-
UnionFromClause.new(arel_table_alias, nil,
|
56
|
-
self.bound_attributes + other.bound_attributes)
|
57
|
-
relation
|
58
|
-
end
|
59
|
-
|
60
|
-
class UnionFromClause < ActiveRecord::Relation::FromClause
|
61
|
-
def initialize(value, name, bound_attributes)
|
62
|
-
super(value, name)
|
63
|
-
@bound_attributes = bound_attributes
|
64
|
-
end
|
65
|
-
|
66
|
-
def binds
|
67
|
-
@bound_attributes
|
68
|
-
end
|
69
|
-
end
|
70
|
-
else
|
71
|
-
# In Rails 4.x, binds are maintained in both ActiveRecord relations and
|
72
|
-
# clauses and also in their Arel ASTs.
|
73
|
-
def build_union_relation(arel_table_alias, other)
|
74
|
-
relation = @klass.unscoped.from(arel_table_alias)
|
75
|
-
relation.bind_values = self.arel.bind_values + self.bind_values +
|
76
|
-
other.arel.bind_values + other.bind_values
|
77
|
-
relation
|
78
|
-
end
|
44
|
+
def build_union_relation(arel_table_alias, _other)
|
45
|
+
self.klass.unscoped.from(arel_table_alias)
|
79
46
|
end
|
80
47
|
|
81
48
|
def verify_relations_for_set_operation!(operation, *relations)
|
data/rails_6.0.gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in active_record_union.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'rails', '~> 6.0.0'
|
7
|
+
|
8
|
+
# https://github.com/rails/rails/blob/v6.0.6.1/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
|
9
|
+
gem "pg", ">= 0.18", "< 2.0"
|
10
|
+
|
11
|
+
# https://github.com/rails/rails/blob/v6.0.2/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.6.1/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
|
15
|
+
gem "mysql2", ">= 0.4.4"
|
16
|
+
|
data/rails_6.1.gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in active_record_union.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'rails', '~> 6.1.0'
|
7
|
+
|
8
|
+
# https://github.com/rails/rails/blob/v6.1.7.10/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
|
9
|
+
gem "pg", "~> 1.1"
|
10
|
+
|
11
|
+
# https://github.com/rails/rails/blob/v6.1.2/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13
|
12
|
+
gem "sqlite3", "~> 1.4"
|
13
|
+
|
14
|
+
# https://github.com/rails/rails/blob/v6.1.7.10/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
|
15
|
+
gem "mysql2", "~> 0.5"
|
16
|
+
|
data/rails_7.0.gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in active_record_union.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'rails', '~> 7.0.0'
|
9
|
+
|
10
|
+
# https://github.com/rails/rails/blob/v7.0.2/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13
|
11
|
+
gem 'sqlite3', '~> 1.4'
|
12
|
+
|
13
|
+
# https://github.com/rails/rails/blob/v7.0.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4
|
14
|
+
gem 'pg', '~> 1.1'
|
15
|
+
|
16
|
+
# https://github.com/rails/rails/blob/v7.0.2/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6
|
17
|
+
gem 'mysql2', '~> 0.5'
|
data/rails_7.1.gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in active_record_union.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'rails', '~> 7.1.0'
|
9
|
+
|
10
|
+
# https://github.com/rails/rails/blob/v7.1.2/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13
|
11
|
+
gem 'sqlite3', '~> 1.4'
|
12
|
+
|
13
|
+
# https://github.com/rails/rails/blob/v7.1.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4
|
14
|
+
gem 'pg', '~> 1.1'
|
15
|
+
|
16
|
+
# https://github.com/rails/rails/blob/v7.1.2/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6
|
17
|
+
gem 'mysql2', '~> 0.5'
|
data/rails_7.2.gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in active_record_union.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'rails', '~> 7.2.0'
|
9
|
+
|
10
|
+
# https://github.com/rails/rails/blob/v7.2.0/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13
|
11
|
+
gem 'sqlite3', '>= 1.4'
|
12
|
+
|
13
|
+
# https://github.com/rails/rails/blob/v7.2.0/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4
|
14
|
+
gem 'pg', '~> 1.1'
|
15
|
+
|
16
|
+
# https://github.com/rails/rails/blob/v7.2.0/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6
|
17
|
+
gem 'mysql2', '~> 0.5'
|
data/rails_8.0.gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in active_record_union.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'rails', '~> 8.0.0'
|
9
|
+
|
10
|
+
# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13
|
11
|
+
gem 'sqlite3', '>= 2.1'
|
12
|
+
|
13
|
+
# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4
|
14
|
+
gem 'pg', '~> 1.1'
|
15
|
+
|
16
|
+
# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6
|
17
|
+
gem 'mysql2', '~> 0.5'
|
data/spec/spec_helper.rb
CHANGED
@@ -9,6 +9,7 @@ Databases.connect_to_sqlite
|
|
9
9
|
|
10
10
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
11
11
|
RSpec.configure do |config|
|
12
|
+
config.backtrace_inclusion_patterns << %r{gems/([0-9.])+/gems/(?!rspec|capybara)} if ENV['BACKTRACE']
|
12
13
|
# Run specs in random order to surface order dependencies. If you find an
|
13
14
|
# order dependency and want to debug it, you can fix the order by providing
|
14
15
|
# the seed, which is printed after each run.
|
data/spec/support/databases.rb
CHANGED
@@ -11,24 +11,47 @@ module Databases
|
|
11
11
|
|
12
12
|
def connect_to_postgres
|
13
13
|
ActiveRecord::Base.establish_connection(
|
14
|
-
adapter: "postgresql"
|
14
|
+
adapter: "postgresql",
|
15
|
+
host: ENV.fetch('DB_HOST', 'localhost'),
|
16
|
+
username: ENV.fetch("POSTGRES_USER", 'active_record_union'),
|
17
|
+
password: ENV.fetch("POSTGRES_PASSWORD", 'active_record_union')
|
15
18
|
)
|
16
|
-
|
19
|
+
try_to_drop_database
|
20
|
+
ActiveRecord::Base.connection.create_database("test_active_record_union")
|
17
21
|
ActiveRecord::Base.establish_connection(
|
18
22
|
adapter: "postgresql",
|
19
|
-
|
23
|
+
host: ENV.fetch('DB_HOST', 'localhost'),
|
24
|
+
username: ENV.fetch("POSTGRES_USER", 'active_record_union'),
|
25
|
+
password: ENV.fetch("POSTGRES_PASSWORD", 'active_record_union'),
|
26
|
+
database: ENV.fetch("POSTGRES_DB", "test_active_record_union")
|
20
27
|
)
|
21
28
|
load("support/models.rb")
|
22
29
|
end
|
23
30
|
|
31
|
+
def try_to_drop_database
|
32
|
+
ActiveRecord::Base.connection.drop_database("test_active_record_union")
|
33
|
+
rescue ActiveRecord::NoDatabaseError
|
34
|
+
$stderr.puts "Can't drop database 'test_active_record_union' as it doesn't exist"
|
35
|
+
rescue ActiveRecord::ActiveRecordError => e
|
36
|
+
$stderr.puts "Can't drop database 'test_active_record_union' (but continuing anyway): #{e}"
|
37
|
+
rescue => e
|
38
|
+
$stderr.puts "Other error (#{e.class.name}) dropping database 'test_active_record_union' (but continuing anyway): #{e}"
|
39
|
+
end
|
40
|
+
|
24
41
|
def connect_to_mysql
|
25
42
|
ActiveRecord::Base.establish_connection(
|
26
|
-
adapter: "mysql2"
|
43
|
+
adapter: "mysql2",
|
44
|
+
host: ENV.fetch('DB_HOST', 'localhost'),
|
45
|
+
username: ENV.fetch("MYSQL_USER", "active_record_union"),
|
46
|
+
password: ENV.fetch("MYSQL_PASSWORD", "active_record_union")
|
27
47
|
)
|
28
48
|
ActiveRecord::Base.connection.recreate_database("test_active_record_union")
|
29
49
|
ActiveRecord::Base.establish_connection(
|
30
50
|
adapter: "mysql2",
|
31
|
-
|
51
|
+
host: ENV.fetch('DB_HOST', 'localhost'),
|
52
|
+
username: ENV.fetch("MYSQL_USER", "active_record_union"),
|
53
|
+
password: ENV.fetch("MYSQL_PASSWORD", "active_record_union"),
|
54
|
+
database: ENV.fetch("MYSQL_DB", "test_active_record_union")
|
32
55
|
)
|
33
56
|
load("support/models.rb")
|
34
57
|
end
|
data/spec/union_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe ActiveRecord::Relation do
|
4
4
|
TIME = Time.utc(2014, 7, 19, 0, 0, 0)
|
5
|
-
SQL_TIME =
|
5
|
+
SQL_TIME = "2014-07-19 00:00:00"
|
6
6
|
|
7
7
|
describe ".union" do
|
8
8
|
it "returns an ActiveRecord::Relation" do
|
@@ -34,22 +34,30 @@ describe ActiveRecord::Relation do
|
|
34
34
|
expect(union.to_sql.squish).to eq(
|
35
35
|
"SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '#{SQL_TIME}') ) \"posts\""
|
36
36
|
)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
if ActiveRecord.version >= Gem::Version.new("7.2.0")
|
38
|
+
expect(union.arel.to_sql.squish).to eq(
|
39
|
+
"SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = ? UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > ?) ) \"posts\""
|
40
|
+
)
|
41
|
+
expect(bind_values_from_arel(union.arel, Post.arel_table)).to eq([1, TIME])
|
42
|
+
else
|
43
|
+
expect(union.arel.to_sql.squish).to eq(
|
44
|
+
"SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = ? UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '#{SQL_TIME}') ) \"posts\""
|
45
|
+
)
|
46
|
+
expect(bind_values_from_arel(union.arel, Post.arel_table)).to eq([1])
|
47
|
+
end
|
48
|
+
expect { union.to_a }.to_not raise_error
|
41
49
|
end
|
42
50
|
|
43
51
|
def bind_values_from_relation(relation)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
bind_values_from_arel(relation.arel, relation.arel_table)
|
53
|
+
end
|
54
|
+
|
55
|
+
def bind_values_from_arel(arel, arel_table)
|
56
|
+
collector = Arel::Collectors::Bind.new
|
57
|
+
collector.define_singleton_method(:preparable=) { |_preparable| } if ActiveRecord.version.between?(Gem::Version.new("6.1.0"), Gem::Version.new("7.2.99"))
|
58
|
+
arel_table.class.engine.connection.visitor.accept(
|
59
|
+
arel.ast, collector
|
60
|
+
).value.map { |v| v.try(:value) || v }
|
53
61
|
end
|
54
62
|
|
55
63
|
it "binds values properly" do
|
@@ -72,16 +80,16 @@ describe ActiveRecord::Relation do
|
|
72
80
|
bind_values = bind_values_from_relation union
|
73
81
|
expect(bind_values).to eq([true, 11])
|
74
82
|
|
75
|
-
|
76
83
|
expect(union.to_sql.squish).to eq(
|
77
|
-
"SELECT \"users\".* FROM ( SELECT \"users\".* FROM \"users\" INNER JOIN \"posts\" ON \"posts\".\"
|
84
|
+
"SELECT \"users\".* FROM ( SELECT \"users\".* FROM \"users\" INNER JOIN \"posts\" ON \"posts\".\"draft\" = 1 AND \"posts\".\"user_id\" = \"users\".\"id\" UNION SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 11 ) \"users\""
|
78
85
|
)
|
79
86
|
expect{union.to_a}.to_not raise_error
|
80
87
|
end
|
81
88
|
|
82
89
|
it "doesn't repeat default scopes" do
|
83
90
|
expect(Time).to receive(:now) { Time.utc(2014, 7, 24, 0, 0, 0) }
|
84
|
-
|
91
|
+
|
92
|
+
sql_now = "2014-07-24 00:00:00"
|
85
93
|
|
86
94
|
class PublishedPost < ActiveRecord::Base
|
87
95
|
self.table_name = "posts"
|
@@ -105,9 +113,15 @@ describe ActiveRecord::Relation do
|
|
105
113
|
|
106
114
|
context "in SQLite" do
|
107
115
|
it "lets ORDER BY in query subselects throw a syntax error" do
|
108
|
-
|
109
|
-
|
110
|
-
|
116
|
+
if ActiveRecord.version >= Gem::Version.new("7.2.0")
|
117
|
+
expect(union.to_sql.squish).to eq(
|
118
|
+
"SELECT \"posts\".* FROM ( (SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ORDER BY \"posts\".\"created_at\" ASC) UNION (SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00') ORDER BY \"posts\".\"created_at\" ASC) ) \"posts\" ORDER BY \"created_at\" ASC"
|
119
|
+
)
|
120
|
+
else
|
121
|
+
expect(union.to_sql.squish).to eq(
|
122
|
+
"SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ORDER BY \"posts\".\"created_at\" ASC UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00') ORDER BY \"posts\".\"created_at\" ASC ) \"posts\" ORDER BY \"created_at\" ASC"
|
123
|
+
)
|
124
|
+
end
|
111
125
|
expect{union.to_a}.to raise_error(ActiveRecord::StatementInvalid)
|
112
126
|
end
|
113
127
|
end
|
@@ -116,8 +130,9 @@ describe ActiveRecord::Relation do
|
|
116
130
|
it "wraps query subselects in parentheses to allow ORDER BY clauses" do
|
117
131
|
Databases.with_postgres do
|
118
132
|
expect(union.to_sql.squish).to eq(
|
119
|
-
"SELECT \"posts\".* FROM ( (SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ORDER BY \"posts\".\"created_at\" ASC) UNION (SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '
|
133
|
+
"SELECT \"posts\".* FROM ( (SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ORDER BY \"posts\".\"created_at\" ASC) UNION (SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00') ORDER BY \"posts\".\"created_at\" ASC) ) \"posts\" ORDER BY \"created_at\" ASC"
|
120
134
|
)
|
135
|
+
|
121
136
|
expect{union.to_a}.to_not raise_error
|
122
137
|
end
|
123
138
|
end
|
@@ -127,8 +142,9 @@ describe ActiveRecord::Relation do
|
|
127
142
|
it "wraps query subselects in parentheses to allow ORDER BY clauses" do
|
128
143
|
Databases.with_mysql do
|
129
144
|
expect(union.to_sql.squish).to eq(
|
130
|
-
"SELECT `posts`.* FROM ( (SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 ORDER BY `posts`.`created_at` ASC) UNION (SELECT `posts`.* FROM `posts` WHERE (created_at > '
|
145
|
+
"SELECT `posts`.* FROM ( (SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 ORDER BY `posts`.`created_at` ASC) UNION (SELECT `posts`.* FROM `posts` WHERE (created_at > '2014-07-19 00:00:00') ORDER BY `posts`.`created_at` ASC) ) `posts` ORDER BY `created_at` ASC"
|
131
146
|
)
|
147
|
+
|
132
148
|
expect{union.to_a}.to_not raise_error
|
133
149
|
end
|
134
150
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_union
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Hempel
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '6.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,48 +80,6 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: sqlite3
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: pg
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: mysql2
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
83
|
description: UNIONs in ActiveRecord! Adds proper union and union_all methods to ActiveRecord::Relation.
|
126
84
|
email:
|
127
85
|
- plasticchicken@gmail.com
|
@@ -129,20 +87,24 @@ executables: []
|
|
129
87
|
extensions: []
|
130
88
|
extra_rdoc_files: []
|
131
89
|
files:
|
90
|
+
- ".github/workflows/testing.yml"
|
132
91
|
- ".gitignore"
|
133
|
-
-
|
92
|
+
- Gemfile
|
134
93
|
- LICENSE.txt
|
135
94
|
- README.md
|
136
95
|
- Rakefile
|
137
96
|
- active_record_union.gemspec
|
138
97
|
- bin/console
|
98
|
+
- bin/create-db-users
|
139
99
|
- lib/active_record_union.rb
|
140
100
|
- lib/active_record_union/active_record/relation/union.rb
|
141
101
|
- lib/active_record_union/version.rb
|
142
|
-
-
|
143
|
-
-
|
144
|
-
-
|
145
|
-
-
|
102
|
+
- rails_6.0.gemfile
|
103
|
+
- rails_6.1.gemfile
|
104
|
+
- rails_7.0.gemfile
|
105
|
+
- rails_7.1.gemfile
|
106
|
+
- rails_7.2.gemfile
|
107
|
+
- rails_8.0.gemfile
|
146
108
|
- spec/spec_helper.rb
|
147
109
|
- spec/support/databases.rb
|
148
110
|
- spec/support/models.rb
|
@@ -151,7 +113,7 @@ homepage: https://github.com/brianhempel/active_record_union
|
|
151
113
|
licenses:
|
152
114
|
- Public Domain
|
153
115
|
metadata: {}
|
154
|
-
post_install_message:
|
116
|
+
post_install_message:
|
155
117
|
rdoc_options: []
|
156
118
|
require_paths:
|
157
119
|
- lib
|
@@ -166,9 +128,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
128
|
- !ruby/object:Gem::Version
|
167
129
|
version: '0'
|
168
130
|
requirements: []
|
169
|
-
|
170
|
-
|
171
|
-
signing_key:
|
131
|
+
rubygems_version: 3.4.10
|
132
|
+
signing_key:
|
172
133
|
specification_version: 4
|
173
134
|
summary: UNIONs in ActiveRecord! Adds proper union and union_all methods to ActiveRecord::Relation.
|
174
135
|
test_files:
|
@@ -177,3 +138,4 @@ test_files:
|
|
177
138
|
- spec/support/models.rb
|
178
139
|
- spec/union_spec.rb
|
179
140
|
- bin/console
|
141
|
+
- bin/create-db-users
|
data/.travis.yml
DELETED
data/rails_4_2.gemfile
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in active_record_union.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
gem 'rails', '~> 4.2.7'
|
7
|
-
|
8
|
-
# On Rails < 5.2, only pg < v1 is supported. See:
|
9
|
-
# https://github.com/rails/rails/pull/31671
|
10
|
-
# https://bitbucket.org/ged/ruby-pg/issues/270/pg-100-x64-mingw32-rails-server-not-start
|
11
|
-
gem 'pg', '~> 0.21'
|
data/rails_5_0.gemfile
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in active_record_union.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
gem 'rails', '~> 5.0.0'
|
7
|
-
|
8
|
-
# On Rails < 5.2, only pg < v1 is supported. See:
|
9
|
-
# https://github.com/rails/rails/pull/31671
|
10
|
-
# https://bitbucket.org/ged/ruby-pg/issues/270/pg-100-x64-mingw32-rails-server-not-start
|
11
|
-
gem 'pg', '~> 0.21'
|
data/rails_5_1.gemfile
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in active_record_union.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
gem 'rails', '~> 5.1.0'
|
7
|
-
|
8
|
-
# On Rails < 5.2, only pg < v1 is supported. See:
|
9
|
-
# https://github.com/rails/rails/pull/31671
|
10
|
-
# https://bitbucket.org/ged/ruby-pg/issues/270/pg-100-x64-mingw32-rails-server-not-start
|
11
|
-
gem 'pg', '~> 0.21'
|
data/rails_5_2.gemfile
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in active_record_union.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
# pg v1.0+ compatibility, https://github.com/rails/rails/pull/31671:
|
7
|
-
gem 'rails', '~> 5.2.0.beta2', git: 'https://github.com/rails/rails', ref: 'f1af27fd9d9101684b26d0dcf2028859d67bec1f'
|