This repository is private.
All pages are served over SSL and all pushing and pulling is done over SSH.
No one may fork, clone, or view it unless they are added as a member.
Every repository with this icon (
) is private.
Every repository with this icon (
This repository is public.
Anyone may fork, clone, or view it.
Every repository with this icon (
) is public.
Every repository with this icon (
| 570f798d » | ian | 2007-10-23 | 1 | module Ardes #:nodoc: | |
| 8ac908ad » | ianwhite | 2008-09-14 | 2 | # included into ActionController::Base | |
| f0b98bf1 » | ian | 2007-10-18 | 3 | module ResponseFor | |
| 570f798d » | ian | 2007-10-23 | 4 | def self.included(base) | |
| 5 | base.class_eval do | ||||
| 6 | extend ClassMethods | ||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 7 | alias_method_chain :default_render, :response_for | |
| c89bc63b » | ianwhite | 2008-10-09 | 8 | alias_method_chain :template_exists?, :response_for | |
| 37c5ff4c » | ianwhite | 2008-10-19 | 9 | alias_method_chain :respond_to, :response_for | |
| 570f798d » | ian | 2007-10-23 | 10 | end | |
| 11 | end | ||||
| f0b98bf1 » | ian | 2007-10-18 | 12 | ||
| 570f798d » | ian | 2007-10-23 | 13 | module ClassMethods | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 14 | # response_for allows you to specify a default response for your actions that don't specify a | |
| 15 | # respond_to block. | ||||
| 2b728b93 » | ian | 2007-10-23 | 16 | # | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 17 | # Using response_for, you may keep the response logic out of the action, so that it can be overriden easily | |
| 18 | # without having to rewrite the entire action. This is very useful when subclassing controllers. | ||||
| 19 | # | ||||
| 20 | # == Usage | ||||
| 21 | # | ||||
| 22 | # response_for :action1 [, :action2], [,:types => [:mime, :type, :list]] [ do |format| ... end] # or | ||||
| 570f798d » | ian | 2007-10-23 | 23 | # | |
| 24 | # === Example | ||||
| 25 | # | ||||
| 26 | # class FooController < ApplicationController | ||||
| 27 | # def index | ||||
| 28 | # @foos = Foo.find(:all) | ||||
| 29 | # end | ||||
| 30 | # | ||||
| 31 | # def show | ||||
| 32 | # @foo = Foo.find(params[:id]) | ||||
| 33 | # end | ||||
| 34 | # end | ||||
| 35 | # | ||||
| 36 | # # this controller needs to respond_to fbml on index, and | ||||
| 37 | # # js, html and xml (templates) on index and show | ||||
| 38 | # class SpecialFooController < FooController | ||||
| 39 | # response_for :index do |format| | ||||
| 40 | # format.fbml { render :inline => turn_into_facebook(@foos) } | ||||
| 41 | # end | ||||
| 42 | # | ||||
| 43 | # response_for :index, :show, :types => [:html, :xml, :js] | ||||
| 44 | # end | ||||
| 45 | # | ||||
| 9dc94651 » | ianwhite | 2008-09-13 | 46 | # === when response_for kicks in | |
| 64911cf3 » | ian | 2007-11-27 | 47 | # | |
| 9dc94651 » | ianwhite | 2008-09-13 | 48 | # response_for only kicks in if the action (or any filters) have not already redirected or rendered. | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 49 | # | |
| 9dc94651 » | ianwhite | 2008-09-13 | 50 | # This means that if you foresee wanting to override your action's responses, you should write them without | |
| 51 | # a respond_to block, but with a response_for block (the latter can be overridden by subsequent response_fors, the | ||||
| 52 | # former cannot) | ||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 53 | # | |
| 54 | # === Other examples | ||||
| 570f798d » | ian | 2007-10-23 | 55 | # | |
| 56 | # response_for :index, :types => [:fbml] # index will respond to fbml and try to render, say, index.fbml.builder | ||||
| 57 | # | ||||
| 58 | # response_for :update do |format| # this example is for a resources_controller controller | ||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 59 | # if !(resource.new_record? || resource.changed?) # => resource.saved? | |
| c89bc63b » | ianwhite | 2008-10-09 | 60 | # format.js { render(:update) {|page| page.replace dom_id(resource), :partial => resource }} | |
| 570f798d » | ian | 2007-10-23 | 61 | # else | |
| 62 | # format.js { render(:update) {|page| page.visual_effect :shake, dom_id(resource) }} | ||||
| 63 | # end | ||||
| 64 | # end | ||||
| 65 | # | ||||
| 66 | # === Notes | ||||
| 67 | # | ||||
| c89bc63b » | ianwhite | 2008-10-09 | 68 | # * If the before_filters or action renders or redirects, then response_for will not be invoked. | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 69 | # * you can stack up multiple response_for calls, the most recent has precedence | |
| 570f798d » | ian | 2007-10-23 | 70 | # * the specifed block is executed within the controller instance, so you can use controller | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 71 | # instance methods and instance variables (i.e. you can make it look just like a regular | |
| c89bc63b » | ianwhite | 2008-10-09 | 72 | # respond_to block). | |
| 73 | # * you can add a response_for an action that has no action method defined. This is just like | ||||
| 74 | # defining a template for an action that has no action method defined. | ||||
| 570f798d » | ian | 2007-10-23 | 75 | # * you can combine the :types option with a block, the block has precedence if you specify the | |
| 76 | # same mime type in both. | ||||
| 77 | def response_for(*actions, &block) | ||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 78 | (options = actions.extract_options!).assert_valid_keys(:types) | |
| 570f798d » | ian | 2007-10-23 | 79 | ||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 80 | types_block = if options[:types] | |
| 81 | proc {|responder| Array(options[:types]).each {|type| responder.send type}} | ||||
| 82 | end | ||||
| 570f798d » | ian | 2007-10-23 | 83 | ||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 84 | # store responses against action names | |
| 570f798d » | ian | 2007-10-23 | 85 | actions.collect(&:to_s).each do |action| | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 86 | action_responses[action] ||= [] | |
| 87 | action_responses[action].unshift types_block if types_block | ||||
| 88 | action_responses[action].unshift block if block | ||||
| 570f798d » | ian | 2007-10-23 | 89 | end | |
| 90 | end | ||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 91 | ||
| 9dc94651 » | ianwhite | 2008-09-13 | 92 | # remove any response for the specified actions. If no arguments are given, | |
| 93 | # then all repsonses for all actions are removed | ||||
| 570f798d » | ian | 2007-10-23 | 94 | def remove_response_for(*actions) | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 95 | if actions.empty? | |
| 96 | instance_variable_set('@action_responses', nil) | ||||
| 97 | else | ||||
| 98 | actions.each {|action| action_responses.delete(action.to_s)} | ||||
| 99 | end | ||||
| 570f798d » | ian | 2007-10-23 | 100 | end | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 101 | ||
| 102 | # return action_responses Hash. On initialize, set and return hash whose values are copies of superclass action_responses, if any | ||||
| 570f798d » | ian | 2007-10-23 | 103 | def action_responses | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 104 | instance_variable_get('@action_responses') || instance_variable_set('@action_responses', copy_of_each_of_superclass_action_responses) | |
| 570f798d » | ian | 2007-10-23 | 105 | end | |
| 106 | |||||
| 06da19df » | ianwhite | 2008-10-09 | 107 | # takes any responses from the argument (a controller, or responses module) and adds them to this controller's responses | |
| 108 | def include_responses_from(responses_container) | ||||
| 109 | responses_container.action_responses.each do |action, responses| | ||||
| 110 | action_responses[action] ||= [] | ||||
| d8ca73c5 » | ianwhite | 2008-10-09 | 111 | action_responses[action].unshift(*responses) | |
| 06da19df » | ianwhite | 2008-10-09 | 112 | end | |
| 113 | end | ||||
| 114 | |||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 115 | private | |
| 116 | def copy_of_each_of_superclass_action_responses | ||||
| 117 | (superclass.action_responses rescue {}).inject({}){|m,(k,v)| m.merge(k => v.dup)} | ||||
| 570f798d » | ian | 2007-10-23 | 118 | end | |
| 119 | end | ||||
| c92657b8 » | ian | 2007-12-11 | 120 | ||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 121 | protected | |
| c89bc63b » | ianwhite | 2008-10-09 | 122 | # does a response exist for the current action? | |
| 123 | def response_exists? | ||||
| 124 | self.class.action_responses.keys.include?(action_name.to_s) | ||||
| 125 | end | ||||
| 126 | |||||
| 127 | # we extend template_exists? to return true if a template OR a response exists corresponding to the current action. | ||||
| 128 | # This is so that a default render will be triggered when no action, but a repsonse does exist. | ||||
| 129 | def template_exists_with_response_for? | ||||
| 130 | response_exists? || template_exists_without_response_for? | ||||
| 131 | end | ||||
| 132 | |||||
| 9dc94651 » | ianwhite | 2008-09-13 | 133 | # if there are responses for the current action, then respond_to them | |
| 8ac908ad » | ianwhite | 2008-09-14 | 134 | # | |
| 135 | # we rescue the case where there were no responses, so that the default_render | ||||
| 136 | # action will be performed | ||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 137 | def respond_to_action_responses | |
| 37c5ff4c » | ianwhite | 2008-10-19 | 138 | if !@respond_to_performed && (responses = self.class.action_responses[action_name]) && responses.any? | |
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 139 | respond_to do |responder| | |
| 8ac908ad » | ianwhite | 2008-09-14 | 140 | responses.each {|response| instance_exec(responder, &response) } | |
| 141 | end rescue Responder::NoResponsesError | ||||
| 570f798d » | ian | 2007-10-23 | 142 | end | |
| 143 | end | ||||
| 144 | |||||
| 9dc94651 » | ianwhite | 2008-09-13 | 145 | # this method is invoked if we've got to the end of an action without | |
| 146 | # performing, which is when we respond_to any repsonses defined | ||||
| 3b1ae5e4 » | ianwhite | 2008-09-13 | 147 | def default_render_with_response_for | |
| 148 | respond_to_action_responses | ||||
| 149 | default_render_without_response_for unless performed? | ||||
| 570f798d » | ian | 2007-10-23 | 150 | end | |
| 8ac908ad » | ianwhite | 2008-09-14 | 151 | ||
| 37c5ff4c » | ianwhite | 2008-10-19 | 152 | def respond_to_with_response_for(*args, &block) | |
| 153 | @respond_to_performed = true | ||||
| 154 | respond_to_without_response_for(*args, &block) | ||||
| 155 | end | ||||
| 156 | |||||
| 8ac908ad » | ianwhite | 2008-09-14 | 157 | # included into ActionController::MimeResponds::Responder | |
| 158 | module Responder | ||||
| 159 | class NoResponsesError < RuntimeError; end | ||||
| 160 | |||||
| 161 | def self.included(responder) | ||||
| 162 | responder.class_eval do | ||||
| 163 | # we make the responder raise an error if there are no responses | ||||
| 164 | def respond_with_response_for | ||||
| 165 | raise NoResponseError if @responses.empty? | ||||
| 166 | respond_without_response_for | ||||
| 167 | end | ||||
| 168 | alias_method_chain :respond, :response_for | ||||
| 169 | end | ||||
| 170 | end | ||||
| 171 | end | ||||
| 3d94fabc » | ianwhite | 2008-10-10 | 172 | ||
| 173 | module VERSION #:nodoc: | ||||
| 174 | MAJOR = 0 | ||||
| 175 | MINOR = 2 | ||||
| 176 | TINY = 1 | ||||
| 177 | |||||
| 178 | STRING = [MAJOR, MINOR, TINY].join('.') | ||||
| 179 | end | ||||
| f0b98bf1 » | ian | 2007-10-18 | 180 | end | |
| 181 | end | ||||








