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.

Merge :joins instead of clobbering them

#501

The attached patch enhances with_scope, etc. by enabling the merging of :joins specified either in the new style or old style sql fragments.

1. Where both are new style they are merged in the same manner as :include.

2. Where both are strings they are concatenated together.

3. Where one is a new style and the other is a string then the new style :joins is converted to an sql fragment and then concatenated with the other sql fragment.

4. construct_finder_sql adds the DISTINCT sql keyword to limit the number of rows returned as joins generally multiply the number of rows returned - this is an enhancement to the change in ticket #46 with_scope clobbers result attributes when :joins key is specified.

5. Tests have been added and all tests pass

6. Documentation has been updated to reflect that :joins as well as :include and :conditions are merged.

Reported by Andrew White · June 27th, 2008 @ 05:35 PM

State: resolved
Milestone: none
Assigned to: Jeremy Kemper Jeremy Kemper
Importance: Low

Activity

  1. Jeremy Kemper
    Jeremy Kemper
    • State changed from new to open
    • Milestone cleared.
    • Assigned user set to Jeremy Kemper

    Hey Andrew, nice patch. Could you explain adding DISTINCT to the finder sql?

    June 28th, 2008 @ 02:06 AM

  2. Andrew White
    Andrew White

    The DISTINCT is for when you're joining a has_many or habtm association - e.g. a post joined with comments:

    Post.find(:all, :joins => :comments, :conditions => 'comments.approved = 1')

    Ticket #46 with_scope clobbers result attributes when :joins key is specified scopes the select to the posts table (i.e. 'posts.*') but if a post has more than one comment approved you'll get back duplicate post instances. Adding 'DISTINCT posts.*' eliminates these duplicate records.

    There may by some circumstances where you don't want the DISTINCT in which case you can override it with :select, but the majority of cases would need it so that's why I've added it by default.

    June 28th, 2008 @ 06:22 AM

  3. Pratik
    Pratik

    I agree with Andrew that DISTINCT would make sense in a lot of cases. However, using DISTINCT can easily become a performance problem if the query has LIMIT, ORDER BY etc. Apart from that, it'll also change the existing behavior, which can possibly break some stuff. So I'm not sure if it'll be a sensible default or not.

    How about adding :distinct option to find ?

    Interested in hearing more thoughts on this.

    July 12th, 2008 @ 03:06 AM

  4. Andrew White
    Andrew White

    We could do a :distinct option and then set it true by default if we detect a has_many or habtm join being specified. This would only be when using the new style join syntax limiting any backward compatibility problems.

    July 16th, 2008 @ 11:31 AM

  5. Pratik
    Pratik

    I'm not convinced about setting it to default.

    July 16th, 2008 @ 11:34 AM

  6. Andrew White
    Andrew White

    If we don't set it as the default when the destination join has more than one matching row then we'll get duplicate instances of the parent. I can't think of a use case where this would correct or useful.

    However looking at count it sets :distinct => true for :include and leaves it out when using :joins, so I guess the precedent is to make the developer specify it.

    July 16th, 2008 @ 12:13 PM

  7. Andrew White
    Andrew White

    I've modified the patch to only merge :joins and not bother about making the select statement distinct. I'll create a separate ticket and patch for adding a distinct option to find.

    One question regarding the distinct option for find - which of the following would be better:

    Post.find :all, :distinct => true, :joins => :comments

    or

    Post.find :distinct, :joins => :comments

    July 29th, 2008 @ 03:14 PM

  8. Pratik
    Pratik

    "Post.find :all, :distinct => true, :joins => :comments"

    We can always do "Post.all, :distinct => true, :joins => :comments" once that's done.

    July 29th, 2008 @ 03:18 PM

  9. Jeremy Kemper
    Jeremy Kemper

    The patch looks good. Could you rebase against master?

    August 28th, 2008 @ 07:38 AM

  10. Andrew White
    Andrew White

    Updated patch rebased against master

    August 28th, 2008 @ 05:06 PM

  11. Repository
    Repository
    • State changed from open to resolved

    (from [db22c89543f45d7f27847003af949afa21cb6fa1]) Merge scoped :joins together instead of overwriting them. May expose scoping bugs in your code!

    [#501 Merge :joins instead of clobbering them state:resolved]

    Signed-off-by: Jeremy Kemper jeremy@bitsweat.net http://github.com/rails/rails/co...

    August 28th, 2008 @ 08:09 PM

  12. David Stevenson
    David Stevenson
    • Tag changed from activerecord, enhancement, joins, patch to activerecord, enhancement, joins, patch

    Wait!

    Is there a reason merge_joins isn't used inside of with_scope to merge joins there too?

    Without it in that location, it's not possible to chain multiple named_scopes that have joins.

    September 18th, 2008 @ 07:31 PM

  13. Andrew White
    Andrew White

    It is used in with_scope - chaining multiple named scopes works fine for me. Do you have an example that doesn't work?

    September 19th, 2008 @ 06:01 AM

  14. Yi Lin
    Yi Lin

    What happened to the patch for DISTINCT to work?

    March 5th, 2009 @ 03:28 AM

  15. Ryan Bigg
    Ryan Bigg
    • Tag cleared.
    • Importance changed from to Low

    Automatic cleanup of spam.

    October 9th, 2010 @ 10:02 PM