Archives

Tags

Showing articles written in December 2008. Show all articles

Multiple before/after model filters with Merb

This evening I found myself in a position in which I wanted to execute several "before" methods hooks/filters on a DataMapper model in a Merb application. I had a look around in the source and API docs, but couldn't really find a nice way of doing it (even though having every hook on a seperate line is not such a bad thing in terms of readability, I suppose).

Anyway, I came up with the following mixin for Extlib (which houses DataMapper's before/after hook functionality):

module Extlib
  module Hook
    module ClassMethods

      alias_method :singular_before, :before
      alias_method :singular_after, :after

      def before(target_methods, filter_methods = nil, &block)
        insert_multiple_hooks "before", target_methods, filter_methods, &block
      end

      def after(target_methods, filter_methods = nil, &block)
        insert_multiple_hooks "after", target_methods, filter_methods, &block
      end

      private

      def insert_multiple_hooks(context, target_methods, filter_methods, &block)
        targets = [target_methods].flatten
        filters = [filter_methods].flatten

        targets.each do |target|
          filters.each do |filter|
            send("singular_#{context}", target.to_sym, filter.to_sym, &block)
          end
        end
      end

    end
  end
end

Hopefully it is fairly straight-forward. Basically, it will allow you to pass an array to the before and after methods. For example, you can do this:

before [ :create, :update ], [ :set_filename, :set_filesize, :generate_thumbnail ]

Which is equivalent to:

before :create, :set_filename
before :create, :set_filesize
before :create, :generate_thumbnail
before :update, :set_filename
before :update, :set_filesize
before :update, :generate_thumbnail

I got it loaded into my Merb app by creating an app/lib directory and requireing the contents of it from the config/init.rb file.