1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
# frozen_string_literal: true
require "cases/helper"
require "models/author"
require "models/comment"
require "models/developer"
require "models/computer"
require "models/post"
require "models/project"
require "models/rating"
class RelationMergingTest < ActiveRecord::TestCase
fixtures :developers, :comments, :authors, :author_addresses, :posts
def test_relation_merging
devs = Developer.where("salary >= 80000").merge(Developer.limit(2)).merge(Developer.order("id ASC").where("id < 3"))
assert_equal [developers(:david), developers(:jamis)], devs.to_a
dev_with_count = Developer.limit(1).merge(Developer.order("id DESC")).merge(Developer.select("developers.*"))
assert_equal [developers(:poor_jamis)], dev_with_count.to_a
end
def test_relation_to_sql
post = Post.first
sql = post.comments.to_sql
assert_match(/.?post_id.? = #{post.id}\z/i, sql)
end
def test_relation_merging_with_arel_equalities_keeps_last_equality
devs = Developer.where(Developer.arel_table[:salary].eq(80000)).merge(
Developer.where(Developer.arel_table[:salary].eq(9000))
)
assert_equal [developers(:poor_jamis)], devs.to_a
end
def test_relation_merging_with_arel_equalities_keeps_last_equality_with_non_attribute_left_hand
salary_attr = Developer.arel_table[:salary]
devs = Developer.where(
Arel::Nodes::NamedFunction.new("abs", [salary_attr]).eq(80000)
).merge(
Developer.where(
Arel::Nodes::NamedFunction.new("abs", [salary_attr]).eq(9000)
)
)
assert_equal [developers(:poor_jamis)], devs.to_a
end
def test_relation_merging_with_eager_load
relations = []
relations << Post.order("comments.id DESC").merge(Post.eager_load(:last_comment)).merge(Post.all)
relations << Post.eager_load(:last_comment).merge(Post.order("comments.id DESC")).merge(Post.all)
relations.each do |posts|
post = posts.find { |p| p.id == 1 }
assert_equal Post.find(1).last_comment, post.last_comment
end
end
def test_relation_merging_with_locks
devs = Developer.lock.where("salary >= 80000").order("id DESC").merge(Developer.limit(2))
assert_predicate devs, :locked?
end
def test_relation_merging_with_preload
[Post.all.merge(Post.preload(:author)), Post.preload(:author).merge(Post.all)].each do |posts|
assert_queries(2) { assert posts.first.author }
end
end
def test_relation_merging_with_joins
comments = Comment.joins(:post).where(body: "Thank you for the welcome").merge(Post.where(body: "Such a lovely day"))
assert_equal 1, comments.count
end
def test_relation_merging_with_left_outer_joins
comments = Comment.joins(:post).where(body: "Thank you for the welcome").merge(Post.left_outer_joins(:author).where(body: "Such a lovely day"))
assert_equal 1, comments.count
end
def test_relation_merging_with_skip_query_cache
assert_equal Post.all.merge(Post.all.skip_query_cache!).skip_query_cache_value, true
end
def test_relation_merging_with_association
assert_queries(2) do # one for loading post, and another one merged query
post = Post.where(body: "Such a lovely day").first
comments = Comment.where(body: "Thank you for the welcome").merge(post.comments)
assert_equal 1, comments.count
end
end
test "merge collapses wheres from the LHS only" do
left = Post.where(title: "omg").where(comments_count: 1)
right = Post.where(title: "wtf").where(title: "bbq")
merged = left.merge(right)
assert_not_includes merged.to_sql, "omg"
assert_includes merged.to_sql, "wtf"
assert_includes merged.to_sql, "bbq"
end
def test_merging_reorders_bind_params
post = Post.first
right = Post.where(id: 1)
left = Post.where(title: post.title)
merged = left.merge(right)
assert_equal post, merged.first
end
def test_merging_compares_symbols_and_strings_as_equal
post = PostThatLoadsCommentsInAnAfterSaveHook.create!(title: "First Post", body: "Blah blah blah.")
assert_equal "First comment!", post.comments.where(body: "First comment!").first_or_create.body
end
def test_merging_with_from_clause
relation = Post.all
assert_empty relation.from_clause
relation = relation.merge(Post.from("posts"))
assert_not_empty relation.from_clause
end
def test_merging_with_from_clause_on_different_class
assert Comment.joins(:post).merge(Post.from("posts")).first
end
def test_merging_with_order_with_binds
relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
assert_equal ["title LIKE '%suffix'"], relation.order_values
end
def test_merging_with_order_without_binds
relation = Post.all.merge(Post.order(Arel.sql("title LIKE '%?'")))
assert_equal ["title LIKE '%?'"], relation.order_values
end
def test_merging_annotations_respects_merge_order
assert_sql(%r{/\* foo \*/ /\* bar \*/}) do
Post.annotate("foo").merge(Post.annotate("bar")).first
end
assert_sql(%r{/\* bar \*/ /\* foo \*/}) do
Post.annotate("bar").merge(Post.annotate("foo")).first
end
assert_sql(%r{/\* foo \*/ /\* bar \*/ /\* baz \*/ /\* qux \*/}) do
Post.annotate("foo").annotate("bar").merge(Post.annotate("baz").annotate("qux")).first
end
end
end
class MergingDifferentRelationsTest < ActiveRecord::TestCase
fixtures :posts, :authors, :author_addresses, :developers
test "merging where relations" do
hello_by_bob = Post.where(body: "hello").joins(:author).
merge(Author.where(name: "Bob")).order("posts.id").pluck("posts.id")
assert_equal [posts(:misc_by_bob).id,
posts(:other_by_bob).id], hello_by_bob
end
test "merging order relations" do
posts_by_author_name = Post.limit(3).joins(:author).
merge(Author.order(:name)).pluck("authors.name")
assert_equal ["Bob", "Bob", "David"], posts_by_author_name
posts_by_author_name = Post.limit(3).joins(:author).
merge(Author.order("name")).pluck("authors.name")
assert_equal ["Bob", "Bob", "David"], posts_by_author_name
end
test "merging order relations (using a hash argument)" do
posts_by_author_name = Post.limit(4).joins(:author).
merge(Author.order(name: :desc)).pluck("authors.name")
assert_equal ["Mary", "Mary", "Mary", "David"], posts_by_author_name
end
test "relation merging (using a proc argument)" do
dev = Developer.where(name: "Jamis").first
comment_1 = dev.comments.create!(body: "I'm Jamis", post: Post.first)
rating_1 = comment_1.ratings.create!
comment_2 = dev.comments.create!(body: "I'm John", post: Post.first)
comment_2.ratings.create!
assert_equal dev.ratings, [rating_1]
end
end
|