Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Expand order(:symbol) to "table".symbol to prevent broken queries on PG.

Fixes #9275.

When `#order` is called with a Symbol this patch will prepend the quoted_table_name.
Before the postgresql adapter failed to build queries containg a join and an order
with a symbol.

This expansion happens for all adapters.
  • Loading branch information...
commit e0356990856abc9a84e6e038e7b06e2931502728 1 parent 45321a6
@senny senny authored
9 activerecord/CHANGELOG.md
@@ -1,5 +1,14 @@
## Rails 4.0.0 (unreleased) ##
+* Fix when performing an ordered join query. The bug only
+ affected queries where the order was given with a symbol.
+ Fixes #9275.
+
+ Example:
+
+ # This will expand the order :name to "authors".name.
+ Author.joins(:books).where('books.published = 1').order(:name)
+
* Fixing issue #8345. Now throwing an error when one attempts to touch a
new object that has not yet been persisted. For instance:
View
5 activerecord/lib/active_record/relation/query_methods.rb
@@ -285,6 +285,11 @@ def order!(*args) # :nodoc:
references.map! { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 }.compact!
references!(references) if references.any?
+ # if a symbol is given we prepend the quoted table name
+ args = args.map { |arg|
+ arg.is_a?(Symbol) ? "#{quoted_table_name}.#{arg} ASC" : arg
@tenderlove Owner

Hi, I'd like to avoid slapping together SQL string literals if possible please. If you're writing SQL literal strings, please think twice.

I've removed the SQL literal here: d345ed4

@senny Owner
senny added a note

@tenderlove Thanks for the fix and letting me know. :heart:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ }
+
self.order_values = args + self.order_values
self
end
View
7 activerecord/test/cases/associations/eager_test.rb
@@ -218,7 +218,7 @@ def test_finding_with_includes_on_belongs_to_association_with_same_include_inclu
def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
post = posts(:welcome)
post.update!(author: nil)
- post = assert_queries(1) { Post.all.merge!(includes: {author_with_address: :author_address}).find(post.id) }
+ post = assert_queries(1) { Post.all.merge!(includes: {author_with_address: :author_address}).find(post.id) }
# find the post, then find the author which is null so no query for the author or address
assert_no_queries do
assert_equal nil, post.author_with_address
@@ -1173,4 +1173,9 @@ def test_deep_including_through_habtm
assert_no_queries { assert_equal 2, author.comments_with_order_and_conditions.size }
assert_no_queries { assert_equal 5, author.posts.size, "should not cache a subset of the association" }
end
+
+ test "works in combination with order(:symbol)" do
+ author = Author.includes(:posts).references(:posts).order(:name).where('posts.title IS NOT NULL').first
+ assert_equal authors(:bob), author
+ end
end
View
17 activerecord/test/cases/relation_test.rb
@@ -180,19 +180,32 @@ def test_references_values_dont_duplicate
class RelationMutationTest < ActiveSupport::TestCase
class FakeKlass < Struct.new(:table_name, :name)
+ def quoted_table_name
+ %{"#{table_name}"}
+ end
end
def relation
- @relation ||= Relation.new FakeKlass, :b
+ @relation ||= Relation.new FakeKlass.new('posts'), :b
end
- (Relation::MULTI_VALUE_METHODS - [:references, :extending]).each do |method|
+ (Relation::MULTI_VALUE_METHODS - [:references, :extending, :order]).each do |method|
test "##{method}!" do
assert relation.public_send("#{method}!", :foo).equal?(relation)
assert_equal [:foo], relation.public_send("#{method}_values")
end
end
+ test "#order!" do
+ assert relation.order!('name ASC').equal?(relation)
+ assert_equal ['name ASC'], relation.order_values
+ end
+
+ test "#order! with symbol prepends the table name" do
+ assert relation.order!(:name).equal?(relation)
+ assert_equal ['"posts".name ASC'], relation.order_values
+ end
+
test '#references!' do
assert relation.references!(:foo).equal?(relation)
assert relation.references_values.include?('foo')
Please sign in to comment.
Something went wrong with that request. Please try again.