Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit, tests will be coming

  • Loading branch information...
commit 37f33a21ec587867e1383cfdb267eb69e369fab2 0 parents
Jack Chen authored
2  CHANGELOG
@@ -0,0 +1,2 @@
+v0.0.3 (September 8th, 2008)
+ * Initial release
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46 README
@@ -0,0 +1,46 @@
+priority_filter
+==============
+
+priority_filter is an extension of filters in Rails that allows you to set priorities to filters. The main benefit of this is you can now have a filter defined in a parent controller that gets executed after the same type of filter in a child controller.
+
+It does this by overriding all the *_filter methods and storing them in an array, and then rebuilding the filter chain whenever a filter is added or skipped. This causes a longer loading time, but it only has to do this when the controller is loaded, so after the application loads, there is no performance hit (that I can see).
+
+A more elegant solution would to be override the find_filter_append/prepend_position, but it wasn't working for me so I gave up and went with this method.
+
+Usage
+=====
+
+All the *_filter methods now accept :priority as an option. :priority can be any positive integer, or :first (which gets changed to 0) or :last (will always be called after all other filters that are also not :last). Leaving out :priority sets the priority to 1. So if you install this plugin into an existing project, it (theoretically) will not change the filter execution order. prepend_*_filter simply implies :first.
+
+before_filter :filter, :priority => 5
+after_filter :after, :priority => :last
+
+
+Example
+=======
+
+class ApplicationController < ActionController::Base
+ before_filter :foo, :priority => 5
+ before_filter :bar, :priority => :first
+end
+
+class FooController < ApplicationController
+ before_filter :rah, :priority => 3
+ before_filter :moo, :priority => :first
+end
+
+class BarController < FooController
+ before_filter :kek
+ before_filter :bah, :priority => :last
+end
+
+Filter priorities (in execution order):
+ :bar => 0
+ :moo => 0
+ :kek => 1
+ :rah => 3
+ :foo => 5
+ :bah => last
+
+
+Copyright (c) 2008 Jack Chen, under the MIT License
22 Rakefile
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the priority_filter plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the priority_filter plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'PriorityFilter'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
3  init.rb
@@ -0,0 +1,3 @@
+require 'priority_filter'
+
+ActionController::Base.send(:include, ActionController::Filters::PriorityFilter)
1  install.rb
@@ -0,0 +1 @@
+# Install hook code here
131 lib/priority_filter.rb
@@ -0,0 +1,131 @@
+module ActionController
+ module Filters
+ module PriorityFilter
+
+ def self.included(base)
+ base.extend ClassMethods
+ end
+
+ module ClassMethods
+ def extract_options(*methods, &block)
+ methods.flatten!
+ options = methods.extract_options!
+ methods << block if block_given?
+ return methods, options
+ end
+
+ def add_priority_filter(default_priority, filter_type, *filters, &block)
+
+ filters, options = extract_options(filters)
+
+ f = priority_filters
+ l = last_priority_filters
+
+ priority = options[:priority] ||= default_priority
+ priority = 0 if priority == :first
+
+ if priority != :last and !priority.is_a? Integer and priority < 0
+ throw "Invalid priority, must be a positive integer, :first or :last"
+ end
+
+ options.reject! { |k, v| k == :priority }
+
+ new_filters = {:filters => filters, :options => options, :block => block, :type => filter_type}
+ if priority == :last
+ l << new_filters
+ elsif priority > f.length - 1
+ f.insert priority, [new_filters]
+ else
+ f[priority] ||= Array.new
+ f[priority] << new_filters
+ end
+
+ rebuild_filter_chain
+
+ end
+
+ def rebuild_filter_chain
+ filter_chain.clear
+ priority_filters.flatten.compact.map do |filters|
+ filter_chain.append_filter_to_chain [filters[:filters], filters[:options]], filters[:type], &filters[:block]
+ end
+
+ last_priority_filters.flatten.compact.map do |filters|
+ filter_chain.append_filter_to_chain [filters[:filters], filters[:options]], filters[:type], &filters[:block]
+ end
+
+ skip_filters.each do |filters|
+ filter_chain.skip_filter_in_chain(filters[:filters], &filters[:test])
+ end
+ end
+
+
+ def append_before_filter(*filters, &block)
+ add_priority_filter(1, :before, *filters, &block)
+ end
+
+ def append_after_filter(*filters, &block)
+ add_priority_filter(1, :after, *filters, &block)
+ end
+
+ def append_around_filter(*filters, &block)
+ add_priority_filter(1, :around, *filters, &block)
+ end
+
+ alias_method :before_filter, :append_before_filter
+ alias_method :after_filter, :append_after_filter
+ alias_method :around_filter, :append_around_filter
+
+ def prepend_before_filter(*filters, &block)
+ add_priority_filter(:first, :before, *filters, &block)
+ end
+
+ def prepend_after_filter(*filters, &block)
+ add_priority_filter(:first, :after, *filters, &block)
+ end
+
+ def prepend_around_filter(*filters, &block)
+ add_priority_filter(:first, :around, *filters, &block)
+ end
+
+
+ def skip_filter(*filters)
+ skip_filters << {:filters => filters}
+ rebuild_filter_chain
+ end
+
+ def skip_before_filter(*filters)
+ skip_filters << {:filters => filters, :test => :before?}
+ rebuild_filter_chain
+ end
+
+ def skip_after_filter(*filters)
+ skip_filters << {:filters => filters, :test => :after?}
+ rebuild_filter_chain
+ end
+
+
+ def priority_filters
+ @priority_filters ||= (self != ActionController::Base ? deep_clone(superclass.priority_filters) : [])
+ end
+
+ def last_priority_filters
+ @last_priority_filters ||= (self != ActionController::Base ? deep_clone(superclass.last_priority_filters) : [])
+ end
+
+ def skip_filters
+ @skip_filters ||= (self != ActionController::Base ? deep_clone(superclass.skip_filters) : [])
+ end
+
+ private
+
+ def deep_clone(array)
+ array = array.clone
+ array.map!(&:clone)
+ end
+
+ end
+
+ end
+ end
+end
4 tasks/priority_filter_tasks.rake
@@ -0,0 +1,4 @@
+# desc "Explaining what the task does"
+# task :priority_filter do
+# # Task goes here
+# end
8 test/priority_filter_test.rb
@@ -0,0 +1,8 @@
+require 'test/unit'
+
+class PriorityFilterTest < Test::Unit::TestCase
+ # Replace this with your real tests.
+ def test_this_plugin
+ flunk
+ end
+end
1  uninstall.rb
@@ -0,0 +1 @@
+# Uninstall hook code here
Please sign in to comment.
Something went wrong with that request. Please try again.