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.

Using :joins when calling first on an association ignores joins

#5951

Running the following test:

  def test_using_joins_on_many_association_with_has_one_join
    parrot = Parrot.create!(:name => "Petal")
    pirate_with_a_ship = Pirate.create!(:catchphrase => "Where is Seaman Staines?")
    ship = Ship.create!(:name => "Black pig", :pirate => pirate_with_a_ship)
    pirate_without_a_ship = Pirate.create!(:catchphrase => "Argh, I better run from the captain!")
    parrot.pirates << pirate_without_a_ship
    parrot.pirates << pirate_with_a_ship
    assert_equal pirate_with_a_ship, parrot.pirates.all(:joins => :ship, :order => "catchphrase", :limit => 1).first
    assert_equal pirate_with_a_ship, parrot.pirates.first(:joins => :ship, :order => "catchphrase")
  end

The first query using the .all, correctly applies the :joins and :order clause, whereas the second query using .first only applies the :order.

As such, the pirate returned from the second query is the wrong pirate.

SELECT "pirates".* FROM "pirates" INNER JOIN "parrots_pirates" ON "pirates".id = "parrots_pirates".pirate_id 
INNER JOIN "ships" ON ships.pirate_id = pirates.id WHERE ("parrots_pirates".parrot_id = 1 ) 
ORDER BY catchphrase LIMIT 1
SELECT * FROM "pirates" INNER JOIN "parrots_pirates" ON "pirates".id = "parrots_pirates".pirate_id 
WHERE ("parrots_pirates".parrot_id = 1 ) ORDER BY catchphrase LIMIT 1

Is the output from debug.log showing the SQL ran by both queries.

Reported by omarqureshi · November 11th, 2010 @ 09:34 AM

State: stale
Milestone: 3.x
Assigned to: Aaron Patterson Aaron Patterson
Importance: Low

Activity

  1. Neeraj Singh
    Neeraj Singh
    • State changed from new to open
    • Milestone set to 3.x
    • Importance changed from to Low

    The author says that this is an issue in 2.3-stable . I can reproduce it in rails edge too.

    November 15th, 2010 @ 09:26 PM

  2. Neeraj Singh
    Neeraj Singh
    • Assigned user set to Aaron Patterson
    • Tag changed from 2-3-stable, 2.3.10, activerecord, associations, first to 2-3-stable, 2.3.10, activerecord, associations, first, rails3

    November 16th, 2010 @ 08:31 PM

  3. Neeraj Singh
    Neeraj Singh

    I spent some time (infact some good time) looking at it.

    The path followed by

    parrot.pirates.all(:joins => :ship)
    

    is

    association_collection -> method_missing

    and then call

    Pirate.with_scope(@scope) do
    args # {:joins => :capital} end

    straight forward and simple. However notice that it does select pirates.*

    In the case of

    parrot.pirates.first(:joins => :ship, :order => "catchphrase")
    

    it hits

    association_collection => first
    association_collection => find

    there method construct_find_options is called which takes the options as input. However it does not use the input and clobbers the options[:joins] and
    {:joins => :ship } is lost forever.

    The fix of that is something like this https://gist.github.com/703946 .That takes care of building the joins. However the sql produced is

    select * from pirates
    

    Any attempt to have

    select pirates.* from
    

    is making other test fail which rely on getting the join attribute . Remember we are dealing with habtm.

    November 17th, 2010 @ 07:55 PM

  4. omarqureshi
    omarqureshi

    Sorry, have come back to this after a long hiatus.

    Isn't this what is required? The problem is the joins, not the select clause and infact, is probably preferable to have instead of table. since it is a join and a :select has not been specified.

    January 16th, 2011 @ 01:04 AM

  5. rails
    rails
    • Tag changed from 2-3-stable, 2.3.10, activerecord, associations, first, rails3 to 2-3-stable, 2310, activerecord, associations, first, rails3

    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.

    April 19th, 2011 @ 01:00 AM

  6. rails
    rails
    • State changed from open to stale

    April 19th, 2011 @ 01:00 AM