aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/relation_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/relation_test.rb')
-rw-r--r--activerecord/test/cases/relation_test.rb97
1 files changed, 54 insertions, 43 deletions
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 5fb32270b7..b424ca91de 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "cases/helper"
require "models/post"
require "models/comment"
@@ -6,25 +8,7 @@ require "models/rating"
module ActiveRecord
class RelationTest < ActiveRecord::TestCase
- fixtures :posts, :comments, :authors, :author_addresses
-
- FakeKlass = Struct.new(:table_name, :name) do
- extend ActiveRecord::Delegation::DelegateCache
-
- inherited self
-
- def self.connection
- Post.connection
- end
-
- def self.table_name
- "fake_table"
- end
-
- def self.sanitize_sql_for_order(sql)
- sql
- end
- end
+ fixtures :posts, :comments, :authors, :author_addresses, :ratings
def test_construction
relation = Relation.new(FakeKlass, :b, nil)
@@ -70,8 +54,8 @@ module ActiveRecord
def test_has_values
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
- relation.where! relation.table[:id].eq(10)
- assert_equal({ id: 10 }, relation.where_values_hash)
+ relation.where!(id: 10)
+ assert_equal({ "id" => 10 }, relation.where_values_hash)
end
def test_values_wrong_table
@@ -84,16 +68,11 @@ module ActiveRecord
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
left = relation.table[:id].eq(10)
right = relation.table[:id].eq(10)
- combine = left.and right
+ combine = left.or(right)
relation.where! combine
assert_equal({}, relation.where_values_hash)
end
- def test_table_name_delegates_to_klass
- relation = Relation.new(FakeKlass.new("posts"), :b, Post.predicate_builder)
- assert_equal "posts", relation.table_name
- end
-
def test_scope_for_create
relation = Relation.new(FakeKlass, :b, nil)
assert_equal({}, relation.scope_for_create)
@@ -101,28 +80,27 @@ module ActiveRecord
def test_create_with_value
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
- hash = { hello: "world" }
- relation.create_with_value = hash
- assert_equal hash, relation.scope_for_create
+ relation.create_with_value = { hello: "world" }
+ assert_equal({ "hello" => "world" }, relation.scope_for_create)
end
def test_create_with_value_with_wheres
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
- relation.where! relation.table[:id].eq(10)
+ assert_equal({}, relation.scope_for_create)
+
+ relation.where!(id: 10)
+ assert_equal({ "id" => 10 }, relation.scope_for_create)
+
relation.create_with_value = { hello: "world" }
- assert_equal({ hello: "world", id: 10 }, relation.scope_for_create)
+ assert_equal({ "hello" => "world", "id" => 10 }, relation.scope_for_create)
end
- # FIXME: is this really wanted or expected behavior?
- def test_scope_for_create_is_cached
+ def test_empty_scope
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
- assert_equal({}, relation.scope_for_create)
-
- relation.where! relation.table[:id].eq(10)
- assert_equal({}, relation.scope_for_create)
+ assert relation.empty_scope?
- relation.create_with_value = { hello: "world" }
- assert_equal({}, relation.scope_for_create)
+ relation.merge!(relation)
+ assert relation.empty_scope?
end
def test_bad_constants_raise_errors
@@ -210,7 +188,7 @@ module ActiveRecord
relation = Relation.new(klass, :b, nil)
relation.merge!(where: ["foo = ?", "bar"])
- assert_equal Relation::WhereClause.new(["foo = bar"], []), relation.where_clause
+ assert_equal Relation::WhereClause.new(["foo = bar"]), relation.where_clause
end
def test_merging_readonly_false
@@ -224,7 +202,26 @@ module ActiveRecord
def test_relation_merging_with_merged_joins_as_symbols
special_comments_with_ratings = SpecialComment.joins(:ratings)
posts_with_special_comments_with_ratings = Post.group("posts.id").joins(:special_comments).merge(special_comments_with_ratings)
- assert_equal({ 2 => 1, 4 => 3, 5 => 1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count)
+ assert_equal({ 4 => 2 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count)
+ end
+
+ def test_relation_merging_with_merged_symbol_joins_keeps_inner_joins
+ queries = capture_sql { Author.joins(:posts).merge(Post.joins(:comments)).to_a }
+
+ nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
+ assert_equal 2, nb_inner_join, "Wrong amount of INNER JOIN in query"
+ assert queries.none? { |sql| /LEFT\s+(OUTER)?\s+JOIN/i.match?(sql) }, "Shouldn't have any LEFT JOIN in query"
+ end
+
+ def test_relation_merging_with_merged_symbol_joins_has_correct_size_and_count
+ # Has one entry per comment
+ merged_authors_with_commented_posts_relation = Author.joins(:posts).merge(Post.joins(:comments))
+
+ post_ids_with_author = Post.joins(:author).pluck(:id)
+ manual_comments_on_post_that_have_author = Comment.where(post_id: post_ids_with_author).pluck(:id)
+
+ assert_equal manual_comments_on_post_that_have_author.size, merged_authors_with_commented_posts_relation.count
+ assert_equal manual_comments_on_post_that_have_author.size, merged_authors_with_commented_posts_relation.to_a.size
end
def test_relation_merging_with_joins_as_join_dependency_pick_proper_parent
@@ -277,18 +274,32 @@ module ActiveRecord
assert_equal({ 2 => 1, 4 => 3, 5 => 1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count)
end
+ def test_relation_merging_keeps_joining_order
+ authors = Author.where(id: 1)
+ posts = Post.joins(:author).merge(authors)
+ comments = Comment.joins(:post).merge(posts)
+ ratings = Rating.joins(:comment).merge(comments)
+
+ assert_equal 3, ratings.count
+ end
+
class EnsureRoundTripTypeCasting < ActiveRecord::Type::Value
def type
:string
end
+ def cast(value)
+ raise value unless value == "value from user"
+ "cast value"
+ end
+
def deserialize(value)
raise value unless value == "type cast for database"
"type cast from database"
end
def serialize(value)
- raise value unless value == "value from user"
+ raise value unless value == "cast value"
"type cast for database"
end
end