# code: # * George Moschovitis # # (c) 2004 Navel, all rights reserved. # $Id: filters.rb 184 2004-12-07 14:42:22Z gmosx $ module N # = Filtering # # Filtering functionality for renders/services. The design # and implementation is HEAVILY influenced by Rails. # # Examples: # # Filter as class: # # class TouchFilter # end # # Filter # before # filter # after # # TODO: # implement inheritable filters. # module Filtering # Ruby is sometimes VERY surprising, the following trick is needed # to include singleton methods in other classes. # def self.append_features(base) super; base.extend(ClassMethods) end module ClassMethods # the filters to be evaluated before the method @@before_filters = [] # the filters to be evaluated after the method @@after_filters = [] # # def before_filters @@before_filters end # # def after_filters @@after_filters end # # def prepend_before_filter(*filters, &block) filters << block if block_given? @@before_filters = filters + @@before_filters end # # def append_before_filter(*filters, &block) filters << block if block_given? @@before_filters = @@before_filters + filters end # Alias for the most common case. alias :before_filter :prepend_before_filter # # def prepend_after_filter(*filters, &block) filters << block if block_given? @@after_filters = filters + @@after_filters end # # def append_after_filter(*filters, &block) filters << block if block_given? @@after_filters = @@after_filters + filters end # Alias for the most common case. alias :after_filter :append_after_filter # Install an arround Filter. A filter is a class that responds # to the before and after methods. Both methods are prepended to # the respective lists. # def prepend_arround_filter(*filters) filters = [filters].flatten for filter in filters if filter.respond_to?(:before) prepend_before_filter { |c| filter.before(c) } elsif filter.respond_to?(:filter) # consider 'filter' as synonym of before. prepend_before_filter { |c| filter.filter(c) } end prepend_after_filter { |c| filter.after(c) } if filter.respond_to?(:after) end end # Install an arround Filter. A filter is a class that responds # to the before and after methods. Both methods are appended to # the respective lists. # def append_arround_filter(*filters) filters = [filters].flatten for filter in filters if filter.respond_to?(:before) append_before_filter { |c| filter.before(c) } elsif filter.respond_to?(:filter) # consider 'filter' as synonym of before. append_before_filter { |c| filter.filter(c) } end append_after_filter { |c| filter.after(c) } if filter.respond_to?(:after) end end # Alias for the most common case. alias :filter :append_arround_filter # # def gen_filters_call_code(filters) code = "" filters.each do |filter| if Symbol === filter code << "if #{filter} == false then return false end;" elsif filter.respond_to?('call') && (filter.arity == 1 || filter.arity == -1) code << 'if filter.call(self) == false then return false end;' elsif filter.is_a?(Module) and filter.instance_methods.size > 0 class_eval "include #{filter};" meth = filter.instance_methods[0] code << "if #{meth} == false then return false end;" elsif filter.respond_to?('filter') code << "if #{filter}.filter(self) == false then return false end" else raise 'Valid filters are either a symbol or a proc/method.' end end return code end end end end # module