Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

named_scope with :joins does not work properly through HABTM associations

#1695

This is using Rails 2.2.2 on OS X Leopard.

When calling a named_scope method on an array returned via HABTM association, where the named_scope has additional :joins, the :select condition of the named_scope is ignored and the return value contains the :join'd object instead of the model object.

In an example where:

  • Car has_and_belongs_to_many Parts
  • Part belongs_to PartType

..if we have a named_scope :ordered defined on Part, which :joins to :part_type for part of its condition, calling @car.parts.ordered will return an array of PartTypes instead of Parts.

I've written up a more complete example and pasted it here: http://pastie.org/352661

Reported by Alex Levy · January 5th, 2009 @ 05:17 AM

State: stale
Milestone: 3.x
Assigned to: Pratik Pratik
Importance: none

Activity

  1. Pascal Ehlert
    Pascal Ehlert

    I've had a quick look at this and the problem is that you have ambiguous column names and the select options from your scope are overridden by the association's select options which are constructed like this:

    
    @reflection.options[:select] || "*"
    

    Despite the problem with the ignored scope, what I found weird is that we are using "SELECT *" there instead of a specific select with the qualified table name.

    This is apparently done to allow additional attributes on the join table to be selected as well, which I find rather confusing and which is probably a relic from those ancient "push_with_attributes" times:

    
    def test_additional_columns_from_join_table
      assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on.to_date
    end
    

    A first proposal of a fix would be to replace the above default SELECT statement generation by the following, which would not yet solve the scope issues but is more safe anyway:

    
    @reflection.options[:select] || "#{@reflection.quoted_table_name}.*"
    

    I'll see if I can work out a patch for the scope stuff while waiting for your comments.

    January 5th, 2009 @ 01:53 PM

  2. Alex Levy
    Alex Levy

    The only ambiguous column being pulled back is "id", and I think the behavior in question is precisely due to what you identified -- it's using "SELECT " instead of "SELECT parts.", and that is causing the wrong objects to come back. I'm glad you were able to pinpoint it, because I'm new to the Rails stack and was struggling to figure out where this was getting overwritten.

    If I make that one change -- line 16 of has_and_belongs_to_many_association.rb -- the test shown in my pasted example will pass. That change also solves the problem I'm having in my real application, which prompted me to investigate in the first place.

    So, thank you! I'm satisfied that we've resolved the issue, provided that change makes its way in.

    January 6th, 2009 @ 07:37 AM

  3. Pratik
    Pratik
    • State changed from new to incomplete
    • Assigned user set to Pratik

    Is this still a problem ? Can we please have a failing test case ?

    http://guides.rails.info/contrib... should be helpful if you haven't done it before!

    Thanks.

    March 12th, 2009 @ 03:50 PM

  4. Alex Levy
    Alex Levy

    I included a link to a failing test in my original report: http://pastie.org/352661

    March 12th, 2009 @ 04:34 PM

  5. Pratik
  6. Pratik
  7. Alex Levy
    Alex Levy

    I've merged the earlier-linked failing test into the AR test suite and attached the diff here.

    March 13th, 2009 @ 03:37 AM

  8. Mark Lubarsky
    Mark Lubarsky

    I am running into a similar issue, where my :select on the named_scope is ignored. It happens regardless of whether the main association has :select with specific fields or not. Could you please advise on whether the fix for this is coming or there is another workaround?

    September 11th, 2009 @ 07:33 PM

  9. marli
    marli

    I am also having a similar problem in rails 2.3.2 and 2.3.4

    October 15th, 2009 @ 08:30 PM

  10. klochner
    klochner

    Ditto on having my :select ignored by named_scope in a habtm relation, e.g.,:

    foo.bars.my_scope

    I end up with garbage records because of column name collision on the join.

    February 9th, 2010 @ 07:57 PM

  11. Tanel Suurhans
    Tanel Suurhans

    Seems like this bug surfaces even without :select conditions.
    For example in a case like this:

    class Key < ActiveRecord::Base
      has_many :values
    end
    
    class Value < ActiveRecord::Base
      belongs_to :key
      default_scope :joins => :key, :order => "keys.name"
    end
    
    class Foo < ActiveRecord::Base
      has_and_belongs_to_many :values
    end
    

    Now when i access Foo.first.values it will do a "SELECT *" across 2 joins which results in "keys" table id-s shadowing "values" table id-s.

    SELECT * FROM "values" INNER JOIN "keys" ON "keys".id = "values".key_id INNER JOIN "foos_values" ON "values".id = "foos_values".value_id WHERE ("foos_values".foo_id = 1) ORDER BY keys.name;
    

    Right off the bat i would say that "SELECT 'values'.*" i.e the association endpoint table name would solve this issue, although i have no idea what else would break in result of this.

    March 1st, 2010 @ 03:46 PM

  12. Rudolf Gavlas
    Rudolf Gavlas

    Since the 'default_select' method used in 'construct_finder_sql' in active_record/base.rb uses the '' as last resort, there is IMO no need to default to '' in has_and_belongs_to_many_association.rb. The attached patch fixed my problems with named_scopes and habtm associations.

    April 10th, 2010 @ 03:08 AM

  13. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.x to 3.x

    May 4th, 2010 @ 06:48 PM

  14. rails
    rails
    • Tag changed from 2.2.2, habtm, named_scope to 222, habtm, named_scope
    • State changed from incomplete to open
    • Importance changed from to

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

    February 26th, 2011 @ 12:00 AM

  15. rails
    rails
    • State changed from open to stale

    February 26th, 2011 @ 12:00 AM

  16. claw
    claw

    I appear to be hitting this issue as well in 2.3.9 on OS X Snow Leopard. I have discovered a workaround that appears to work though. Using the model names in the original report (Car HABTM Parts; Parts belongs_to PartType), you can redefine the ordered named_scope like so:

    class Parts < ActiveRecord::Base
      has_and_belongs_to_many :cars
      belongs_to :part_type
    
      # Workaround for named_scope :ordered, :conditions => ..., :joins => :part_type
      def self.ordered
        scoped(:conditions => ..., :joins => :part_type)
      end
    end
    

    This workaround appears to correctly put the table name in the SELECT query (e.g., SELECT parts.*). Looking at the named_scope code in ActiveRecord though, I don't see why scoped should behave any differently, since they both appear to ultimately end up calling ActiveRecord::NamedScope::Scope.new(self, scope, &block).

    I see the milestone for this issue was moved from 2.x to 3.x; is there any chance we could see the fix for this in 2.x?

    March 24th, 2011 @ 11:02 PM