You are right, the second way will go through a method_missing
. ActiveRecord will parse the method name and if it is a valid name, it will generate a method on the fly.
If you look in the source of ActiveRecord::Base
, in method_missing
you'll see that developers left us a comment of how this generated method would look like:
# def self.find_by_login_and_activated(*args)
# options = args.extract_options!
# attributes = construct_attributes_from_arguments(
# [:login,:activated],
# args
# )
# finder_options = { :conditions => attributes }
# validate_find_options(options)
# set_readonly_option!(options)
#
# if options[:conditions]
# with_scope(:find => finder_options) do
# find(:first, options)
# end
# else
# find(:first, options.merge(finder_options))
# end
# end
So you see that generally it boils down to the same find
method.
I would not say that the first way is preferable because of method_missing
, because the performance penalty for that is negligible. The second way reads better and works well if you just need to fetch records based on attributes equal to some values.
However, this second form does not allow you to do anything beyond equality comparison (e.g., range comparison, "not equal to" expressions, joins, etc.). In such cases, you'll just have to use the find
method with appropriate conditions
and other parameters.