diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml new file mode 100644 index 0000000..f471b08 --- /dev/null +++ b/.github/workflows/testing.yml @@ -0,0 +1,70 @@ +name: RSpec Test Matrix +on: + push: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + + services: + postgresql: + image: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: + POSTGRES_DB: active_record_union + POSTGRES_USER: active_record_union + POSTGRES_PASSWORD: active_record_union + + mysql2: + image: mysql:8.0 + env: + MYSQL_DATABASE: active_record_union + MYSQL_ROOT_PASSWORD: active_record_union + options: >- + --health-cmd "mysqladmin ping" + --health-interval 10s + --health-timeout 5s + ports: + - "3306:3306" + + strategy: + fail-fast: false + matrix: + # just define specific versions for each rails version + include: + - ruby: 2.6 + rails: "6.0" + - ruby: "3.0" + rails: 6.1 + - ruby: 3.1 + rails: "7.0" + - ruby: 3.2 + rails: 7.1 + - ruby: 3.2 + rails: 7.2 + - ruby: 3.3 + rails: "8.0" + + env: + BUNDLE_GEMFILE: "rails_${{ matrix.rails }}.gemfile" + DB_HOST: 127.0.0.1 + MYSQL_ROOT_HOST: "%" + MYSQL_DB: active_record_union + MYSQL_USER: root + MYSQL_PASSWORD: active_record_union + steps: + - uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true # install gems and cache + + - run: bundle exec rspec --force-color --format d diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a2622d5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: ruby -addons: - postgresql: "17" -rvm: - - 3.3.5 -gemfile: - - rails_6_1.gemfile - - rails_7_0.gemfile - - rails_7_1.gemfile -script: bundle exec rspec diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..7ef00db --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +# this is just a convenience for out of the box development +source 'https://rubygems.org' + +eval_gemfile File.expand_path('./rails_8.0.gemfile', __dir__) diff --git a/README.md b/README.md index ffaf8df..e862db7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ user_1.posts.union(user_2.posts).union(Post.published) user_1.posts.union_all(user_2.posts) ``` -ActiveRecordUnion is tested against Rails 5.0, 5.1, and 5.2. It should also work on Rails 4.2. It may or may not work on Rails 4.0/4.1. +ActiveRecordUnion is tested against Rails 6.0, 6.1, 7.0, 7.1, 7.2 and 8.0. 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. @@ -216,9 +216,9 @@ This public domain dedication follows the the CC0 1.0 at https://creativecommons 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Run the tests: 1. Install MySQL and PostgreSQL. - 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. From a vanilla install of MariaDB from Homebrew, this just works. For Postgres installed by Homebrew, you may need to run `$ echo "create database my_computer_user_name;" | psql postgres` since the initial database created by Homebrew is named "postgres" but PG defaults to connecting to a database named after your username. + 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`). 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). - 4. Run `rake test_rails_4_2` or `rake test_rails_5_2` etc. to test a specific Rails version. + 4. Run `rake test_rails_8_0` or `rake test_rails_7_2` etc. to test a specific Rails version. 4. There is also a `bin/console` command to load up a REPL for playing around 5. Commit your changes (`git commit -am 'Add some feature'`) 6. Push to the branch (`git push origin my-new-feature`) diff --git a/Rakefile b/Rakefile index b92b9df..7fb579a 100644 --- a/Rakefile +++ b/Rakefile @@ -51,11 +51,11 @@ end TestTasks.gemfiles.each do |gemfile| - rails_version_underscored = gemfile[/rails_(.+)\.gemfile/, 1] + rails_version = gemfile[/rails_(.+)\.gemfile/, 1] - desc "Test Rails #{rails_version_underscored.gsub("_", ".")}" - task :"test_rails_#{rails_version_underscored}" do + desc "Test Rails #{rails_version}" + task :"test_rails_#{rails_version.gsub(".", "_")}" do env = { 'BUNDLE_GEMFILE' => gemfile } TestTasks.run_one(env) end -end \ No newline at end of file +end diff --git a/active_record_union.gemspec b/active_record_union.gemspec index a945f75..89a77ef 100644 --- a/active_record_union.gemspec +++ b/active_record_union.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.files.grep(%r{^bin/}) spec.require_paths = ["lib"] - spec.add_dependency "activerecord", ">= 4.0" + spec.add_dependency "activerecord", ">= 6.0" spec.add_development_dependency "bundler" spec.add_development_dependency "rake" diff --git a/bin/create-db-users b/bin/create-db-users new file mode 100755 index 0000000..e786129 --- /dev/null +++ b/bin/create-db-users @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +GREEN='\033[0;32m' +RESET_COLOR='\033[0m' + +if [ -n "$1" ]; then cat <<'HELP'; exit; fi +Usage: bin/create-db-users +Create the active_record_union database users for all the supported databases. +If the `DB` environment variable is set, do the above only for that database. +HELP + +USER='active_record_union' +PASS='active_record_union' + +set -e +log() { if [ -t 1 ]; then echo -e >&2 "${GREEN}create-db-users: $@${RESET_COLOR}"; else echo >&2 "$@"; fi } + +create_mysql_user() { + if mysql -s -u"$USER" -p"$PASS" -e '' 2>/dev/null; then return; fi + log "Creating MySQL '$USER' user. MySQL root password required." + mysql --verbose -uroot -p </dev/null; then + log "sudo required:" + cmd="sudo -u ${PG_DAEMON_USER:-postgres} psql postgres" + fi +# need to also create database first time + $cmd --echo-all <= Gem::Version.new('5.2.0.beta2') - # Since Rails 5.2, binds are maintained only in the Arel AST. - def build_union_relation(arel_table_alias, _other) - self.klass.unscoped.from(arel_table_alias) - end - elsif ActiveRecord::VERSION::MAJOR >= 5 - # In Rails >= 5.0, < 5.2, binds are maintained only in ActiveRecord - # relations and clauses. - def build_union_relation(arel_table_alias, other) - relation = self.klass.unscoped.spawn - relation.from_clause = - UnionFromClause.new(arel_table_alias, nil, - self.bound_attributes + other.bound_attributes) - relation - end - - class UnionFromClause < ActiveRecord::Relation::FromClause - def initialize(value, name, bound_attributes) - super(value, name) - @bound_attributes = bound_attributes - end - - def binds - @bound_attributes - end - end - else - # In Rails 4.x, binds are maintained in both ActiveRecord relations and - # clauses and also in their Arel ASTs. - def build_union_relation(arel_table_alias, other) - relation = self.klass.unscoped.from(arel_table_alias) - relation.bind_values = self.arel.bind_values + self.bind_values + - other.arel.bind_values + other.bind_values - relation - end + def build_union_relation(arel_table_alias, _other) + self.klass.unscoped.from(arel_table_alias) end def verify_relations_for_set_operation!(operation, *relations) diff --git a/rails_6.0.gemfile b/rails_6.0.gemfile new file mode 100644 index 0000000..e6f3117 --- /dev/null +++ b/rails_6.0.gemfile @@ -0,0 +1,16 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in active_record_union.gemspec +gemspec + +gem 'rails', '~> 6.0.0' + +# https://github.com/rails/rails/blob/v6.0.6.1/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +gem "pg", ">= 0.18", "< 2.0" + +# https://github.com/rails/rails/blob/v6.0.2/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13 +gem "sqlite3", "~> 1.4" + +# https://github.com/rails/rails/blob/v6.0.6.1/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +gem "mysql2", ">= 0.4.4" + diff --git a/rails_6.1.gemfile b/rails_6.1.gemfile new file mode 100644 index 0000000..87c5f3c --- /dev/null +++ b/rails_6.1.gemfile @@ -0,0 +1,16 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in active_record_union.gemspec +gemspec + +gem 'rails', '~> 6.1.0' + +# https://github.com/rails/rails/blob/v6.1.7.10/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +gem "pg", "~> 1.1" + +# https://github.com/rails/rails/blob/v6.1.2/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13 +gem "sqlite3", "~> 1.4" + +# https://github.com/rails/rails/blob/v6.1.7.10/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +gem "mysql2", "~> 0.5" + diff --git a/rails_7.0.gemfile b/rails_7.0.gemfile new file mode 100644 index 0000000..83fe1d0 --- /dev/null +++ b/rails_7.0.gemfile @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +# Specify your gem's dependencies in active_record_union.gemspec +gemspec + +gem 'rails', '~> 7.0.0' + +# https://github.com/rails/rails/blob/v7.0.2/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13 +gem 'sqlite3', '~> 1.4' + +# https://github.com/rails/rails/blob/v7.0.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4 +gem 'pg', '~> 1.1' + +# https://github.com/rails/rails/blob/v7.0.2/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6 +gem 'mysql2', '~> 0.5' diff --git a/rails_7.1.gemfile b/rails_7.1.gemfile new file mode 100644 index 0000000..b599c1a --- /dev/null +++ b/rails_7.1.gemfile @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +# Specify your gem's dependencies in active_record_union.gemspec +gemspec + +gem 'rails', '~> 7.1.0' + +# https://github.com/rails/rails/blob/v7.1.2/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13 +gem 'sqlite3', '~> 1.4' + +# https://github.com/rails/rails/blob/v7.1.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4 +gem 'pg', '~> 1.1' + +# https://github.com/rails/rails/blob/v7.1.2/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6 +gem 'mysql2', '~> 0.5' diff --git a/rails_7.2.gemfile b/rails_7.2.gemfile new file mode 100644 index 0000000..1899253 --- /dev/null +++ b/rails_7.2.gemfile @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +# Specify your gem's dependencies in active_record_union.gemspec +gemspec + +gem 'rails', '~> 7.2.0' + +# https://github.com/rails/rails/blob/v7.2.0/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13 +gem 'sqlite3', '>= 1.4' + +# https://github.com/rails/rails/blob/v7.2.0/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4 +gem 'pg', '~> 1.1' + +# https://github.com/rails/rails/blob/v7.2.0/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6 +gem 'mysql2', '~> 0.5' diff --git a/rails_8.0.gemfile b/rails_8.0.gemfile new file mode 100644 index 0000000..7c87d2e --- /dev/null +++ b/rails_8.0.gemfile @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +# Specify your gem's dependencies in active_record_union.gemspec +gemspec + +gem 'rails', '~> 8.0.0' + +# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L13 +gem 'sqlite3', '>= 2.1' + +# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L4 +gem 'pg', '~> 1.1' + +# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6 +gem 'mysql2', '~> 0.5' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bf56911..9d5426b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -9,6 +9,7 @@ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| + config.backtrace_inclusion_patterns << %r{gems/([0-9.])+/gems/(?!rspec|capybara)} if ENV['BACKTRACE'] # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. diff --git a/spec/support/databases.rb b/spec/support/databases.rb index 5898b0a..eb75f40 100644 --- a/spec/support/databases.rb +++ b/spec/support/databases.rb @@ -11,24 +11,47 @@ def connect_to_sqlite def connect_to_postgres ActiveRecord::Base.establish_connection( - adapter: "postgresql" + adapter: "postgresql", + host: ENV.fetch('DB_HOST', 'localhost'), + username: ENV.fetch("POSTGRES_USER", 'active_record_union'), + password: ENV.fetch("POSTGRES_PASSWORD", 'active_record_union') ) - ActiveRecord::Base.connection.recreate_database("test_active_record_union") + try_to_drop_database + ActiveRecord::Base.connection.create_database("test_active_record_union") ActiveRecord::Base.establish_connection( adapter: "postgresql", - database: "test_active_record_union" + host: ENV.fetch('DB_HOST', 'localhost'), + username: ENV.fetch("POSTGRES_USER", 'active_record_union'), + password: ENV.fetch("POSTGRES_PASSWORD", 'active_record_union'), + database: ENV.fetch("POSTGRES_DB", "test_active_record_union") ) load("support/models.rb") end + def try_to_drop_database + ActiveRecord::Base.connection.drop_database("test_active_record_union") + rescue ActiveRecord::NoDatabaseError + $stderr.puts "Can't drop database 'test_active_record_union' as it doesn't exist" + rescue ActiveRecord::ActiveRecordError => e + $stderr.puts "Can't drop database 'test_active_record_union' (but continuing anyway): #{e}" + rescue => e + $stderr.puts "Other error (#{e.class.name}) dropping database 'test_active_record_union' (but continuing anyway): #{e}" + end + def connect_to_mysql ActiveRecord::Base.establish_connection( - adapter: "mysql2" + adapter: "mysql2", + host: ENV.fetch('DB_HOST', 'localhost'), + username: ENV.fetch("MYSQL_USER", "active_record_union"), + password: ENV.fetch("MYSQL_PASSWORD", "active_record_union") ) ActiveRecord::Base.connection.recreate_database("test_active_record_union") ActiveRecord::Base.establish_connection( adapter: "mysql2", - database: "test_active_record_union" + host: ENV.fetch('DB_HOST', 'localhost'), + username: ENV.fetch("MYSQL_USER", "active_record_union"), + password: ENV.fetch("MYSQL_PASSWORD", "active_record_union"), + database: ENV.fetch("MYSQL_DB", "test_active_record_union") ) load("support/models.rb") end diff --git a/spec/union_spec.rb b/spec/union_spec.rb index f2020e1..83bbed0 100644 --- a/spec/union_spec.rb +++ b/spec/union_spec.rb @@ -2,7 +2,7 @@ describe ActiveRecord::Relation do TIME = Time.utc(2014, 7, 19, 0, 0, 0) - SQL_TIME = ActiveRecord::VERSION::MAJOR >= 5 ? "2014-07-19 00:00:00" : "2014-07-19 00:00:00.000000" + SQL_TIME = "2014-07-19 00:00:00" describe ".union" do it "returns an ActiveRecord::Relation" do @@ -34,22 +34,30 @@ expect(union.to_sql.squish).to eq( "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '#{SQL_TIME}') ) \"posts\"" ) - expect(union.arel.to_sql.squish).to eq( - "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = ? UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '#{SQL_TIME}') ) \"posts\"" - ) - expect{union.to_a}.to_not raise_error + if ActiveRecord.version >= Gem::Version.new("7.2.0") + expect(union.arel.to_sql.squish).to eq( + "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = ? UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > ?) ) \"posts\"" + ) + expect(bind_values_from_arel(union.arel, Post.arel_table)).to eq([1, TIME]) + else + expect(union.arel.to_sql.squish).to eq( + "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = ? UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '#{SQL_TIME}') ) \"posts\"" + ) + expect(bind_values_from_arel(union.arel, Post.arel_table)).to eq([1]) + end + expect { union.to_a }.to_not raise_error end def bind_values_from_relation(relation) - if ActiveRecord.gem_version >= Gem::Version.new('5.2.0.beta2') - relation.arel_table.class.engine.connection.visitor.accept( - relation.arel.ast, Arel::Collectors::Bind.new - ).value.map(&:value) - elsif ActiveRecord::VERSION::MAJOR >= 5 - relation.bound_attributes.map { |a| a.value_for_database } - else - (relation.arel.bind_values + relation.bind_values).map { |_column, value| value } - end + bind_values_from_arel(relation.arel, relation.arel_table) + end + + def bind_values_from_arel(arel, arel_table) + collector = Arel::Collectors::Bind.new + collector.define_singleton_method(:preparable=) { |_preparable| } if ActiveRecord.version.between?(Gem::Version.new("6.1.0"), Gem::Version.new("7.2.99")) + arel_table.class.engine.connection.visitor.accept( + arel.ast, collector + ).value.map { |v| v.try(:value) || v } end it "binds values properly" do @@ -72,16 +80,16 @@ def bind_values_from_relation(relation) bind_values = bind_values_from_relation union expect(bind_values).to eq([true, 11]) - expect(union.to_sql.squish).to eq( - "SELECT \"users\".* FROM ( SELECT \"users\".* FROM \"users\" INNER JOIN \"posts\" ON \"posts\".\"user_id\" = \"users\".\"id\" AND \"posts\".\"draft\" = 't' UNION SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 11 ) \"users\"" + "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\"" ) expect{union.to_a}.to_not raise_error end it "doesn't repeat default scopes" do expect(Time).to receive(:now) { Time.utc(2014, 7, 24, 0, 0, 0) } - sql_now = "2014-07-24 00:00:00#{".000000" if ActiveRecord::VERSION::MAJOR < 5}" + + sql_now = "2014-07-24 00:00:00" class PublishedPost < ActiveRecord::Base self.table_name = "posts" @@ -105,13 +113,13 @@ class PublishedPost < ActiveRecord::Base context "in SQLite" do it "lets ORDER BY in query subselects throw a syntax error" do - if ([ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] <=> [5, 2]) >= 0 + if ActiveRecord.version >= Gem::Version.new("7.2.0") expect(union.to_sql.squish).to eq( - "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" + "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" ) else expect(union.to_sql.squish).to eq( - "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 > '#{SQL_TIME}') ORDER BY \"posts\".\"created_at\" ASC ) \"posts\" ORDER BY \"posts\".\"created_at\" ASC" + "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" ) end expect{union.to_a}.to raise_error(ActiveRecord::StatementInvalid) @@ -121,15 +129,10 @@ class PublishedPost < ActiveRecord::Base context "in Postgres" do it "wraps query subselects in parentheses to allow ORDER BY clauses" do Databases.with_postgres do - if ([ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] <=> [5, 2]) >= 0 - expect(union.to_sql.squish).to eq( - "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" - ) - else - expect(union.to_sql.squish).to eq( - "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 > '#{SQL_TIME}') ORDER BY \"posts\".\"created_at\" ASC) ) \"posts\" ORDER BY \"posts\".\"created_at\" ASC" - ) - end + expect(union.to_sql.squish).to eq( + "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" + ) + expect{union.to_a}.to_not raise_error end end @@ -138,15 +141,10 @@ class PublishedPost < ActiveRecord::Base context "in MySQL" do it "wraps query subselects in parentheses to allow ORDER BY clauses" do Databases.with_mysql do - if ([ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] <=> [5, 2]) >= 0 - expect(union.to_sql.squish).to eq( - "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" - ) - else - expect(union.to_sql.squish).to eq( - "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 > '#{SQL_TIME}') ORDER BY `posts`.`created_at` ASC) ) `posts` ORDER BY `posts`.`created_at` ASC" - ) - end + expect(union.to_sql.squish).to eq( + "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" + ) + expect{union.to_a}.to_not raise_error end end