This is great, and I wouldn't have seen the possibilities if you hadn't explained it in code!
Thanks! -Tim On Tue, Oct 19, 2010 at 5:28 PM, Aaron Patterson <[email protected] > wrote: > On Tue, Oct 19, 2010 at 04:16:33PM -0500, Tim Morgan wrote: > > Sure! > > > > Here is the updated patch: > > > https://rails.lighthouseapp.com/projects/8994/tickets/1812/a/727956/allow-default_scope-to-accept-a-proc2.patch > > Thanks! I've applied it and extended it a little bit so that > default_scope will take any object that responds to "call". > > I'll show some code, then try to explain the benefits. This is now > possible: > > class AuthorFilter < Struct.new(:klass, :author_id) > def call > klass.where(:author_id => author_id) > end > end > > class AmazingPost < ActiveRecord::Base > self.table_name = 'posts' > default_scope AuthorFilter.new(self, 2) > end > > The Object form does not need to save binding like the lambda form does. > This > can lead to less memory usage and help curb "leaking objects". > > Because we can use objects, it allows our default scopes to contain more > logic: we can actually break up functionality to other methods. For > example: > > class AuthorFilter < Struct.new(:klass, :some_value) > def calculate_id > ... do som complex logic to figure out the id ... > end > > def call > klass.where(:author_id => calculate_id) > end > end > > We can even use modules or subclasses to extend our logic. For example: > > module BodyFilter > def call > super.where(:body => 'hello') > end > end > > class AuthorFilter < Struct.new(:klass, :author_id) > def call > klass.where(:author_id => author_id) > end > end > > class AmazingPost < ActiveRecord::Base > self.table_name = 'posts' > # Produces: WHERE author_id = 2 AND body = 'hello' > default_scope AuthorFilter.new(self, 2).extend(BodyFilter) > end > > Finally, we can more easily test any complex logic we need in this > filter: > > class FilterTest < Test::Unit::TestCase > class DreamCatcher > attr_reader :wheres > def initialize; @wheres = []; end > def where(arg); @wheres << arg; end > end > > def test_appropriate_where_clause > dc = DreamCatcher.new > AuthorFilter.new(dc, 2).call > assert_equal([{:author_id => 2}], dc.wheres) > end > end > > I'd like to see the rest of our scope methods to allow arbitrary objects > that respond to `call` for the above reasons. :-) > > -- > Aaron Patterson > http://tenderlovemaking.com/ > -- 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.
