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

# http://wiki.github.com/botanicus/rango/controllers

require "forwardable"
require "rango/router"
require "rango/exceptions"
require "rango/rack/request"
require "rango/environments"

module Rango
  class Controller
    include Rango::UrlHelper
    include Rango::Exceptions
    extend Forwardable
    # for routers
      attribute :after_filters,  Hash.new

      def inherited(subclass)
        unless subclass.before_filters.empty? && subclass.after_filters.empty?
          Rango.logger.debug("Inheritting filters from #{self.inspect} to #{subclass.inspect} (before: #{subclass.before_filters.inspect}, after: #{subclass.after_filters.inspect})")
          subclass.before_filters = self.before_filters
          subclass.after_filters = self.after_filters
        end
      end

      # before :login

    # default, redefine in plugin if you need to
    def invoke_action(action)
      Rango.logger.debug("Calling method #{self.class.name}##{action} without arguments")
      self.response.body = self.send(action)
    end

    def action
        self.after_filters[action || block] = options
      end

    def logger
      Rango.logger
    end

    def_delegators :response, :status, :status=
    def_delegators :response, :headers, :headers=

    # absolute_uri "http://google.com" => "http://google.com"
    # absolute_uri "/products" => "http://localhost:4000/products"
    def absolute_uri(path)
      if path.match(/^https?:\/{2}/)
        path
      else
        (request.base_url.chomp("/") + path).chomp("/")
      end
    end

    # @since 0.0.2
    # @version 0.2.1
    # @return [String] Escaped URL (which is RFC recommendation)
    def redirect(location, status = 303, &block)
      if (300..399).include?(status)
        exception = Redirection.new(absolute_uri(location))
        exception.status = status
        if response["Set-Cookie"]
          exception.headers["Set-Cookie"] = response["Set-Cookie"] # otherwise it don't save cookies
        end
        block.call(exception) unless block.nil?
        raise exception
      else
        raise ArgumentError, "Status has to be between 300 and 399"
      end
    end

    attr_reader :env
    def initialize(env)
      @env = env
    end

    def request
      @request ||= Rango::Request.new(env)
    end

    def response
      @response ||= Rack::Response.new
    end

    def_delegators :request, :cookies, :session

    def router_params
      @router_params ||= self.env["rango.router.params"]
    end

    def params
      @params ||= begin
        params = self.request.params
        params.merge!(self.router_params) if router_params
        params
      end
    end

    # redefine this method for your controller if you want to provide custom error pages
    # returns response array for rack
    # if you need to change just body of error message, define render_http_error method
    # @api plugin
    def rescue_http_error(exception)
      # we need to call it before we assign the variables
      body = self.render_http_error(exception)
      [exception.status, exception.headers, body]
    end

    def render_http_error(exception)
      exception.headers["Content-Type"] = "text/html"
      if Rango.production?
        <<-EOF
<h1>Application Error</h1>
<p>
  The application you are trying to reach has currently some issues. Please contact our team and tell us about the troubles. Thank you.
</p>
        EOF
      else
        <<-EOF
<h1>#{exception.class}: #{exception.message}</h1>
<ul>
  <li>#{exception.backtrace.join("</li><li>")}</li>
</ul>
        EOF
      end
    end
  end
end

<MSG> Before/After render/display filters

<DFF> @@ -17,11 +17,23 @@ module Rango
       attribute :after_filters,  Hash.new
 
       def inherited(subclass)
+        # TODO: rewrite with inherit_filters
         unless subclass.before_filters.empty? && subclass.after_filters.empty?
-          Rango.logger.debug("Inheritting filters from #{self.inspect} to #{subclass.inspect} (before: #{subclass.before_filters.inspect}, after: #{subclass.after_filters.inspect})")
+          Rango.logger.debug("Inheritting filters from #{self.inspect} to #{subclass.inspect} (before: #{subclass.before_filters.inspect}, after: #{subclass.after_filters.inspect})") # WTF?
           subclass.before_filters = self.before_filters
           subclass.after_filters = self.after_filters
         end
+        inherit_filters(subclass, :before_render)
+        inherit_filters(subclass, :after_render)
+        inherit_filters(subclass, :before_display)
+        inherit_filters(subclass, :after_display)
+      end
+
+      def inherit_filters(subclass, name)
+        unless self.send("#{name}_filters").empty?
+          Rango.logger.debug("Inheritting #{name} filters from #{self.inspect} to #{subclass.inspect}")
+          subclass.send("#{name}_filters") = self.send("#{name}_filters")
+        end
       end
 
       # before :login
@@ -36,6 +48,26 @@ module Rango
         self.after_filters[action || block] = options
       end
 
+      cattr_accessor :before_render_filters
+      cattr_accessor :after_render_filters
+      @@before_render_filters = Array.new
+      @@after_render_filters  = Array.new
+
+      cattr_accessor :before_display_filters
+      cattr_accessor :after_display_filters
+      @@before_display_filters = Array.new
+      @@after_display_filters  = Array.new
+
+      # class Posts < Rango::Controller
+      #   self.context ||= Object.new.binding
+      #   def show
+      #     # you can't use @explicit
+      #     post = Post.get(params[:id])
+      #     render "post.html", post: post
+      #   end
+      # end
+      attribute :context
+
       # [master] Change Merb::Controller to respond to #call and return a Rack Array. (wycats)http://rubyurl.com/BhoY
       # @since 0.0.2
       def call(env)

Before/After render/display filters