lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application.rb



module Padrino
  class ApplicationSetupError < RuntimeError #:nodoc:
  end

  ##
  # Subclasses of this become independent Padrino applications (stemming from Sinatra::Application)
  # These subclassed applications can be easily mounted into other Padrino applications as well.
  #
  class Application < Sinatra::Base
    register Padrino::Routing   # Support for advanced routing, controllers, url_for

    class << self

      def inherited(base) #:nodoc:
        logger.devel "Setup #{base}"
        CALLERS_TO_IGNORE.concat(PADRINO_IGNORE_CALLERS)
        base.default_configuration!
        base.prerequisites.concat([
          File.join(base.root, "/models.rb"),
          File.join(base.root, "/models/**/*.rb"),
          File.join(base.root, "/lib.rb"),
          File.join(base.root, "/lib/**/*.rb")
        ]).uniq!
        Padrino.require_dependencies(base.prerequisites)
        super(base) # Loading the subclass inherited method
      end

      ##
      # Hooks into when a new instance of the application is created
      # This is used because putting the configuration into inherited doesn't
      # take into account overwritten app settings inside subclassed definitions
      # Only performs the setup first time application is initialized.
      #
      def new(*args, &bk)
        setup_application!
        logging, logging_was = false, logging
        show_exceptions, show_exceptions_was = false, show_exceptions
        super(*args, &bk)
      ensure
        logging, show_exceptions = logging_was, show_exceptions_was
      end

      ##
      # Reloads the application files from all defined load paths
      #
      # This method is used from our Padrino Reloader during development mode
      # in order to reload the source files.
      #
      # ==== Examples
      #
      #   MyApp.reload!
      #
      def reload!
        logger.devel "Reloading #{self}"
        @_dependencies = nil # Reset dependencies
        reset! # Reset sinatra app
        reset_routes! # Remove all existing user-defined application routes
        Padrino.require_dependencies(self.app_file, :force => true) # Reload the app file
        require_dependencies # Reload dependencies
        register_initializers # Reload our middlewares
        default_filters! # Reload filters
        default_errors!  # Reload our errors
        I18n.reload! if defined?(I18n) # Reload also our translations
      end

      ##
      # Resets application routes to only routes not defined by the user
      #
      # ==== Examples
      #
      #   MyApp.reset_routes!
      #
      def reset_routes!
        reset_router!
        default_routes!
      end

      ##
      # Returns the routes of our app.
      #
      # ==== Examples
      #
      #   MyApp.routes
      #
      def routes
        router.routes
      end

      ##
      # Setup the application by registering initializers, load paths and logger
      # Invoked automatically when an application is first instantiated
      #
      def setup_application!
        return if @_configured
        self.register_initializers
        self.require_dependencies
        self.disable :logging # We need do that as default because Sinatra use commonlogger.
        self.default_filters!
        self.default_routes!
        self.default_errors!
        if defined?(I18n)
          I18n.load_path << self.locale_path
          I18n.reload!
        end
        @_configured = true
      end

      ##
      # Run the Padrino app as a self-hosted server using
      # Thin, Mongrel or WEBrick (in that order)
      #
      def run!(options={})
        return unless Padrino.load!
        Padrino.mount(self.to_s).to("/")
        Padrino.run!(options)
      end

      ##
      # Returns the used $LOAD_PATHS from this application
      #
      def load_paths
        @_load_paths ||= %w(models lib mailers controllers helpers).map { |path| File.join(self.root, path) }
      end

      ##
      # Returns default list of path globs to load as dependencies
      # Appends custom dependency patterns to the be loaded for your Application
      #
      # ==== Examples
      #   MyApp.dependencies << "#{Padrino.root}/uploaders/**/*.rb"
      #   MyApp.dependencies << Padrino.root('other_app', 'controllers.rb')
      #
      def dependencies
        @_dependencies ||= [
          "urls.rb", "config/urls.rb", "mailers/*.rb", "mailers.rb",
          "controllers/**/*.rb", "controllers.rb", "helpers/**/*.rb", "helpers.rb"
        ].map { |file| Dir[File.join(self.root, file)] }.flatten
      end

      ##
      # An array of file to load before your app.rb, basically are files wich our app depends on.
      #
      # By default we look for files:
      #
      #   yourapp/models.rb
      #   yourapp/models/**/*.rb
      #   yourapp/lib.rb
      #   yourapp/lib/**/*.rb
      #
      # ==== Examples
      #   MyApp.prerequisites << Padrino.root('my_app', 'custom_model.rb')
      #
      def prerequisites
        @_prerequisites ||= []
      end

      protected
        ##
        # Defines default settings for Padrino application
        #
        def default_configuration!
          # Overwriting Sinatra defaults
          set :app_file, File.expand_path(caller_files.first || $0) # Assume app file is first caller
          set :environment, Padrino.env
          set :reload, Proc.new { development? }
          set :logging, Proc.new { development? }
          set :method_override, true
          set :sessions, false
          set :public, Proc.new { Padrino.root('public', uri_root) }
          set :views, Proc.new { File.join(root,   "views") }
          set :images_path, Proc.new { File.join(public, "images") }
          # Padrino specific
          set :uri_root, "/"
          set :app_name, self.to_s.underscore.to_sym
          set :default_builder, 'StandardFormBuilder'
          set :flash, defined?(Rack::Flash)
          set :authentication, false
          # Padrino locale
          set :locale_path, Proc.new { Dir[File.join(self.root, "/locale/**/*.{rb,yml}")] }
          # Load the Global Configurations
          class_eval(&Padrino.apps_configuration) if Padrino.apps_configuration
        end

        ##
        # We need to add almost __sinatra__ images.
        #
        def default_routes!
          configure :development do
            get '/__sinatra__/:image.png' do
              content_type :png
              filename = File.dirname(__FILE__) + "/images/#{params[:image]}.png"
              send_file filename
            end
          end
        end

        ##
        # This filter it's used for know the format of the request, and automatically set the content type.
        #
        def default_filters!
          before do
            unless @_content_type
              @_content_type = :html
              response['Content-Type'] = 'text/html;charset=utf-8'
            end
          end
        end

        ##
        # This log errors for production environments
        #
        def default_errors!
          configure :production do
            error ::Exception do
              boom = env['sinatra.error']
              logger.error ["#{boom.class} - #{boom.message}:", *boom.backtrace].join("\n ")
              response.status = 500
              content_type 'text/html'
              '<h1>Internal Server Error</h1>'
            end
          end
        end

        ##
        # Requires the Padrino middleware
        #
        def register_initializers
          use Padrino::ShowExceptions         if show_exceptions?
          use Padrino::Logger::Rack, uri_root if Padrino.logger && logging?
          use Padrino::Reloader::Rack         if reload?
          use Rack::Flash, :sweep => true     if flash?
        end

        ##
        # Requires all files within the application load paths
        #
        def require_dependencies
          Padrino.set_load_paths(*load_paths)
          Padrino.require_dependencies(dependencies, :force => true)
        end
    end # self

    # TODO Remove deprecated render inclusion in a few versions
    # Detects if a user is incorrectly using 'render' and warns them about the fix
    # In 0.10.0, Padrino::Rendering now has to be explicitly included in the application
    def render(*args)
      if !defined?(DEFAULT_RENDERING_OPTIONS) && !@_render_included &&
          (args.size == 1 || (args.size == 2 && args[0].is_a?(String) && args[1].is_a?(Hash)))
        logger.warn "[Deprecation] Please 'register Padrino::Rendering' for each application as shown here:
          https://gist.github.com/1d36a35794dbbd664ea4 for 'render' to function as expected"
        self.class.instance_eval { register Padrino::Rendering }
        @_render_included = true
        render(*args)
      else # pass through, rendering is valid
        super(*args)
      end
    end # render method
  end # Application
end # Padrino