[LRUG] Baffled by inconsistent behaviour of Rails find_by_* method

Graham Ashton graham at effectif.com
Wed Aug 24 04:42:04 PDT 2011


On 24 Aug 2011, at 12:09, Mark Woods wrote:

>> There are indeed those three different specification codes in the database,
>> and each of them begins with "4400", but why does the same method find only
>> one when run from the console?
> 
> I'm scared... is Exammodule.find_all_by_specificationcode really
> finding partial matches when given a string argument? If so, what
> query is activerecord generating?

If memory serves it was ActiveRecord 2.2.2? Even though it seems as though MySQL is at fault, I couldn't resist having a look.

If you want to follow what it's doing in this scenario:

- `finder` is :all
- `attribute_names` is ['specificationcode']
- `bang` is nil

Lines 1780-1800 of lib/active_record/base.rb (extracted from a 60 line method). The first time you call it, it generates a method on the model on the fly.

  finder = match.finder
  bang = match.bang?
  self.class_eval %{
    def self.#{method_id}(*args)
      options = args.extract_options!
      attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
      finder_options = { :conditions => attributes }
      validate_find_options(options)
      set_readonly_option!(options)

      #{'result = ' if bang}if options[:conditions]
        with_scope(:find => finder_options) do
          find(:#{finder}, options)
        end 
      else
        find(:#{finder}, options.merge(finder_options))
      end 
      #{'result || raise(RecordNotFound)' if bang}
    end 
  }, __FILE__, __LINE__
  send(method_id, *arguments)

I can't say I'm a fan of meta programming in Ruby by lobbing strings of code around. Good to know what's behind the scenes though.


More information about the Chat mailing list