Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

ActiveRecord has_many :through :order is broken when using includes #8663

Closed
elado opened this Issue · 9 comments

6 participants

@elado

Rails 3.2.9:

When using order option on has_many :through, and querying the object with includes it tries to sort the association table instead of the associated records.

Models:

class Category < ActiveRecord::Base
  attr_accessible :name

  has_many :product_categories
  has_many :products, through: :product_categories
end

class Product < ActiveRecord::Base
  attr_accessible :name

  has_many :product_categories
  has_many :categories, through: :product_categories, order: 'name'
end

class ProductCategory < ActiveRecord::Base
  belongs_to :product
  belongs_to :category
end

Notice the order on Product has_many :categories

This is fine:

> Product.first.categories

  Product Load (0.1ms)  SELECT "products".* FROM "products" LIMIT 1
  Category Load (0.1ms)  SELECT "categories".* FROM "categories" INNER JOIN "product_categories" ON "categories"."id" = "product_categories"."category_id" WHERE "product_categories"."product_id" = 1 ORDER BY name

This is not:

> Product.includes(:categories)

  Product Load (0.1ms)  SELECT "products".* FROM "products" 
  ProductCategory Load (0.1ms)  SELECT "product_categories".* FROM "product_categories" WHERE "product_categories"."product_id" IN (1) ORDER BY name
SQLite3::SQLException: no such column: name: SELECT "product_categories".* FROM "product_categories"  WHERE "product_categories"."product_id" IN (1) ORDER BY name
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: name: SELECT "product_categories".* FROM "product_categories"  WHERE "product_categories"."product_id" IN (1) ORDER BY name

If the order is removed it works fine.

(Tested on sqlite3 and mysql)

@rrouse

Here is an app that reproduces it along with the stack trace and Arel AST for the queries.

https://github.com/rrouse/testrepo

@senny
Owner

I confirmed this issue against master and it is still happening. The problem lies in the preloader and a PR is in the works.

@senny senny referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@senny senny referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@senny senny closed this issue from a commit
@senny senny don't apply invalid ordering when preloading hmt associations.
closes #8663.

When preloading a hmt association there two possible scenarios:

1.) preload with 2 queries: first hm association, then hmt with id IN ()
2.) preload with join: hmt association is loaded with a join on the hm association

The bug was happening in scenario 1.) with a normal order clause on the hmt association.
The ordering was also applied when loading the hm association, which resulted in the error.

This patch only applies the ordering the the hm-relation if we are performing a join (2).
Otherwise the order will only appear in the second query (1).
4ef75b6
@senny senny closed this in 4ef75b6
@grosser

any idea how to patch that on rails 3 ?

@edsinclair edsinclair referenced this issue from a commit in edsinclair/rails
@edsinclair edsinclair update ActiveRecord::Associations::Preloader::ThroughAssociation
Set through_options[:include] even if options[:conditions] is not defined.
30775b6
@edsinclair

Previous fix broke tests and was too broad. Updated fix with a proper test:
edsinclair@66163ab

@edsinclair edsinclair referenced this issue from a commit in edsinclair/rails
@edsinclair edsinclair Fix behavior of a table qualified :order option on a
through association with a :source option specified
66163ab
@senny
Owner

@edsinclair did you submit a PR? If not, please do so.

@edsinclair

@senny I'd be glad to, but it I'm not quite sure how to go about submitting a PR for something that is only applicable to the rails/3-2-stable branch or even if those are accepted?

@paulgid

I applied the patch above and it didn't seem to remove the fault. Am I missing something? I'm using Rails 3.2.14

@edsinclair

@paulgid Are you using the :source option?

https://github.com/edsinclair/rails/blob/b21066871f085bc5f8c980d613986c64ec64a56f/activerecord/lib/active_record/associations/preloader/through_association.rb#L63

This patch merely restores the Rails 2 behavior which enabled includes to work for through associations as long as you specified the :source option. Hope that helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.