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.

Allow ActiveRecord's find to take a Range

#3419

This patch will allow you to pass a Range of IDs to find:

Person.find(1..5)
Person.find(1, 3..8)

Reported by Mike Breen · October 24th, 2009 @ 05:58 PM

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

Activity

  1. Mislav
    Mislav

    This line doesn't look right at all:

    ids.inject([]) {|m, o| m << (o.kind_of?(Range) ? o.to_a : o)}.flatten.compact.uniq
    

    And why special-case Ranges? Why not accept anything that has a to_a method?

    October 24th, 2009 @ 07:02 PM

  2. CancelProfileIsBroken
    CancelProfileIsBroken

    We could almost do

    ids = ids.map(&:to_a).flatten.compact.uniq
    

    The problem is that under 1.9, Fixnum doesn't have a to_a. So the code is more about special-casing Fixnum. Not clear to me that picking up everything that has to_a is the right answer - we need a specific thing, an array of integers, no?

    October 24th, 2009 @ 07:49 PM

  3. Mike Breen
    Mike Breen

    @Mislav - Thanks for the feedback. I guess it would be better to handle anything that has a to_a:

    ids.inject([]) {|m,o| m << (o.respond_to? :to_a ? o.to_a : o)}.flatten.compact.uniq
    

    Other than the special case for Ranges what else doesn't look right about the line?

    October 24th, 2009 @ 08:13 PM

  4. MatthewRudy
    MatthewRudy

    in 1.9 we still get;

    Array(2)    # => [2]
    Array(4..6) # => [4, 5, 6]
    
    so
    ids.map{|id| Array(id)}.flatten.compact.uniq
    

    October 25th, 2009 @ 09:46 AM

  5. Mike Breen
    Mike Breen

    @MatthewRudy - that's much nicer. Thanks!

    I've attached an updated patch with Matthew's changes.

    October 25th, 2009 @ 11:16 AM

  6. Matt Jones
    Matt Jones

    This seems like a bad idea - what about people who are using non-numeric primary keys (GUIDs, for instance)?

    I'm also not clear on what the use case for this is - is it really that much more effort to to_a the range yourself?

    October 26th, 2009 @ 03:29 AM

  7. Mike Breen
    Mike Breen

    @Matt Jones - Thanks for the feedback.

    This seems like a bad idea - what about people who are using non-numeric primary keys (GUIDs, for instance)?

    You're correct, this is probably not very useful for people using non-numeric primary keys. I guess my only answer is that they shouldn't use Ranges in their finds. Adding this won't change SOP for those using non-numeric primary keys and will only be a benefit to those who stick with the Rails conventions.

    I'm also not clear on what the use case for this is - is it really that much more effort to to_a the range yourself?

    That's pretty much what I do now >> Person.find(1, (4..7).to_a) and I thought that if I'm a using a Range in my find then someone else may find it useful also. But the case may be that this does not belong in Core and is only a very specific use case.

    October 26th, 2009 @ 01:56 PM

  8. Mike Breen
    Mike Breen
    • Tag changed from 2, 2-3-stable, active_record, find, patch to 2-3-stable, active_record, find, patch

    October 26th, 2009 @ 08:50 PM

  9. Dan Pickett
    Dan Pickett
    • Tag changed from 2-3-stable, active_record, find, patch to 2-3-stable, active_record, bugmash, find, patch

    May 9th, 2010 @ 05:51 PM

  10. Rizwan Reza
    Rizwan Reza
    • Milestone set to 2.3.6
    • State changed from new to open

    May 15th, 2010 @ 03:57 PM

  11. Rizwan Reza
    Rizwan Reza

    +1 verified

    I have attached a patch for Rails 3 as well.

    May 15th, 2010 @ 04:33 PM

  12. Rizwan Reza
  13. Rizwan Reza
    Rizwan Reza
    • Milestone cleared.
    • Tag changed from 2-3-stable, active_record, bugmash, find, patch to 2-3-stable, 3.0, active_record, bugmash, bugmash-review, find, patch

    May 15th, 2010 @ 04:50 PM

  14. Jeremy Kemper
    Jeremy Kemper

    Need to use Array.wrap() since Array() complains about destructuring strings on 1.8.8. (require 'active_support/core_ext/array/wrap)

    May 15th, 2010 @ 05:26 PM

  15. Rizwan Reza
    Rizwan Reza
    • Assigned user set to Jeremy Kemper

    Done.

    May 15th, 2010 @ 05:33 PM

  16. Jeremy Kemper
    Jeremy Kemper

    Also, is flatten needed? That could be

    ids.sum { |id| Array.wrap(id) }.uniq
    

    May 15th, 2010 @ 05:37 PM

  17. Mike Breen
    Mike Breen

    Updated the 2.3x patch with Jeremy's recommendations.

    May 15th, 2010 @ 05:40 PM

  18. Rizwan Reza
    Rizwan Reza

    Mike, tests fail on this one, you will need to change it like this:

    ids = ids.map {|id| Array.wrap(id)}.flatten.compact.uniq

    May 15th, 2010 @ 05:49 PM

  19. Jeremy Kemper
    Jeremy Kemper

    Reading back up, this means find(1, 5..10000) will generate a query with 9996 ids. This should use normal range query mapping instead.

    May 15th, 2010 @ 05:52 PM

  20. Jeremy Kemper
    Jeremy Kemper
    • State changed from open to wontfix

    May 15th, 2010 @ 05:52 PM

  21. Rizwan Reza
    Rizwan Reza
    • Tag changed from 2-3-stable, 3.0, active_record, bugmash, bugmash-review, find, patch to 2-3-stable, 3.0, active_record, find, patch

    May 15th, 2010 @ 06:36 PM