What's New in Edge Rails: Around Filters are Here

Posted by ryan
at 4:42 AM on Friday, September 22, 2006

For the second time I’ve had my virtual hand slapped for trumpeting a poor usage of with_scope . For the record, I want to make it clear that one should be using the rich domain model that active record provides to operate on associated objects: user.assets.find() and user.asset.create() instead of scoping to a user as my and Roman’s examples implied. Just a case of not thinking hard enough to come up with an appropriate example. Sorry David, won’t happen again!

I’ve mentioned the Meantime filter plugin by Roman Le Negrate in the past as a very useful little utility – apparently the core team agrees as around filtering is now part of edge Rails.

Usage is pretty much the same as with meantime:


class AssetController < ActionController

  before_filter :verify_login
  around_filter :benchmark

  def assets
    @assets = Asset.find(:all)
  end

  def benchmark
    benchmark("Asset benchmark") { yield }
  end

end

You can also define a class to handle your filtering needs (whose filter method yields to the action block)


class AssetController < ActionController

  around_filter BenchmarkFilter   # or BenchmarkFilter.new
  ...

  class BenchmarkFilter
    def filter
      benchmark("Benchmarking...") { yield }
    end
  end

end

Or you can directly pass a Proc in as the filter:


class AssetController < ActionController

  around_filter (:only => :assets) do |controller,action_block| 
    controller.benchmark("Benchmarking...") { action_block.call }
  end
  ...
end

Since the around filter explicitly governs the execution of the action being requested, you can use them to skip the action completely. This would act the same as a before_filter that returned false.

tags: rubyonrails, rails

Comments

Leave a response

  1. DHHSeptember 22, 2006 @ 06:19 AM
    For the record, it's STRONGLY discouraged to use the around filter with with_scope like the example above proposes. Instead you should do be following the association hierarchy, so you do something like @current_user.assets.find(params[:id])@. Using with_scope at all in filters is a bad idea. In the very, very few cases where it's applicable at all, it should be encapsulated in the model. Otherwise you're nuking the coherence of the domain model and bleeding it into the controllers. Remember that part of the reason that we have a domain model at all is because we want to use it outside just the controllers (like in script/console or in a script), so we can't let domain concerns bleed into the controller. I'd appreciate if this post was updated to reflect that ;). I'll post something on the Rails weblog shortly to underscore these recommendations. AWDwR is being updated to contain the same recommendations. Thanks!
  2. DHHSeptember 22, 2006 @ 12:18 PM
    If the above sounded a little harsh, let me take the opportunity to thank you for running this blog. It's a bright light in the Rails community. Truly a valuable resource. I salute, thee!
  3. Ryan DaigleSeptember 22, 2006 @ 12:30 PM
    David - the last thing you have to worry about is offending me. My skin is thick and your points are valid - both of which lead to no offense taken. Thanks for stopping by!
  4. Lee O'MaraSeptember 27, 2006 @ 09:08 AM
    A minor nitpik, around filters are not new, in fact they have been around since Rails 0.5.7 (two years ago) See this comment in the actionpack changelog. http://dev.rubyonrails.org/browser/trunk/actionpack/CHANGELOG?rev=4#L638
  5. Ryan DaigleSeptember 27, 2006 @ 03:33 PM
    Lee, great point. I guess what's new here is the ability to pass in your around filter as a block or method reference... Thanks for the clarification.
  6. GAHHHHH May 01, 2007 @ 11:54 AM

    i need to get around the school filters…GAHHH