Edge report: with_scope protected
June 19, 2007 @ 12:59 PMI knew all along that using with_scope outside my models was a bad idea, but I did it anyway. So once this little change came through, I had to rethink some of my code…
Just to throw this out there – let’s call it peer-review – my new method of encapsulating with_scope usages sort of piggy-backs on finder encapsulation.
Take, for example, the following code:
1 2 3 4 5 6 7 8 9 10 11 12 |
class Post < ActiveRecord::Base def self.find_active # ... some finder code to return all active posts end end class PostsController < ApplicationController def index @posts = Post::find_active end end |
… despite my habit of encapsulating finders, I still found myself doing this:
1 2 3 4 5 |
# In around-filter or action Post::with_scope( ... conditions ... ) do # ... yield or something end |
– Obviously, BAD. So the alternative is to do something like Post::scope_by_active or something. What about adding a fairly simple block_given? condition to the existing find_active method? Use your imagination on the implementation of that, but the usage would now look something like this:
1 2 3 4 5 6 7 8 |
# No block, returns all active @posts = Post::find_active # block, scopes to active, returns result of block. @my_posts = Post::find_active do Post::find_by_user( user ) end |
Soooo… peer-review away!
I’m code to same construct
def self.find_something(*opts) # :block - optional with_scope(…) do block_given? ? yield : find(:all, *opts) end end