Bug #21654
openSet#new calls extra methods compared to previous versions
Description
I'm trying to test Ruby 3.5.0 with our Rails application and we've found that Set.new is now causing extra database queries to happen.
The changes in d4020dd5faf call "size" on enumerable objects that are passed to the new method, and this causes extra "COUNT" queries to happen with ActiveRecord associations.
For example:
Set.new(some_activerecord_association)
Previously, the above code would only do one query by iterating over the association. Now it issues two queries, a count query, and then the normal query for results.
Since d4020dd5faf is dealing with endless ranges, I would like to narrow the scope from all Enumerable objects to just Ranges. Unfortunately, I noticed we have a test like this:
assert_raise(ArgumentError) {
Set.new(1.upto(Float::INFINITY))
}
I'm not sure how we can handle such a case without testing size.
Updated by k0kubun (Takashi Kokubun) 1 day ago
How about handling only Range and Enumerator (not Enumerable) for now? Avoiding an extra DB query on ActiveRecord relations seems like a more important use case than preventing user-defined Enumerable with an infinite length from hanging, unless we already know of an existing use case for it. I think infinite-sized Enumerable classes are often implemented as an Enumerator, so it might still work for such cases too.
Updated by Dan0042 (Daniel DeLorme) 1 day ago
It seems to me that's an argument in favor of #17924 Range#infinite?
Updated by mame (Yusuke Endoh) 1 day ago
- Related to Bug #21513: Converting endless range to set hangs added
Updated by tenderlovemaking (Aaron Patterson) 1 day ago
k0kubun (Takashi Kokubun) wrote in #note-1:
How about handling only
RangeandEnumerator(notEnumerable) for now? Avoiding an extra DB query on ActiveRecord relations seems like a more important use case than preventing user-definedEnumerablewith an infinite length from hanging, unless we already know of an existing use case for it. I think infinite-sizedEnumerableclasses are often implemented as anEnumerator, so it might still work for such cases too.
I think that makes sense. I've got a patch mostly prepared, so I'll submit it.
Updated by mame (Yusuke Endoh) 1 day ago
How about handling only
RangeandEnumerator(notEnumerable) for now?
I think it would be better to handle only Range for now, and not Enumerator either. See https://bugs.ruby-lang.org/issues/21513#note-10
Updated by tenderlovemaking (Aaron Patterson) about 10 hours ago
mame (Yusuke Endoh) wrote in #note-5:
How about handling only
RangeandEnumerator(notEnumerable) for now?I think it would be better to handle only Range for now, and not Enumerator either. See https://bugs.ruby-lang.org/issues/21513#note-10
I sent a pull request that only handles Range for now: https://github.com/ruby/ruby/pull/14990
This fixes the issues we're seeing in tests.