Permalink
Browse files

with_action plugin for executing different blocks base on request par…

…ameters
  • Loading branch information...
0 parents commit 1c912997bdff6ee5a93e666bc5cd25da47e17fb4 @bkeepers bkeepers committed Jul 16, 2007
Showing with 184 additions and 0 deletions.
  1. +20 −0 MIT-LICENSE
  2. +34 −0 README
  3. +22 −0 Rakefile
  4. +5 −0 init.rb
  5. +44 −0 lib/with_action.rb
  6. +4 −0 tasks/with_action_tasks.rake
  7. +55 −0 test/with_action_test.rb
@@ -0,0 +1,20 @@
+Copyright (c) 2007 [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.
@@ -0,0 +1,34 @@
+= WithAction
+
+A respond_to style helper for doing different actions based on which request parameters are passed. Specifically, it is helpful if you want to use multiple form buttons on a page, such as "Save", "Save and Continue Editing", and "Cancel". with_action executes different blocks based on what the presence of request parameters.
+
+ def create
+ with_action do |a|
+ a.cancel { redirect_to articles_path }
+ a.any do
+ @article = Article.new(params[:article])
+ if @article.save
+ a.save { redirect_to article_path(@article) }
+ a.edit { redirect_to article_path(@article) }
+ a.approve do
+ @article.approve!
+ redirect_to article_path(@article)
+ end
+ else
+ render :action => 'new'
+ end
+ end
+ end
+ end
+
+A block is invoked if a parameter with the same name exists and is not blank. Here is an example of a form to submit to this action:
+
+ <%= submit_tag 'Save', :name => 'save' %>
+ <%= submit_tag 'Save & Continue Editing', :name => 'edit' %>
+ <%= submit_tag 'Save & Approve', :name => 'approve' %>
+ <%= submit_tag 'Cancel', :name => 'cancel' %>
+
+If an @any@ block is present and no parameter that matches one of the other blocks, it is called by default, otherwise the first block will be called. The @any@ block is the only one that can have nesting and be called multiple times.
+
+
+(c) Copyright 2007 Brandon Keepers (brandon@opensoul.org)
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the with_action plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the with_action plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'WithAction'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
@@ -0,0 +1,5 @@
+require 'with_action'
+
+ActionController::Base.class_eval do
+ include CollectiveIdea::WithAction
+end
@@ -0,0 +1,44 @@
+module CollectiveIdea
+ module WithAction
+ def self.included(base)
+ base.send(:include, InstanceMethods)
+ end
+
+ module InstanceMethods
+ def with_action
+ responder = ActionResponder.new(params)
+ yield responder
+ responder.respond
+ end
+ end
+
+ class ActionResponder
+ def initialize(params)
+ @params = params
+ @order, @responses = [], {}
+ end
+
+ def respond
+ action = @order.detect {|a| !@params[a].blank? }
+ action ||= @order.include?(:any) ? :any : @order.first
+ @responses[action].call if @responses[action]
+ end
+
+ def any(&block)
+ method_missing(:any) do
+ # reset
+ @order, @responses = [], {}
+ returning block.call do
+ respond
+ end
+ end
+ end
+
+ def method_missing(action, &block)
+ @order << action
+ @responses[action] = block
+ end
+ end
+
+ end
+end
@@ -0,0 +1,4 @@
+# desc "Explaining what the task does"
+# task :with_action do
+# # Task goes here
+# end
@@ -0,0 +1,55 @@
+require 'test/unit'
+require 'rubygems'
+require 'active_support'
+require 'mocha'
+require 'stubba'
+require File.dirname(__FILE__) + '/../lib/with_action'
+
+class WithActionTest < Test::Unit::TestCase
+
+ def setup
+ @parameters = {}
+ @responder = CollectiveIdea::WithAction::ActionResponder.new(@parameters)
+ end
+
+ def test_calls_second_with_two_responses
+ @parameters[:save] = true
+ @responder.cancel { @executed = :cancel }
+ @responder.save { @executed = :save }
+ @responder.respond
+ assert_equal :save, @executed
+ end
+
+ def test_does_not_call_any_on_match
+ @parameters[:cancel] = true
+ @responder.cancel { @executed = :cancel }
+ @responder.any { @executed = :any }
+ @responder.respond
+ assert_equal :cancel, @executed
+ end
+
+ def test_any
+ @parameters[:bar] = true
+ @responder.foo { @executed = :foo }
+ @responder.any do
+ @responder.bar { @executed = :bar }
+ end
+ @responder.respond
+ assert_equal :bar, @executed
+ end
+
+ def test_defaults_to_any_block
+ @responder.foo { @executed = :foo }
+ @responder.any { @executed = :any }
+ @responder.respond
+ assert_equal :any, @executed
+ end
+
+ def test_defaults_to_first_without_any_block
+ @responder.foo { @executed = :foo }
+ @responder.bar { @executed = :bar }
+ @responder.respond
+ assert_equal :foo, @executed
+ end
+
+end

0 comments on commit 1c91299

Please sign in to comment.