diff options
| author | Mikel Lindsaar <raasdnil@gmail.com> | 2010-01-17 12:46:51 +1100 | 
|---|---|---|
| committer | Mikel Lindsaar <raasdnil@gmail.com> | 2010-01-17 12:46:51 +1100 | 
| commit | 6f663addaa7ed40f1133687d7a2be0958bf0c059 (patch) | |
| tree | 7beb7f092c1979d1fd5ea6e7aaaf4f59c2f4abf4 /actionpack/lib/action_dispatch/middleware | |
| parent | 8834b2612b7ddda70ee6a685eb0063d3daa8e63d (diff) | |
| parent | 3e94032227d450d479f511070c51f37f53d0ecc4 (diff) | |
| download | rails-6f663addaa7ed40f1133687d7a2be0958bf0c059.tar.gz rails-6f663addaa7ed40f1133687d7a2be0958bf0c059.tar.bz2 rails-6f663addaa7ed40f1133687d7a2be0958bf0c059.zip | |
Merge branch 'master' of github.com:lifo/docrails
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware')
6 files changed, 223 insertions, 38 deletions
| diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb index 49bc20f11f..5ec406e134 100644 --- a/actionpack/lib/action_dispatch/middleware/callbacks.rb +++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb @@ -1,4 +1,10 @@  module ActionDispatch +  # Provide callbacks to be executed before and after the request dispatch. +  # +  # It also provides a to_prepare callback, which is performed in all requests +  # in development by only once in production and notification callback for async +  # operations. +  #    class Callbacks      include ActiveSupport::Callbacks @@ -29,12 +35,6 @@ module ActionDispatch        set_callback(:call, :after, *args, &block)      end -    class << self -      # DEPRECATED -      alias_method :before_dispatch, :before -      alias_method :after_dispatch, :after -    end -      def initialize(app, prepare_each_request = false)        @app, @prepare_each_request = app, prepare_each_request        run_callbacks(:prepare) @@ -45,6 +45,8 @@ module ActionDispatch          run_callbacks(:prepare) if @prepare_each_request          @app.call(env)        end +    ensure +      ActiveSupport::Notifications.instrument "action_dispatch.callback"      end    end  end diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb new file mode 100644 index 0000000000..99b36366d6 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -0,0 +1,174 @@ +module ActionDispatch +  class Request +    # Access the contents of the flash. Use <tt>flash["notice"]</tt> to +    # read a notice you put there or <tt>flash["notice"] = "hello"</tt> +    # to put a new one. +    def flash +      session['flash'] ||= Flash::FlashHash.new +    end +  end + +  # The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed +  # to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create +  # action that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can +  # then expose the flash to its template. Actually, that exposure is automatically done. Example: +  # +  #   class PostsController < ActionController::Base +  #     def create +  #       # save post +  #       flash[:notice] = "Successfully created post" +  #       redirect_to posts_path(@post) +  #     end +  # +  #     def show +  #       # doesn't need to assign the flash notice to the template, that's done automatically +  #     end +  #   end +  # +  #   show.html.erb +  #     <% if flash[:notice] %> +  #       <div class="notice"><%= flash[:notice] %></div> +  #     <% end %> +  # +  # This example just places a string in the flash, but you can put any object in there. And of course, you can put as +  # many as you like at a time too. Just remember: They'll be gone by the time the next action has been performed. +  # +  # See docs on the FlashHash class for more details about the flash. +  class Flash +    class FlashNow #:nodoc: +      def initialize(flash) +        @flash = flash +      end + +      def []=(k, v) +        @flash[k] = v +        @flash.discard(k) +        v +      end + +      def [](k) +        @flash[k] +      end +    end + +    class FlashHash < Hash +      def initialize #:nodoc: +        super +        @used = Set.new +      end + +      def []=(k, v) #:nodoc: +        keep(k) +        super +      end + +      def update(h) #:nodoc: +        h.keys.each { |k| keep(k) } +        super +      end + +      alias :merge! :update + +      def replace(h) #:nodoc: +        @used = Set.new +        super +      end + +      # Sets a flash that will not be available to the next action, only to the current. +      # +      #     flash.now[:message] = "Hello current action" +      # +      # This method enables you to use the flash as a central messaging system in your app. +      # When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>). +      # When you need to pass an object to the current action, you use <tt>now</tt>, and your object will +      # vanish when the current action is done. +      # +      # Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>. +      def now +        FlashNow.new(self) +      end + +      # Keeps either the entire current flash or a specific flash entry available for the next action: +      # +      #    flash.keep            # keeps the entire flash +      #    flash.keep(:notice)   # keeps only the "notice" entry, the rest of the flash is discarded +      def keep(k = nil) +        use(k, false) +      end + +      # Marks the entire flash or a single flash entry to be discarded by the end of the current action: +      # +      #     flash.discard              # discard the entire flash at the end of the current action +      #     flash.discard(:warning)    # discard only the "warning" entry at the end of the current action +      def discard(k = nil) +        use(k) +      end + +      # Mark for removal entries that were kept, and delete unkept ones. +      # +      # This method is called automatically by filters, so you generally don't need to care about it. +      def sweep #:nodoc: +        keys.each do |k| +          unless @used.include?(k) +            @used << k +          else +            delete(k) +            @used.delete(k) +          end +        end + +        # clean up after keys that could have been left over by calling reject! or shift on the flash +        (@used - keys).each{ |k| @used.delete(k) } +      end + +      # Convenience accessor for flash[:alert] +      def alert +        self[:alert] +      end + +      # Convenience accessor for flash[:alert]= +      def alert=(message) +        self[:alert] = message +      end + +      # Convenience accessor for flash[:notice] +      def notice +        self[:notice] +      end + +      # Convenience accessor for flash[:notice]= +      def notice=(message) +        self[:notice] = message +      end + +      private +        # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods +        #     use()               # marks the entire flash as used +        #     use('msg')          # marks the "msg" entry as used +        #     use(nil, false)     # marks the entire flash as unused (keeps it around for one more action) +        #     use('msg', false)   # marks the "msg" entry as unused (keeps it around for one more action) +        # Returns the single value for the key you asked to be marked (un)used or the FlashHash itself +        # if no key is passed. +        def use(key = nil, used = true) +          Array(key || keys).each { |k| used ? @used << k : @used.delete(k) } +          return key ? self[key] : self +        end +    end + +    def initialize(app) +      @app = app +    end + +    def call(env) +      if (session = env['rack.session']) && (flash = session['flash']) +        flash.sweep +      end + +      @app.call(env) +    ensure +      if (session = env['rack.session']) && (flash = session['flash']) && flash.empty? +        session.delete('flash') +      end +    end +  end +end diff --git a/actionpack/lib/action_dispatch/middleware/head.rb b/actionpack/lib/action_dispatch/middleware/head.rb new file mode 100644 index 0000000000..56e2d2f2a8 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/head.rb @@ -0,0 +1,18 @@ +module ActionDispatch +  class Head +    def initialize(app) +      @app = app +    end + +    def call(env) +      if env["REQUEST_METHOD"] == "HEAD" +        env["REQUEST_METHOD"] = "GET" +        env["rack.methodoverride.original_method"] = "HEAD" +        status, headers, body = @app.call(env) +        [status, headers, []] +      else +        @app.call(env) +      end +    end +  end +end diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 7d4f0998ce..311880cabc 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -102,7 +102,7 @@ module ActionDispatch                  # Note that the regexp does not allow $1 to end with a ':'                  $1.constantize                rescue LoadError, NameError => const_error -                raise ActionDispatch::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n" +                raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n"                end                retry diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 4ebc8a2ab9..10f04dcdf6 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -1,7 +1,24 @@  require 'active_support/core_ext/exception' +require 'active_support/notifications'  require 'action_dispatch/http/request'  module ActionDispatch +  # This middleware rescues any exception returned by the application and renders +  # nice exception pages if it's being rescued locally. +  # +  # Every time an exception is caught, a notification is published, becoming a good API +  # to deal with exceptions. So, if you want send an e-mail through ActionMailer +  # everytime this notification is published, you just need to do the following: +  # +  #   ActiveSupport::Notifications.subscribe "action_dispatch.show_exception" do |name, start, end, instrumentation_id, payload| +  #     ExceptionNotifier.deliver_exception(start, payload) +  #   end +  # +  # The payload is a hash which has two pairs: +  # +  # * :env - Contains the rack env for the given request; +  # * :exception - The exception raised; +  #    class ShowExceptions      LOCALHOST = '127.0.0.1'.freeze @@ -44,8 +61,11 @@ module ActionDispatch      def call(env)        @app.call(env)      rescue Exception => exception -      raise exception if env['action_dispatch.show_exceptions'] == false -      render_exception(env, exception) +      ActiveSupport::Notifications.instrument 'action_dispatch.show_exception', +        :env => env, :exception => exception do +        raise exception if env['action_dispatch.show_exceptions'] == false +        render_exception(env, exception) +      end      end      private diff --git a/actionpack/lib/action_dispatch/middleware/string_coercion.rb b/actionpack/lib/action_dispatch/middleware/string_coercion.rb deleted file mode 100644 index 232e947835..0000000000 --- a/actionpack/lib/action_dispatch/middleware/string_coercion.rb +++ /dev/null @@ -1,29 +0,0 @@ -module ActionDispatch -  class StringCoercion -    class UglyBody < ActiveSupport::BasicObject -      def initialize(body) -        @body = body -      end - -      def each -        @body.each do |part| -          yield part.to_s -        end -      end - -      private -        def method_missing(*args, &block) -          @body.__send__(*args, &block) -        end -    end - -    def initialize(app) -      @app = app -    end - -    def call(env) -      status, headers, body = @app.call(env) -      [status, headers, UglyBody.new(body)] -    end -  end -end | 
