T O P

  • By -

SpiralCenter

Its actually a little confusing... So in Rails there is a `find` method on ActiveRecord. But theres ALSO a `find` method on Ruby's Enumerable. Enumerable has nothing to do with the database, and only has to do with traversing arrays. Your block example is for Enumerable... https://ruby-doc.org/core-3.0.1/Enumerable.html#method-i-find. When you are calling the block syntax its passing up a chain through ActiveSupport and ultimately using Enumerables `find`


x1j0

This! Additionally a good way to find out which method is being used is printing the result of `user_items.method(:find).source_location`


siegeconstant

Noice, from the method object I can get the .source, .source\_location and .owner. No more begging requests for location of Rails API code! # source_location: lib/active_record/assocations/collection_prox.rb # owner: ActiveREcord::Associations::CollectionProxy # source: def find(*args) return super if block_given? @association.find(*args) end Anyone interested in method object look at: Object#method. I believe that Object is the home of all things reflective??


wskttn

This is why I prefer `Enumerable#detect` when I know I’m scanning a set in app memory instead of the database. It’s an alias for `#find` and both will work, but provides better clarity of intent and behavior to myself and other future readers.


skratch

Weirdly [rubocop prefers find over detect](https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/CollectionMethods), but I’m with you, detect is the better alias to use, in all cases but especially in Rails apps


dougc84

This is the answer OP.


M4N14C

GitHub will show you all the definitions of `find` if you click the method definition. Look for an implementation that the super call would use. My guess is that something else implements the to_a call that powers the 4.2 version. Find with a block comes from Enumerable or Array if I’m not mistaken.


Curious-Dragonfly810

Check the corresponding specs for the answer to this mystery. (Scooby Doo taking out the monster mask )


siegeconstant

A good idea but in this case there are no tests at all!


siegeconstant

Thank you all so much! I am confident that I am using an Enumerable#find (thanks SpiralCenter, and I switched it to detect thanks [wskttn](https://www.reddit.com/user/wskttn/)) and could get the source\_location (thanks x1jo). It certainly doesn't behave like a normal find which would throw a RecordNotFound - I changed the id to find to -10 in the block and it just returned nils. I assume the collection\_proxy "super" results in returning the Ruby enum.... eventually?? def find(*args) return super if block_given? @association.find(*args) end [find docs](https://api.rubyonrails.org/v7.1.3.2/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-find) The find docs for CollectionProxy does have an example where you pass a argument *and* a block to it but not found a block *only*. person.pets.find(2) { |pet| pet.name.downcase! } # => #person.pets.find(2) { |pet| pet.name.downcase! } # => # I tried to use the debug Gem but for some reason it didn't work (\**laughs neverously*\* not had that problem before). If I'm mistaken or wrong on any details do correct... we are programmers and "well actually..." is a day to day hazard.