One important feature of an ActiveRecord find refactoring should be
the ability to extend functionality without having to modify a core
class, although this perhaps does not come first.

After releasing ActiveRecord::Extensions 0.5.0 I started refactoring
AR and found a lot of nastiness. I like the dispatch pattern, and
there should also be a way to subscribe to the Finder to give it more
things to dispatch to.

Perhaps a callback for each key/value pair in the conditions hash. The
below would give you the ability to handle things suffixed with "_in",
ie: age_less_than => 50

IE:

ActiveRecord::Base.finder.new_find_condition do |key,val|
   if key=conditions_hash.keys.find(/(.+)_less_than$/) and val.is_a?
(Numeric)
     [ "#{$1} < ?", val ]
   end
end

Zach
P.S. - please CC my email in response to this

Courtenay wrote:
> Hi guys, what do you think about this implementation (before I go off
> and actually make it work).  The plan is to make it easier to write
> extensions or plugins for find, as well as define your own options for
> the precious first-level argument, :first, :all, etc.
>
> If you want to skip to the paste/diff, it's here: http://pastie.caboo.se/89252
>
> The current way:
>
>       def find(*args)
>         options = args.extract_options!
>         validate_find_options(options)
>         set_readonly_option!(options)
>
>         case args.first
>           when :first then find_initial(options)
>           when :all   then find_every(options)
>           else             find_from_ids(args, options)
>         end
>       end
>
>
> A new way?
>
>       def find(*args)
>         options = args.extract_options!
>         validate_find_options(options)
>         set_readonly_option!(options)
>
>         finder.dispatch(args, options)
>       end
>
>
>       # The Finder class allows you to easily define your own custom
> find implementations.
>       # Simply define this class in your model, and any of its methods
> will be available
>       # to your #find call as the first symbol.  For example,
>       #
>       #   User.find(:last, :conditions => ['name = ?', 'John'])
>       #
>       # is implemented as
>       #
>       #   class User < ActiveRecord::Base
>       #     class Finder
>       #       def last(options)
>       #         @base.find(:first, options.update(:order => 'id desc'))
>       #       end
>       #     end
>       #   end
>       #
>       #
>       # Note: if you want to refer to any methods on Base other than
> find, you'll need to
>       # use the @base proxy object
>       #
>       #   def last(options)
>       #     @base.find_by_sql(...)
>       #   end
>       #
>       class Finder
>         def initialize(base_instance)
>           @base = base_instance
>         end
>
>         def dispatch(args, options)
>           finder_method = args.first
>           if finder_method.is_a?(Symbol) and respond_to?(finder_method)
>             send(finder_method, options)
>           else
>             from_ids(args, options)
>           end
>         end
>
>         def find(*args)
>           @base.find(*args)
>         end
>
>         def all(options)
>           @base.send(:find_every, options)
>         end
>
>         def first(options)
>           @base.send(:find_initial, options)
>         end
>
>         def from_ids(ids, options)
>           @base.send(:find_from_ids, ids, options)
>         end
>
>       end
>
>       def finder
>         @finder ||= Finder.new(self)
>       end
>
> ...
>
> This will also allow some fun things, like, keeping state in the
> finder, or even recording the last SQL statistics.
>
>   @user = User.find(2)
>   User::Finder.records_returned => 25
>   User::Finder.benchmark => 0.025
>
> What do you guys think? All the AR tests still pass with this method,
> since it's a fairly simple proxy, but it allows for much greater
> customization.
>
>
> Courtenay


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-core?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to