<NME> message.rb
<BEF> # encoding: utf-8

module Rango
  module MessageMixin
    # The rails-style flash messages
    # @since 0.0.2
    # NOTE: it's important to include this mixin after ImplicitRendering mixin
    def self.included(controller)
      controller.class_eval do
        if self.method_defined?(:context)
          Rango.logger.debug("Extending #{self}#context by message")
          # This could be in the mixin itself, but we don't want
          # to define it if the context method doesn't exist, so
          # context.respond_to?(:context) as a detection of explicit
          # rendering mixin and similar can work. BTW the following
          # doesn't work with do/end syntax.
          include Module.new {
            def context
              @context ||= super.merge!(message: self.message)
              super.merge!(message: self.message)
            end

            def redirect(uri, status = 301, options = Hash.new)
              status, options = 301, status if status.is_a?(Hash)
              if options.respond_to?(:inject)
                # redirect "/post", error: "Try again"

    def message
      @message ||= begin
        messages = request.GET[:msg] || Hash.new
        if messages.is_a?(String)
          messages.force_encoding(Encoding.default_external)
        elsif messages.is_a?(Hash)
          messages.inject(Hash.new.extend(ParamsMixin)) do |result, pair| # TODO: here is the problem, Hash.new isn't params mixin
            result.merge(pair[0] => pair[1].force_encoding(Encoding.default_external))
          end
        end
      end
    end
    alias_method :flash, :message

    def redirect(uri, options = Hash.new, status = 303, &block)
      # status, options = 303, status if status.is_a?(Hash)
    end

    def message
      @message ||= (request.GET[:msg] || Hash.new)
    end
  end
end
      super(uri, status)
    end
  end
end

<MSG> Controller#redirect takes a block where you get the exception, so you can set headers etc. Set-Cookie header is passed there by default. Also fixed encoding problem in messages and we now pass all exceptions to rescue_http_error. If the exception isn't a http error, we wrap it in a new instance of InternalServerError.

<DFF> @@ -20,7 +20,7 @@ module Rango
               super.merge!(message: self.message)
             end
 
-            def redirect(uri, status = 301, options = Hash.new)
+            def redirect(uri, status = 301, options = Hash.new, &block)
               status, options = 301, status if status.is_a?(Hash)
               if options.respond_to?(:inject)
                 # redirect "/post", error: "Try again"
@@ -44,7 +44,12 @@ module Rango
     end
 
     def message
-      @message ||= (request.GET[:msg] || Hash.new)
+      @message ||= begin
+        messages = request.GET[:msg] || Hash.new
+        messages.inject(Hash.new) do |result, pair|
+          result.merge(pair[0] => pair[1].force_encoding(Encoding.default_external))
+        end
+      end
     end
   end
 end

Controller#redirect takes a block where you get the exception, so you can set headers etc. Set-Cookie header is passed there by default. Also fixed encoding problem in messages and we now pass all exceptions to rescue_http_error. If the exception isn't a http error, we wrap it in a new instance of InternalServerError.