aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile.lock8
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/activerecord.gemspec2
-rw-r--r--activerecord/lib/active_record/associations/join_dependency.rb4
-rw-r--r--activerecord/lib/active_record/associations/join_dependency/join_association.rb4
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/array_handler.rb12
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb10
-rw-r--r--activerecord/test/cases/relation/or_test.rb11
-rw-r--r--railties/lib/rails/test_unit/runner.rb9
-rw-r--r--railties/test/application/console_test.rb31
-rw-r--r--railties/test/application/dbconsole_test.rb23
-rw-r--r--railties/test/console_helpers.rb23
-rw-r--r--railties/test/engine/commands_test.rb24
13 files changed, 72 insertions, 96 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 0c727a76ca..a6f7286994 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -31,9 +31,9 @@ GIT
GIT
remote: https://github.com/rails/arel.git
- revision: 0e7ce3f4c7c17e72f905b26aff3893149f524888
+ revision: f4227bf20a16a1d688afc24cf0038e2f98905dd4
specs:
- arel (8.0.0)
+ arel (9.0.0.alpha)
GIT
remote: https://github.com/rails/sass-rails.git
@@ -81,7 +81,7 @@ PATH
activerecord (5.2.0.alpha)
activemodel (= 5.2.0.alpha)
activesupport (= 5.2.0.alpha)
- arel (~> 8.0)
+ arel (= 9.0.0.alpha)
activesupport (5.2.0.alpha)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
@@ -188,7 +188,7 @@ GEM
erubis (2.7.0)
et-orbi (1.0.5)
tzinfo
- event_emitter (0.2.5)
+ event_emitter (0.2.6)
eventmachine (1.2.3)
eventmachine (1.2.3-x64-mingw32)
eventmachine (1.2.3-x86-mingw32)
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index a656c767c0..1ff7010c2f 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,10 @@
+* `Relation#or` now accepts two relations who have different values for
+ `references` only, as `references` can be implicitly called by `where`.
+
+ Fixes #29411.
+
+ *Sean Griffin*
+
* ApplicationRecord is no longer generated when generating models. If you
need to generate it, it can be created with `rails g application_record`.
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index 7b62c98c6e..7ad06fe840 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -31,5 +31,5 @@ Gem::Specification.new do |s|
s.add_dependency "activesupport", version
s.add_dependency "activemodel", version
- s.add_dependency "arel", "~> 8.0"
+ s.add_dependency "arel", "9.0.0.alpha"
end
diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb
index 2c3d5b3429..dc029c08bd 100644
--- a/activerecord/lib/active_record/associations/join_dependency.rb
+++ b/activerecord/lib/active_record/associations/join_dependency.rb
@@ -174,9 +174,9 @@ module ActiveRecord
def make_join_constraints(parent, child, join_type, aliasing = false)
tables = aliasing ? table_aliases_for(parent, child) : child.tables
- info = make_constraints(parent, child, tables, join_type)
+ joins = make_constraints(parent, child, tables, join_type)
- [info] + child.children.flat_map { |c| make_join_constraints(child, c, join_type, aliasing) }
+ joins.concat child.children.flat_map { |c| make_join_constraints(child, c, join_type, aliasing) }
end
def table_aliases_for(parent, node)
diff --git a/activerecord/lib/active_record/associations/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/join_dependency/join_association.rb
index 30dbdb7fa5..a526468bf6 100644
--- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb
+++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb
@@ -23,8 +23,6 @@ module ActiveRecord
super && reflection == other.reflection
end
- JoinInformation = Struct.new :joins
-
def join_constraints(foreign_table, foreign_klass, join_type, tables, chain)
joins = []
tables = tables.reverse
@@ -51,7 +49,7 @@ module ActiveRecord
foreign_table, foreign_klass = table, klass
end
- JoinInformation.new joins
+ joins
end
def table
diff --git a/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb
index ad617365fc..2fd75c8958 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb
@@ -9,7 +9,6 @@ module ActiveRecord
def call(attribute, value)
return attribute.in([]) if value.empty?
- return queries_predicates(value) if value.all? { |v| v.is_a?(Hash) }
values = value.map { |x| x.is_a?(Base) ? x.id : x }
nils, values = values.partition(&:nil?)
@@ -44,17 +43,6 @@ module ActiveRecord
other
end
end
-
- private
- def queries_predicates(queries)
- if queries.size > 1
- queries.map do |query|
- Arel::Nodes::And.new(predicate_builder.build_from_hash(query))
- end.inject(&:or)
- else
- predicate_builder.build_from_hash(queries.first)
- end
- end
end
end
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 812c8e7e3f..f7fe968b55 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -635,6 +635,7 @@ module ActiveRecord
self.where_clause = self.where_clause.or(other.where_clause)
self.having_clause = having_clause.or(other.having_clause)
+ self.references_values += other.references_values
self
end
@@ -1014,11 +1015,8 @@ module ActiveRecord
klass, table, association_joins, join_list
)
- join_infos = join_dependency.join_constraints stashed_association_joins, join_type
-
- join_infos.each do |info|
- info.joins.each { |join| manager.from(join) }
- end
+ joins = join_dependency.join_constraints(stashed_association_joins, join_type)
+ joins.each { |join| manager.from(join) }
manager.join_sources.concat(join_list)
@@ -1161,7 +1159,7 @@ module ActiveRecord
end
end
- STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope]
+ STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
def structurally_incompatible_values_for_or(other)
STRUCTURAL_OR_METHODS.reject do |method|
get_value(method) == other.get_value(method)
diff --git a/activerecord/test/cases/relation/or_test.rb b/activerecord/test/cases/relation/or_test.rb
index 3269620987..b01801b41f 100644
--- a/activerecord/test/cases/relation/or_test.rb
+++ b/activerecord/test/cases/relation/or_test.rb
@@ -1,11 +1,14 @@
# frozen_string_literal: true
require "cases/helper"
+require "models/author"
+require "models/categorization"
require "models/post"
module ActiveRecord
class OrTest < ActiveRecord::TestCase
fixtures :posts
+ fixtures :authors
def test_or_with_relation
expected = Post.where("id = 1 or id = 2").to_a
@@ -115,5 +118,13 @@ module ActiveRecord
Post.where(id: [1, 2, 3]).or(title: "Rails")
end
end
+
+ def test_or_with_references_inequality
+ joined = Post.includes(:author)
+ actual = joined.where(authors: { id: 1 })
+ .or(joined.where(title: "I don't have any comments"))
+ expected = Author.find(1).posts + Post.where(title: "I don't have any comments")
+ assert_equal expected.sort_by(&:id), actual.sort_by(&:id)
+ end
end
end
diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb
index 33ba2788b4..1f3a248bcb 100644
--- a/railties/lib/rails/test_unit/runner.rb
+++ b/railties/lib/rails/test_unit/runner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "shellwords"
require "method_source"
require "rake/file_list"
@@ -58,7 +60,8 @@ module Rails
private
def extract_filters(argv)
- argv.select { |arg| arg =~ %r{^/?\w+/} }.map do |path|
+ # Extract absolute and relative paths but skip -n /.*/ regexp filters.
+ argv.select { |arg| arg =~ %r%^/?\w+/% && !arg.end_with?("/") }.map do |path|
case
when path =~ /(:\d+)+$/
file, *lines = path.split(":")
@@ -66,11 +69,11 @@ module Rails
file
when Dir.exist?(path)
"#{path}/**/*_test.rb"
- when path !~ /\/$/
+ else
filters << [ path, [] ]
path
end
- end.compact
+ end
end
end
end
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index 057d473870..31bef82ccc 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -1,4 +1,5 @@
require "isolation/abstract_unit"
+require "console_helpers"
class ConsoleTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
@@ -93,14 +94,11 @@ class ConsoleTest < ActiveSupport::TestCase
end
end
-begin
- require "pty"
-rescue LoadError
-end
-
class FullStackConsoleTest < ActiveSupport::TestCase
+ include ConsoleHelpers
+
def setup
- skip "PTY unavailable" unless defined?(PTY) && PTY.respond_to?(:open)
+ skip "PTY unavailable" unless available_pty?
build_app
app_file "app/models/post.rb", <<-CODE
@@ -116,24 +114,11 @@ class FullStackConsoleTest < ActiveSupport::TestCase
teardown_app
end
- def assert_output(expected, timeout = 1)
- timeout = Time.now + timeout
-
- output = ""
- until output.include?(expected) || Time.now > timeout
- if IO.select([@master], [], [], 0.1)
- output << @master.read(1)
- end
- end
-
- assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
- end
-
def write_prompt(command, expected_output = nil)
@master.puts command
- assert_output command
- assert_output expected_output if expected_output
- assert_output "> "
+ assert_output command, @master
+ assert_output expected_output, @master if expected_output
+ assert_output "> ", @master
end
def spawn_console(options)
@@ -142,7 +127,7 @@ class FullStackConsoleTest < ActiveSupport::TestCase
in: @slave, out: @slave, err: @slave
)
- assert_output "> ", 30
+ assert_output "> ", @master, 30
end
def test_sandbox
diff --git a/railties/test/application/dbconsole_test.rb b/railties/test/application/dbconsole_test.rb
index ab42199db7..5d89d0e44d 100644
--- a/railties/test/application/dbconsole_test.rb
+++ b/railties/test/application/dbconsole_test.rb
@@ -1,12 +1,10 @@
require "isolation/abstract_unit"
-begin
- require "pty"
-rescue LoadError
-end
+require "console_helpers"
module ApplicationTests
class DBConsoleTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
+ include ConsoleHelpers
def setup
skip "PTY unavailable" unless available_pty?
@@ -74,22 +72,5 @@ module ApplicationTests
def spawn_dbconsole(fd, options = nil)
Process.spawn("#{app_path}/bin/rails dbconsole #{options}", in: fd, out: fd, err: fd)
end
-
- def assert_output(expected, io, timeout = 5)
- timeout = Time.now + timeout
-
- output = ""
- until output.include?(expected) || Time.now > timeout
- if IO.select([io], [], [], 0.1)
- output << io.read(1)
- end
- end
-
- assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
- end
-
- def available_pty?
- defined?(PTY) && PTY.respond_to?(:open)
- end
end
end
diff --git a/railties/test/console_helpers.rb b/railties/test/console_helpers.rb
new file mode 100644
index 0000000000..4b11afa511
--- /dev/null
+++ b/railties/test/console_helpers.rb
@@ -0,0 +1,23 @@
+begin
+ require "pty"
+rescue LoadError
+end
+
+module ConsoleHelpers
+ def assert_output(expected, io, timeout = 10)
+ timeout = Time.now + timeout
+
+ output = ""
+ until output.include?(expected) || Time.now > timeout
+ if IO.select([io], [], [], 0.1)
+ output << io.read(1)
+ end
+ end
+
+ assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
+ end
+
+ def available_pty?
+ defined?(PTY) && PTY.respond_to?(:open)
+ end
+end
diff --git a/railties/test/engine/commands_test.rb b/railties/test/engine/commands_test.rb
index b1c937143f..018c7c949e 100644
--- a/railties/test/engine/commands_test.rb
+++ b/railties/test/engine/commands_test.rb
@@ -1,10 +1,9 @@
require "abstract_unit"
-begin
- require "pty"
-rescue LoadError
-end
+require "console_helpers"
class Rails::Engine::CommandsTest < ActiveSupport::TestCase
+ include ConsoleHelpers
+
def setup
@destination_root = Dir.mktmpdir("bukkits")
Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` }
@@ -64,19 +63,6 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase
"#{@destination_root}/bukkits"
end
- def assert_output(expected, io, timeout = 10)
- timeout = Time.now + timeout
-
- output = ""
- until output.include?(expected) || Time.now > timeout
- if IO.select([io], [], [], 0.1)
- output << io.read(1)
- end
- end
-
- assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
- end
-
def spawn_command(command, fd)
Process.spawn(
"#{plugin_path}/bin/rails #{command}",
@@ -84,10 +70,6 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase
)
end
- def available_pty?
- defined?(PTY) && PTY.respond_to?(:open)
- end
-
def kill(pid)
Process.kill("TERM", pid)
Process.wait(pid)