Merge in recent changes from v3-stable

i18n_v4
Thomas Reynolds 2014-04-08 09:27:18 -07:00
commit 4b53549ae4
250 changed files with 185 additions and 21146 deletions

View File

@ -23,3 +23,8 @@ matrix:
- rvm: jruby
- rvm: jruby-19mode
- rvm: rbx-2
env: TEST=true
before_install: git submodule update --init --recursive
script: bundle exec rake test
notifications:
slack: middleman:JW9OvXmn1m3XrSERe8866nBR

View File

@ -16,9 +16,21 @@ master
* Remove deprecated `request` instance
* Remove old module-style extension support
* Placed all `config.rb` evaluation inside the `ConfigContext` class
* Update Padrino to 0.12.0. Introduces BREAKING CHANGE for Haml. Helpers which take blocks used to require `-` instead of `=` to work correctly. Now, all helpers which output content should use `=`. See: http://www.padrinorb.com/blog/upgrading-padrino-from-0-11-x-to-0-12-0-guide
3.3.0-3.3.2
===
* Update Padrino to 0.12.1. Introduces BREAKING CHANGE for Haml. Helpers which take blocks used to require `-` instead of `=` to work correctly. Now, all helpers which output content should use `=`. See: http://www.padrinorb.com/blog/upgrading-padrino-from-0-11-x-to-0-12-0-guide
* Update Haml to 4.x
* Disable Webrick reverse DNS lookup, vastly improving performance when accessing from a VM.
* Ignore `node_modules` in FileWatcher
* Add `tzinfo-data` for Windows users.
* Prefer loading layouts from `layouts_dir`
* Add `before_build` hook.
* Depend on Erubis and remove support for specifying another ERb engine.
* Removed the ability to set the `sass_cache_path`.
* Improved /__middleman/ meta pages. For example, sitemap view now calls out ignored resources, prints data/options better, and shows which special locals are available on a page.
* Bump Uglifier to 2.5.x
3.2.2
===

View File

@ -29,7 +29,6 @@ module Middleman
desc 'version', 'Show version'
def version
require 'middleman-core/version'
say "Middleman #{Middleman::VERSION}"
end
@ -86,6 +85,9 @@ module Middleman
end
end
# Require the Middleman version
require 'middleman-core/version'
# Include the core CLI items
require 'middleman-cli/init'
require 'middleman-cli/extension'

View File

@ -185,9 +185,7 @@ module Middleman::Cli
@app.sitemap.resources.select do |resource|
resource.ext == '.css'
end.each do |resource|
@rack.get(URI.escape(resource.destination_path))
end
end.each(&method(:build_resource))
logger.debug '== Checking for Compass sprites'
@ -210,25 +208,29 @@ module Middleman::Cli
end
# Loop over all the paths and build them.
resources.each do |resource|
next if @config[:glob] && !File.fnmatch(@config[:glob], resource.destination_path)
output_path = render_to_file(resource)
if should_clean? && output_path.exist?
if RUBY_PLATFORM =~ /darwin/
# handle UTF-8-MAC filename on MacOS
@to_clean.delete(output_path.realpath.to_s.encode('UTF-8', 'UTF-8-MAC'))
else
@to_clean.delete(output_path.realpath)
end
end
end
resources.reject do |resource|
resource.ext == '.css'
end.each(&method(:build_resource))
::Middleman::Profiling.report('build')
end
def build_resource(resource)
return if @config[:glob] && !File.fnmatch(@config[:glob], resource.destination_path)
output_path = render_to_file(resource)
if should_clean? && output_path.exist?
if RUBY_PLATFORM =~ /darwin/
# handle UTF-8-MAC filename on MacOS
@to_clean.delete(output_path.realpath.to_s.encode('UTF-8', 'UTF-8-MAC'))
else
@to_clean.delete(output_path.realpath)
end
end
end
# Render a resource to a file.
#
# @param [Middleman::Sitemap::Resource] resource

View File

@ -11,7 +11,7 @@ Feature: select_tag helper
When I go to "/select_tag.html"
Then I should see:
"""
<select name="colors"><option value="">Choose a color</option>
<select name="colors" include_blank="Choose a color"><option value="">Choose a color</option>
<option value="red">red</option>
<option value="blue">blue</option>
<option value="blorange">blorange</option>

View File

@ -1,11 +1,8 @@
if !defined?(::Padrino::Helpers)
require 'vendored-middleman-deps/padrino-core-0.12.0/lib/padrino-core/support_lite'
require 'vendored-middleman-deps/padrino-helpers-0.12.0/lib/padrino-helpers'
require 'padrino-helpers'
# Don't fail on invalid locale, that's not what our current
# users expect.
::I18n.enforce_available_locales = false
end
# Don't fail on invalid locale, that's not what our current
# users expect.
::I18n.enforce_available_locales = false
class Padrino::Helpers::OutputHelpers::ErbHandler
# Force Erb capture not to use safebuffer
@ -65,16 +62,13 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension
end
def capture_html(*args, &block)
handler = auto_find_proper_handler(&block)
captured_block, captured_html = nil, ''
if handler && handler.engine_matches?(block)
captured_html, captured_block = handler.capture_from_template(*args, &block)
result = if handler = auto_find_proper_handler(&block)
handler.capture_from_template(*args, &block)
else
block.call(*args)
end
# invoking the block directly if there was no template
captured_html = block_given? && ( captured_block || block.call(*args) ) if captured_html.blank?
captured_html
ActiveSupport::SafeBuffer.new.safe_concat(result)
end
def auto_find_proper_handler(&block)

View File

@ -25,6 +25,7 @@
.value {
color: #002B36;
white-space: pre-wrap;
}
.description {
@ -33,4 +34,16 @@
.extensions .settings {
margin-left: 1em;
}
.inactive {
color: #999999;
}
.inactive:after {
content: "Inactive";
font-weight: bold;
color: #999999;
margin-left: 10px;
font-size: .7em;
}

View File

@ -168,6 +168,7 @@ body {
padding-right: 1em;
position: relative;
margin-top: 2em;
margin-bottom: 2em;
}
.container:after {
clear: both;
@ -355,14 +356,29 @@ pre .tex .formula {
#main {
display: inline;
float: left;
font-size: 120%;
font-size: 100%;
margin-left: 0;
margin-right: 1.20482%;
width: 100%;
}
#main h1 {
font-size: 2em;
font-size: 3em;
font-weight: bold;
margin-bottom: .5em;
}
#main h2 {
font-size: 1.5em;
font-size: 2em;
line-height: 1.2;
margin-bottom: 0.75em;
}
.nav-list {
list-style: none;
margin: 0;
padding: 0;
}
.nav-list a {
font-size: 1.4em;
font-weight: bold;
}

View File

@ -9,7 +9,7 @@ details > details {
}
details.resource > summary {
}
.resource-details {
@ -27,6 +27,7 @@ summary > i {
.resource-details th, .resource-details td {
padding: 0;
vertical-align: top;
}
.resource-details th {
@ -40,6 +41,22 @@ summary > i {
font-family: "Arvo","andale mono","lucida console",monospace;
}
.ignored > summary {
color: #999999;
}
.ignored i {
opacity: 0.4;
}
.ignored > summary:after {
content: "Ignored";
font-weight: bold;
color: #999999;
margin-left: 10px;
font-size: .7em;
}
details > summary:before {
content: "" !important;
display: inline-block;

View File

@ -1,3 +1,5 @@
require 'pp'
module Middleman
module MetaPages
# View class for a config entry
@ -13,22 +15,18 @@ module Middleman
content = ''
key_classes = ['key']
key_classes << 'modified' if @setting.value_set?
content << content_tag(:span, @setting.key.inspect, :class => key_classes.join(' '))
content << content_tag(:span, @setting.key.pretty_inspect.strip, :class => key_classes.join(' '))
content << ' = '
content << content_tag(:span, @setting.value.inspect, :class => 'value')
if @setting.default
content << content_tag(:span, @setting.value.pretty_inspect.strip, :class => 'value')
if @setting.default && @setting.value_set? && @setting.default != @setting.value
content << content_tag(:span, :class => 'default') do
if @setting.value_set?
"Default: #{@setting.default.inspect}"
else
'(Default)'
end
"(Default: #{@setting.default.inspect})"
end
end
if @setting.description
content << content_tag(:p, :class => 'description') do
CGI::escapeHTML(@setting.description)
@setting.description
end
end

View File

@ -1,7 +1,4 @@
if !defined?(::Padrino::Helpers)
require 'vendored-middleman-deps/padrino-core-0.12.0/lib/padrino-core/support_lite'
require 'vendored-middleman-deps/padrino-helpers-0.12.0/lib/padrino-helpers'
end
require 'padrino-helpers'
module Middleman
module MetaPages
@ -15,7 +12,9 @@ module Middleman
end
def render
content_tag :div, :class => 'resource-details' do
classes = 'resource-details'
classes << ' ignored' if @resource.ignored?
content_tag :div, :class => classes do
content_tag :table do
content = ''
resource_properties.each do |label, value|
@ -33,24 +32,34 @@ module Middleman
# A hash of label to value for all the properties we want to display
def resource_properties
props = {
'Path' => @resource.path,
'Build Path' => @resource.destination_path,
'URL' => content_tag(:a, @resource.url, :href => @resource.url),
'Source File' => @resource.source_file,
}
props = {}
props['Path'] = @resource.path
build_path = @resource.destination_path
build_path = 'Not built' if ignored?
props['Build Path'] = build_path if @resource.path != build_path
props['URL'] = content_tag(:a, @resource.url, :href => @resource.url) unless ignored?
props['Source File'] = @resource.source_file.sub(/^#{Regexp.escape(ENV['MM_ROOT'] + '/')}/, '')
data = @resource.data
props['Data'] = data unless data.empty?
props['Data'] = data.inspect unless data.empty?
options = @resource.metadata[:options]
props['Options'] = options unless options.empty?
meta = @resource.metadata
options = meta[:options]
props['Options'] = options.inspect unless options.empty?
locals = meta[:locals].keys
props['Locals'] = locals.join(', ') unless locals.empty?
props
end
def ignored?
@resource.ignored?
end
def css_classes
['resource']
['resource'].concat(ignored? ? ['ignored'] : [])
end
end
end

View File

@ -45,7 +45,11 @@ module Middleman
end
def css_classes
['tree']
['tree'].concat(ignored? ? ['ignored'] : [])
end
def ignored?
@children.values.all?(&:ignored?)
end
protected

View File

@ -13,7 +13,7 @@
<a href="/__middleman/">&laquo; back</a>
<h1>Middleman Configuration</h1>
<p>This page shows the current configuration of your Middleman application.</p>
<p>This page shows the current configuration of your Middleman application. <a href="http://middlemanapp.com/advanced/configuration/">Read more about configuring Middleman.</a></p>
<p>
<a href="#core">Core configuration</a>
@ -48,7 +48,7 @@
<% end %>
<% registered_extensions.keys.each do |ext_name| %>
<li><span class="extension"><%= ext_name.inspect %></span> (Inactive)</li>
<li><span class="extension inactive"><%= ext_name.inspect %></span></li>
<% end %>
</ul>
</article>

View File

@ -5,17 +5,27 @@
<title>Middleman Info</title>
<link type="text/css" rel="stylesheet" href="/__middleman/assets/meta.css">
</head>
<body>
<div class="container">
<h1>Middleman Information</h1>
<article id="main">
<h1>Middleman Information</h1>
<ul>
<li><a href="/__middleman/sitemap/">Sitemap</a></li>
<li><a href="/__middleman/config/">Configuration</a></li>
<li><a href="http://middlemanapp.com">Middleman Guides</a></li>
</ul>
<ul class="nav-list">
<li>
<a href="/__middleman/sitemap/">Sitemap</a>
<p>The structure of your site as understood by Middleman.</p>
</li>
<li>
<a href="/__middleman/config/">Configuration</a>
<p>All available configuration options and their current values.</p>
</li>
<li>
<a href="http://middlemanapp.com">Middleman Guides</a>
<p>Documentation about Middleman's features.</p>
</li>
</ul>
</article>
</div>
</body>
</html>

View File

@ -2,17 +2,17 @@
<html>
<head>
<meta charset="utf-8">
<title>Middleman Sitemap</title>
<link type="text/css" rel="stylesheet" href="/__middleman/assets/meta.css">
<link type="text/css" rel="stylesheet" href="/__middleman/assets/sitemap.css">
<script src="/__middleman/assets/jquery-1.8.2.min.js"></script>
<script src="/__middleman/assets/jquery.details-1.6.min.js"></script>
<script src="/__middleman/assets/sitemap.js"></script>
</head>
<body>
<div class="container">
<article id="main">
@ -20,7 +20,7 @@
<h1>Middleman Sitemap</h1>
<p>This page shows all of the pages in
the <a href="http://middlemanapp.com/advanced/sitemap/">sitemap</a>,
<a href="http://middlemanapp.com/advanced/sitemap/">the sitemap</a>,
Middleman's view of your site.</p>
<%= sitemap_tree.render %>
@ -28,4 +28,3 @@
</div>
</body>
</html>

View File

@ -15,7 +15,7 @@ module Middleman
# @return [void]
def start(opts={})
@options = opts
@host = @options[:host] || Socket.gethostname
@host = @options[:host] || Socket.ip_address_list.find(&:ipv4_private?).ip_address
@port = @options[:port] || DEFAULT_PORT
mount_instance(new_app)
@ -166,9 +166,10 @@ module Middleman
# @return [void]
def setup_webrick(is_logging)
http_opts = {
:BindAddress => host,
:Port => port,
:AccessLog => []
:BindAddress => host,
:Port => port,
:AccessLog => [],
:DoNotReverseLookup => true
}
if is_logging

View File

@ -1,4 +1,5 @@
require 'sass'
require 'compass/import-once'
module Middleman
module Renderers
@ -21,6 +22,8 @@ module Middleman
# Tell Tilt to use it as well (for inline scss blocks)
::Tilt.register 'scss', ScssPlusCSSFilenameTemplate
::Tilt.prefer(ScssPlusCSSFilenameTemplate)
::Compass::ImportOnce.activate!
end
alias :included :registered

View File

@ -101,7 +101,7 @@ module Middleman
relative_source = Pathname(source_file).relative_path_from(Pathname(app.root))
instrument 'render.resource', :path => relative_source do
instrument 'render.resource', :path => relative_source, :destination_path => destination_path do
md = metadata.dup
opts = md[:options].deep_merge(opts)
locs = md[:locals].deep_merge(locs)

View File

@ -3,10 +3,11 @@ MIDDLEMAN_BIN_PATH = File.join(MIDDLEMAN_ROOT_PATH, 'bin')
ENV['PATH'] = "#{MIDDLEMAN_BIN_PATH}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
require 'aruba/cucumber'
require 'aruba/jruby'
require 'middleman-core/step_definitions/middleman_steps'
require 'middleman-core/step_definitions/builder_steps'
require 'middleman-core/step_definitions/server_steps'
Before do
@aruba_timeout_seconds = 30
@aruba_timeout_seconds = RUBY_PLATFORM == 'java' ? 120 : 60
end

View File

@ -1,5 +0,0 @@
lib/**/*.rb
bin/*
-
README.rdoc
LICENSE.txt

View File

@ -1,22 +0,0 @@
## MAC OS
.DS_Store
## TEXTMATE
*.tmproj
tmtags
## EMACS
*~
\#*
.\#*
## VIM
*.swp
## PROJECT::GENERAL
coverage
rdoc
pkg
## PROJECT::SPECIFIC
test/tmp/*

View File

@ -1 +0,0 @@
--title 'Padrino Core Documentation' --protected

View File

@ -1,20 +0,0 @@
Copyright (c) 2011 Padrino
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,294 +0,0 @@
= Padrino (padrino-core)
Padrino is the godfather of Sinatra.
== Preface
Padrino is a ruby framework built upon the excellent {Sinatra Microframework}[http://www.sinatrarb.com].
Sinatra is a DSL for creating simple web applications in Ruby with speed and minimal effort.
This framework tries hard to make it as fun and easy as possible to code much more advanced web applications by
building upon the Sinatra philosophies and foundation.
== Introduction
Many people love Sinatra's simplicity and lightweight but often quickly come to miss a great deal
of functionality provided by other web frameworks such as Rails when building non-trivial applications.
Our goal with this framework is to match the essence of Sinatra and at the same time create a standard library
of tools, helpers and components that will make Sinatra suitable for more complex applications.
Here is a brief overview of functionality provided by the Padrino framework:
Agnostic:: Full support for many popular testing, templating, mocking, and data storage choices.
Generators:: Create Padrino applications, models, controllers i.e: padrino-gen project.
Mountable:: Unlike other ruby frameworks, principally designed for mounting multiple apps.
Routing:: Full url named routes, named params, before/after filter support.
Tag Helpers:: View helpers such as: tag, content_tag, input_tag.
Asset Helpers:: View helpers such as: link_to, image_tag, javascript_include_tag.
Form Helpers:: Builder support such as: form_tag, form_for, field_set_tag, text_field.
Text Helpers:: Useful formatting like: time_ago_in_words, js_escape_html, sanitize_html.
Mailer:: Fast and simple delivery support for sending emails (akin to ActionMailer).
Admin:: Builtin Admin interface (like Django)
Logging:: Provide a unified logger that can interact with your ORM or any library.
Reloading:: Automatically reloads server code during development.
Localization:: Full support of I18n language localization and can auto-set user's locale.
Keep in mind, the user will be able to pull in these components
{seperately into existing Sinatra applications}[http://www.padrinorb.com/guides/standalone-usage-in-sinatra]
or use them altogether for a comprehensive upgrade to Sinatra (a full-stack Padrino application).
== Installation
To install the padrino framework, simply grab the latest version from gemcutter:
$ sudo gem install padrino
This will install the necessary padrino gems to get you started.
Now you are ready to use this gem to enhance your sinatra projects or to create new Padrino applications.
For a more detailed look at Padrino installation,
check out the {Installation Guide}[http://www.padrinorb.com/guides/installation].
== Usage
Padrino is a framework which builds on the existing functionality and Sinatra and provides a variety of
additional tools and helpers to build upon that foundation. This README and Padrino documentation in general will focus
on the enhancements to the core Sinatra functionality. To use Padrino, one should be familiar with the basic
usage of Sinatra itself.
Please check out the
{Understanding Sinatra}[http://www.padrinorb.com/guides/underlying-sinatra-overview] guide
to learn more about these fundamentals.
For information on how to use a specific gem in isolation within an existing Sinatra project, checkout the guide for
{Using Padrino in Sinatra}[http://www.padrinorb.com/guides/standalone-usage-in-sinatra].
== Getting Started
Once a developer understands Sinatra, Padrino is quite easy to get comfortable with since Padrino is simply a superset
of existing Sinatra Functionality! Best way to get started with building Padrino applications is to read following resources:
* {Blog Tutorial}[http://www.padrinorb.com/guides/blog-tutorial] - Step-by-step guide to building a blog application with Padrino.
* {Quick Overview}[http://www.padrinorb.com/guides/basic-projects] - Outlines basic generation commands.
* {Padrino Examples}[http://www.padrinorb.com/guides/examples] - List of known Padrino applications which can serve as examples.
== Enhanced Base Application (padrino-core)
Sinatra has support for classes which can be extended to create an application: <tt>Sinatra::Base</tt> and <tt>Sinatra::Application</tt>
These classes can be extended in order to create a Sinatra web application. These classes provide support for all the basic
functionality afforded by Sinatra.
Padrino has support for an enhanced base application class <tt>Padrino::Application</tt>. <tt>Padrino::Application</tt>
expands the capabilities of Sinatra::Application and automatically provides the resulting application access to all of
the padrino framework's functionalities.
=== Simple Application Definition
Let us first take a look at the simplest possible Padrino application:
# app.rb
PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
require 'padrino'
Padrino.load!
class SimpleApp < Padrino::Application
get '/' do
'Hello world'
end
# and for read better we can divide with controllers
controller '/admin' do
get '/foo' do
'Url is /admin/foo'
end
end
end
=== Enhanced Route Definitions and Controllers
For a complete overview of the Padrino routing and controller system,
check out the {Routing and Controller guide}[http://www.padrinorb.com/guides/controllers].
Suppose we wanted to add additional routes to our Padrino application, and we want to organize the routes
within a more structured layout. Simply add a <tt>controllers</tt> or <tt>app/controllers</tt> folder and create a file as such:
# Simple Example
SimpleApp.controllers do
get "/test" do
"Text to return"
end
end
You can also do more complex route alias definitions:
# app/controllers/example.rb
SimpleApp.controllers :posts do
get :index do
...
end
get :show, :with => :id do
# url generated is '/posts/show/:id'
# access params[:id]
end
end
as well as mapping the route aliases to an explicit url:
# app/controllers/example.rb
SimpleApp.controllers do
get :index, :map => '/index' do
...
end
get :account, :map => '/the/accounts/:name/and/:id' do
# access params[:name] and params[:index]
end
end
and even configure the +provides+ for each route:
# app/controllers/example.rb
SimpleApp.controllers :admin do
get :show, :with => :id, :provides => :js do
"Url is /admin/show/#{params[:id]}.#{params[:format]}"
end
get :other, :with => [:id, :name], :provides => [:html, :json] do
case content_type
when :js then ... end
when :json then ... end
end
end
end
or auto lookup for current locale or content_type
# app/controllers/example.rb
SimpleApp.controllers :admin do
get :show, :with => :id, :provides => [:html, :js] do
render "admin/show"
end
end
When you visit :+show+ and your I18n.locale == :ru Padrino try to look for "admin/show.ru.js.*" if nothing match that path
they try "admin/show.ru.*" then "admin/show.js.*" if none match return "admin/show.erb" (or other engine i.e. haml)
For a complete overview of the routing and controller system, check out the
{Routing and Controller guide}[http://www.padrinorb.com/guides/controllers].
=== Rendering
Unlike Sinatra, Padrino supports automatic template lookups such as:
# searches for 'account/index.{erb,haml,...}
render 'account/index'
This render does not require any template engine to be specified and will choose the first one that is discovered.
The existing render function works as well if an engine type should be specified:
# example.haml
render :haml, 'account/index'
For a complete overview of the Padrino rendering system, check out the
{Routing and Controller guide}[http://www.padrinorb.com/guides/controllers].
=== Layout
With Padrino you can (like rails do) use for your custom layout, disable it
class SimpleApp < Padrino::Application
# Disable layouts
disable layout
# Use the layout located in views/layouts/custom.haml
layout :custom
For a complete overview of the layout functionality,
check out the {Routing and Controller guide}[http://www.padrinorb.com/guides/controllers].
=== Mounting Applications
Padrino applications are all automatically mountable into other Padrino projects. This means that a given Padrino
project directory can easily mount multiple applications. This allows for better organization of complex applications,
re-usable applications that can be applied (i.e admin, auth, blog) and even more flexibility.
You can think of mountable applications as a 'full-featured' merb slice or rails engine. Instead of a separate construct,
any application can simply be packaged and mounted into another project.
Padrino stores application mounting information by default within <tt>config/apps.rb</tt>. This file is intended
to keep all information regarding what applications are mounted to which uri's.
For a complete look at mounting applications within a Padrino project,
check out the guide on {Mounting Applications}[http://www.padrinorb.com/guides/mounting-applications].
=== Auto Load Paths
Padrino also intelligently supports requiring useful files within your application automatically and provides
functionality for easily splitting up your application into separate files. Padrino automatically requires <tt>config/database.rb</tt>
as a convention for establishing database connection. Also, any files within the <tt>lib</tt> folder will be required
automatically by Padrino.
For a complete overview of auto-loaded paths within Padrino,
check out the {Padrino Development Guide}[http://www.padrinorb.com/guides/development-and-terminal-commands].
=== Application Logging
Padrino also supports robust logging capabilities. By default, logging information will
go to the STDOUT in development (for use in a console) and in an environment-specific log file <tt>log/development.log</tt>
in test and production environments.
To use the logger within a Padrino application, simply refer to the <tt>logger</tt> method accessible
within your app and any controller or views:
# controllers/example.rb
SimpleApp.controllers do
get("/test") { logger.info "This is a test" }
end
For a complete overview of Padrino logger functionality, check out the
{Padrino Development Guide}[http://www.padrinorb.com/guides/development-and-terminal-commands].
=== Development Reloader
Padrino applications also have the enabled ability to automatically reload all changing application files without
the need to restart the server. Through the use of a customized Rack middleware, all files on the 'load path'
are monitored and reloaded whenever changes are applied.
This makes rapid development much easier and provides a better alternative to 'shotgun' or 'rerun'
which requires the application server to be restarted which makes requests take much longer to complete.
For a complete overview of code reloading in development,
check out the {Padrino Development Guide}[http://www.padrinorb.com/guides/development-and-terminal-commands].
=== Terminal Commands
Padrino also comes equipped with multiple useful terminal commands which can be activated to perform
common tasks such as starting / stopping the application, executing the unit tests or activating an irb session.
The following commands are available:
# starts the app server (non-daemonized)
$ padrino start
# starts the app server (daemonized) with given port, environment and adapter
$ padrino start -d -p 3000 -e development -a thin
# Stops a daemonized app server
$ padrino stop
# Bootup the Padrino console (irb)
$ padrino console
# Run/List tasks
$ padrino rake
You can also create custom rake tasks as well. Using these commands can simplify common tasks
making development that much smoother.
For a complete overview of Padrino terminal commands, check out the
{Padrino Commands Guide}[http://www.padrinorb.com/guides/development-and-terminal-commands].
== Copyright
Copyright (c) 2011-2013 Padrino. See LICENSE for details.

View File

@ -1,5 +0,0 @@
# coding:utf-8
RAKE_ROOT = __FILE__
require 'rubygems'
require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper')

View File

@ -1,9 +0,0 @@
#!/usr/bin/env ruby
require 'rubygems' unless defined?(Gem)
require 'bundler/setup' if %w(Gemfile .components).all? { |f| File.exist?(f) }
padrino_core_path = File.expand_path('../../lib', __FILE__)
$:.unshift(padrino_core_path) if File.directory?(padrino_core_path) && !$:.include?(padrino_core_path)
require 'padrino-core/cli/base'
Padrino::Cli::Base.start(ARGV)

View File

@ -1,196 +0,0 @@
require 'sinatra/base'
require 'padrino-core/version'
require 'padrino-core/support_lite'
require 'padrino-core/application'
require 'padrino-core/caller'
require 'padrino-core/command'
require 'padrino-core/loader'
require 'padrino-core/logger'
require 'padrino-core/mounter'
require 'padrino-core/reloader'
require 'padrino-core/router'
require 'padrino-core/server'
require 'padrino-core/tasks'
require 'padrino-core/module'
if ENV["PADRINO_ENV"]
warn 'Environment variable PADRINO_ENV is deprecated. Please, use RACK_ENV.'
ENV["RACK_ENV"] ||= ENV["PADRINO_ENV"]
end
RACK_ENV = ENV["RACK_ENV"] ||= "development" unless defined?(RACK_ENV)
PADRINO_ROOT = ENV["PADRINO_ROOT"] ||= File.dirname(Padrino.first_caller) unless defined?(PADRINO_ROOT)
module Padrino
class ApplicationLoadError < RuntimeError # @private
end
extend Loader
class << self
##
# Helper method for file references.
#
# @param [Array<String>] args
# The directories to join to {PADRINO_ROOT}.
#
# @return [String]
# The absolute path.
#
# @example
# # Referencing a file in config called settings.yml
# Padrino.root("config", "settings.yml")
# # returns PADRINO_ROOT + "/config/setting.yml"
#
def root(*args)
File.expand_path(File.join(PADRINO_ROOT, *args))
end
##
# Helper method that return {RACK_ENV}.
#
# @return [Symbol]
# The Padrino Environment.
#
def env
@_env ||= RACK_ENV.to_s.downcase.to_sym
end
##
# The resulting rack builder mapping each 'mounted' application.
#
# @return [Padrino::Router]
# The router for the application.
#
# @raise [ApplicationLoadError]
# No applications were mounted.
#
def application
raise ApplicationLoadError, "At least one app must be mounted!" unless Padrino.mounted_apps.present?
router = Padrino::Router.new
Padrino.mounted_apps.each { |app| app.map_onto(router) }
middleware.present? ? add_middleware(router) : router
end
##
# Configure Global Project Settings for mounted apps. These can be overloaded
# in each individual app's own personal configuration. This can be used like:
#
# @yield []
# The given block will be called to configure each application.
#
# @example
# Padrino.configure_apps do
# enable :sessions
# disable :raise_errors
# end
#
def configure_apps(&block)
return unless block_given?
global_configurations << block
end
##
# Stores global configuration blocks.
#
def global_configurations
@_global_configurations ||= []
end
##
# Set +Encoding.default_internal+ and +Encoding.default_external+
# to +Encoding::UFT_8+.
#
# Please note that in +1.9.2+ with some template engines like +haml+
# you should turn off Encoding.default_internal to prevent problems.
#
# @see https://github.com/rtomayko/tilt/issues/75
#
# @return [NilClass]
#
def set_encoding
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8
nil
end
##
# Creates Rack stack with the router added to the middleware chain.
#
def add_middleware(router)
builder = Rack::Builder.new
middleware.each{ |mw,args,block| builder.use(mw, *args, &block) }
builder.run(router)
builder.to_app
end
##
# A Rack::Builder object that allows to add middlewares in front of all
# Padrino applications.
#
# @return [Array<Array<Class, Array, Proc>>]
# The middleware classes.
#
def middleware
@middleware ||= []
end
##
# Clears all previously configured middlewares.
#
# @return [Array]
# An empty array
#
def clear_middleware!
@middleware = []
end
##
# Convenience method for adding a Middleware to the whole padrino app.
#
# @param [Class] m
# The middleware class.
#
# @param [Array] args
# The arguments for the middleware.
#
# @yield []
# The given block will be passed to the initialized middleware.
#
def use(mw, *args, &block)
middleware << [mw, args, block]
end
##
# Registers a gem with padrino. This relieves the caller from setting up
# loadpaths by itself and enables Padrino to look up apps in gem folder.
#
# The name given has to be the proper gem name as given in the gemspec.
#
# @param [String] name
# The name of the gem being registered.
#
# @param [Module] main_module
# The main module of the gem.
#
# @returns The root path of the loaded gem
def gem(name, main_module)
_, spec = Gem.loaded_specs.find{|spec_pair| spec_pair[0] == name }
gems << spec
modules << main_module
spec.full_gem_path
end
##
# @returns [Gem::Specification]
def gems
@gems ||= []
end
##
# @returns [<Padrino::Module>]
def modules
@modules ||= []
end
end
end

View File

@ -1,388 +0,0 @@
require 'padrino-core/application/flash'
require 'padrino-core/application/rendering'
require 'padrino-core/application/routing'
require 'padrino-core/application/show_exceptions'
require 'padrino-core/application/authenticity_token'
module Padrino
##
# 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
# Support for advanced routing, controllers, url_for
register Padrino::Routing
##
# Returns the logger for this application.
#
# @return [Padrino::Logger] Logger associated with this app.
#
def logger
Padrino.logger
end
# TODO: Remove this hack after getting rid of thread-unsafe http_router:
alias_method :original_call, :call
def call(*args)
settings.init_mutex.synchronize do
instance_eval{ undef :call }
class_eval{ alias_method :call, :original_call }
instance_eval{ undef :original_call }
super(*args)
end
end
class << self
def inherited(base)
begun_at = Time.now
CALLERS_TO_IGNORE.concat(PADRINO_IGNORE_CALLERS)
base.default_configuration!
logger.devel :setup, begun_at, base
super(base)
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.
#
# @return [TrueClass]
#
# @example
# MyApp.reload!
#
def reload!
logger.devel "Reloading application #{settings}"
reset!
reset_router!
Padrino.require_dependencies(settings.app_file, :force => true)
require_dependencies
default_filters!
default_routes!
default_errors!
I18n.reload! if defined?(I18n)
true
end
##
# Resets application routes to only routes not defined by the user.
#
# @return [TrueClass]
#
# @example
# MyApp.reset_routes!
#
def reset_routes!
reset_router!
default_routes!
true
end
##
# Returns the routes of our app.
#
# @example
# MyApp.routes
#
def routes
router.routes
end
##
# Returns an absolute path of view in application views folder.
#
# @example
# Admin.view_path 'users/index' #=> "/home/user/test/admin/views/users/index"
#
def view_path(view)
File.expand_path(view, views)
end
##
# Returns an absolute path of application layout.
#
# @example
# Admin.layout_path :application #=> "/home/user/test/admin/views/layouts/application"
#
def layout_path(layout)
view_path("layouts/#{layout}")
end
##
# Setup the application by registering initializers, load paths and logger.
# Invoked automatically when an application is first instantiated.
#
# @return [TrueClass]
#
def setup_application!
return if @_configured
settings.require_dependencies
settings.default_filters!
settings.default_routes!
settings.default_errors!
if defined?(I18n)
Reloader.special_files += settings.locale_path
I18n.load_path << settings.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).
#
# @see Padrino::Server#start
#
def run!(options={})
return unless Padrino.load!
Padrino.mount(settings.to_s).to('/')
Padrino.run!(options)
end
##
# @return [Array]
# directory that need to be added to +$LOAD_PATHS+ from this application
#
def load_paths
@_load_paths ||= [
'models',
'lib',
'mailers',
'controllers',
'helpers',
].map { |path| File.join(settings.root, path) }
end
##
# Returns default list of path globs to load as dependencies.
# Appends custom dependency patterns to the be loaded for your Application.
#
# @return [Array]
# list of path globs to load as dependencies
#
# @example
# MyApp.dependencies << "#{Padrino.root}/uploaders/**/*.rb"
# MyApp.dependencies << Padrino.root('other_app', 'controllers.rb')
#
def dependencies
[
'urls.rb',
'config/urls.rb',
'mailers/*.rb',
'mailers.rb',
'controllers/**/*.rb',
'controllers.rb',
'helpers/**/*.rb',
'helpers.rb',
].map { |file| Dir[File.join(settings.root, file)] }.flatten
end
##
# An array of file to load before your app.rb, basically are files
# which our app depends on.
#
# By default we look for files:
#
# # List of default files that we are looking for:
# yourapp/models.rb
# yourapp/models/**/*.rb
# yourapp/lib.rb
# yourapp/lib/**/*.rb
#
# @example Adding a custom prerequisite
# MyApp.prerequisites << Padrino.root('my_app', 'custom_model.rb')
#
def prerequisites
@_prerequisites ||= []
end
def default(option, *args, &block)
set(option, *args, &block) unless respond_to?(option)
end
protected
##
# Defines default settings for Padrino application.
#
def default_configuration!
set :app_file, File.expand_path(caller_files.first || $0)
set :app_name, settings.to_s.underscore.to_sym
set :environment, Padrino.env
set :reload, Proc.new { development? }
set :logging, Proc.new { development? }
set :method_override, true
set :default_builder, 'StandardFormBuilder'
# TODO: Remove this hack after getting rid of thread-unsafe http_router:
set :init_mutex, Mutex.new
# TODO: Remove this line after sinatra version up.
set :add_charset, %w[javascript xml xhtml+xml].map {|t| "application/#{t}" }
default_paths!
default_security!
global_configuration!
setup_prerequisites!
end
def setup_prerequisites!
prerequisites.concat(default_prerequisites).uniq!
Padrino.require_dependencies(prerequisites)
end
def default_paths!
set :locale_path, Proc.new { Dir.glob File.join(root, 'locale/**/*.{rb,yml}') }
set :views, Proc.new { File.join(root, 'views') }
set :uri_root, '/'
set :public_folder, Proc.new { Padrino.root('public', uri_root) }
set :images_path, Proc.new { File.join(public_folder, 'images') }
end
def default_security!
set :protection, :except => :path_traversal
set :authentication, false
set :sessions, false
set :protect_from_csrf, false
set :allow_disabled_csrf, false
end
##
# Applies global padrino configuration blocks to current application.
#
def global_configuration!
Padrino.global_configurations.each do |configuration|
class_eval(&configuration)
end
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
response['Content-Type'] = 'text/html;charset=utf-8' unless @_content_type
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 unless errors.has_key?(::Exception)
end
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
##
# Returns globs of default paths of application prerequisites.
#
def default_prerequisites
[
'/models.rb',
'/models/**/*.rb',
'/lib.rb',
'/lib/**/*.rb',
].map{ |glob| File.join(settings.root, glob) }
end
private
# Overrides the default middleware for Sinatra based on Padrino conventions.
# Also initializes the application after setting up the middleware.
def setup_default_middleware(builder)
setup_sessions builder
builder.use Padrino::ShowExceptions if show_exceptions?
builder.use Padrino::Logger::Rack, uri_root if Padrino.logger && logging?
builder.use Padrino::Reloader::Rack if reload?
builder.use Rack::MethodOverride if method_override?
builder.use Rack::Head
register Padrino::Flash
setup_protection builder
setup_csrf_protection builder
setup_application!
end
# sets up csrf protection for the app:
def setup_csrf_protection(builder)
check_csrf_protection_dependency
if protect_from_csrf?
options = options_for_csrf_protection_setup
options.merge!(protect_from_csrf) if protect_from_csrf.kind_of?(Hash)
builder.use(options[:except] ? Padrino::AuthenticityToken : Rack::Protection::AuthenticityToken, options)
end
end
# returns the options used in the builder for csrf protection setup
def options_for_csrf_protection_setup
options = { :logger => logger }
if allow_disabled_csrf?
options.merge!({
:reaction => :report,
:report_key => 'protection.csrf.failed'
})
end
options
end
# throw an exception if the protect_from_csrf is active but sessions not.
def check_csrf_protection_dependency
if (protect_from_csrf? && !sessions?) && !defined?(Padrino::IGNORE_CSRF_SETUP_WARNING)
warn(<<-ERROR)
`protect_from_csrf` is activated, but `sessions` seem to be off. To enable csrf
protection, use:
enable :sessions
or deactivate protect_from_csrf:
disable :protect_from_csrf
If you use a different session store, ignore this warning using:
# in boot.rb:
Padrino::IGNORE_CSRF_SETUP_WARNING = true
ERROR
end
end
end
end
end

View File

@ -1,25 +0,0 @@
module Padrino
class AuthenticityToken < Rack::Protection::AuthenticityToken
def initialize(app, options = {})
@app = app
@except = options[:except]
@except = Array(@except) unless @except.is_a?(Proc)
super
end
def call(env)
if except?(env)
@app.call(env)
else
super
end
end
def except?(env)
return false unless @except
path_info = env['PATH_INFO']
@except.is_a?(Proc) ? @except.call(env) : @except.any?{|path|
path.is_a?(Regexp) ? path.match(path_info) : path == path_info }
end
end
end

View File

@ -1,229 +0,0 @@
module Padrino
module Flash
class << self
def registered(app)
app.helpers Helpers
app.after do
session[:_flash] = @_flash.next if @_flash
end
end
end
class Storage
include Enumerable
# @private
def initialize(session=nil)
@_now = session || {}
@_next = {}
end
def now
@_now
end
def next
@_next
end
# @since 0.10.8
# @api public
def [](type)
@_now[type]
end
# @since 0.10.8
# @api public
def []=(type, message)
@_next[type] = message
end
# @since 0.10.8
# @api public
def delete(type)
@_now.delete(type)
self
end
# @since 0.10.8
# @api public
def keys
@_now.keys
end
# @since 0.10.8
# @api public
def key?(type)
@_now.key?(type)
end
# @since 0.10.8
# @api public
def each(&block)
@_now.each(&block)
end
# @since 0.10.8
# @api public
def replace(hash)
@_now.replace(hash)
self
end
# @since 0.10.8
# @api public
def update(hash)
@_now.update(hash)
self
end
alias_method :merge!, :update
# @since 0.10.8
# @api public
def sweep
@_now.replace(@_next)
@_next = {}
self
end
# @since 0.10.8
# @api public
def keep(key = nil)
if key
@_next[key] = @_now[key]
else
@_next.merge!(@_now)
end
self
end
# @since 0.10.8
# @api public
def discard(key = nil)
if key
@_next.delete(key)
else
@_next = {}
end
self
end
# @since 0.10.8
# @api public
def clear
@_now.clear
end
# @since 0.10.8
# @api public
def empty?
@_now.empty?
end
# @since 0.10.8
# @api public
def to_hash
@_now.dup
end
def length
@_now.length
end
alias_method :size, :length
# @since 0.10.8
# @api public
def to_s
@_now.to_s
end
# @since 0.10.8
# @api public
def error=(message)
self[:error] = message
end
# @since 0.10.8
# @api public
def error
self[:error]
end
# @since 0.10.8
# @api public
def notice=(message)
self[:notice] = message
end
# @since 0.10.8
# @api public
def notice
self[:notice]
end
# @since 0.10.8
# @api public
def success=(message)
self[:success] = message
end
# @since 0.10.8
# @api public
def success
self[:success]
end
end # Storage
module Helpers
###
# Overloads the existing redirect helper in-order to provide support for
# flash messages.
#
# @overload redirect(url)
# @param [String] url
#
# @overload redirect(url, status_code)
# @param [String] url
# @param [Fixnum] status_code
#
# @overload redirect(url, status_code, flash_messages)
# @param [String] url
# @param [Fixnum] status_code
# @param [Hash] flash_messages
#
# @overload redirect(url, flash_messages)
# @param [String] url
# @param [Hash] flash_messages
#
# @example
# redirect(dashboard, success: :user_created)
# redirect(new_location, 301, notice: 'This page has moved. Please update your bookmarks!!')
#
# @since 0.10.8
# @api public
def redirect(url, *args)
flashes = args.extract_options!
flashes.each do |type, message|
message = I18n.translate(message) if message.is_a?(Symbol) && defined?(I18n)
flash[type] = message
end
super(url, args)
end
alias_method :redirect_to, :redirect
###
# Returns the flash storage object.
#
# @return [Storage]
#
# @since 0.10.8
# @api public
def flash
@_flash ||= Storage.new(env['rack.session'] ? session[:_flash] : {})
end
end
end
end

View File

@ -1,325 +0,0 @@
require 'padrino-core/support_lite' unless defined?(SupportLite)
module Padrino
##
# Padrino enhances the Sinatra 'render' method to have support for
# automatic template engine detection, enhanced layout functionality,
# locale enabled rendering, among other features.
#
module Rendering
##
# A SafeTemplate assumes that its output is safe.
#
module SafeTemplate
def render(*)
super.html_safe
end
end
##
# Exception responsible for when an expected template did not exist.
#
class TemplateNotFound < RuntimeError
end
##
# This is an array of file patterns to ignore. If your editor add a
# suffix during editing to your files please add it like:
#
# @example
# Padrino::Rendering::IGNORE_FILE_PATTERN << /~$/
#
IGNORE_FILE_PATTERN = [
/~$/ # This is for Gedit
] unless defined?(IGNORE_FILE_PATTERN)
##
# Default options used in the resolve_template-method.
#
DEFAULT_RENDERING_OPTIONS = { :strict_format => false, :raise_exceptions => true } unless defined?(DEFAULT_RENDERING_OPTIONS)
class << self
##
# Default engine configurations for Padrino::Rendering.
#
# @return {Hash<Symbol,Hash>}
# The configurations, keyed by engine.
def engine_configurations
@engine_configurations ||= {}
end
def registered(app)
included(app)
engine_configurations.each do |engine, configs|
app.set engine, configs
end
end
def included(base)
base.send(:include, InstanceMethods)
base.extend(ClassMethods)
end
end
##
# Class methods responsible for rendering templates as part of a request.
#
module ClassMethods
##
# Use layout like rails does or if a block given then like sinatra.
# If used without a block, sets the current layout for the route.
#
# By default, searches in your:
#
# +app+/+views+/+layouts+/+application+.(+haml+|+erb+|+xxx+)
# +app+/+views+/+layout_name+.(+haml+|+erb+|+xxx+)
#
# If you define +layout+ :+custom+ then searches for your layouts in
# +app+/+views+/+layouts+/+custom+.(+haml+|+erb+|+xxx+)
# +app+/+views+/+custom+.(+haml+|+erb+|+xxx+)
#
# @param [Symbol] name (:layout)
# The layout to use.
#
# @yield []
#
def layout(name=:layout, &block)
return super(name, &block) if block_given?
@layout = name
end
##
# Returns the cached template file to render for a given url,
# content_type and locale.
#
# @param [Array<template_path, content_type, locale>] render_options
#
def fetch_template_file(render_options)
(@_cached_templates ||= {})[render_options]
end
##
# Caches the template file for the given rendering options.
#
# @param [String] template_file
# The path of the template file.
#
# @param [Array<template_path, content_type, locale>] render_options
#
def cache_template_file!(template_file, render_options)
(@_cached_templates ||= {})[render_options] = template_file || []
end
##
# Returns the cached layout path.
#
# @param [Symbol, nil] given_layout
# The requested layout.
#
def fetch_layout_path(given_layout=nil)
layout_name = given_layout || @layout || :application
@_cached_layout ||= {}
cached_layout_path = @_cached_layout[layout_name]
return cached_layout_path if cached_layout_path
has_layout_at_root = Dir["#{views}/#{layout_name}.*"].any?
layout_path = has_layout_at_root ? layout_name.to_sym : File.join('layouts', layout_name.to_s).to_sym
@_cached_layout[layout_name] = layout_path unless reload_templates?
layout_path
end
end
# Instance methods that allow enhanced rendering to function properly in Padrino.
module InstanceMethods
attr_reader :current_engine
##
# Get/Set the content_type
#
# @param [String, nil] type
# The Content-Type to use.
#
# @param [Symbol, nil] type.
# Look and parse the given symbol to the matched Content-Type.
#
# @param [Hash] params
# Additional params to append to the Content-Type.
#
# @example
# case content_type
# when :js then do_some
# when :css then do_another
# end
#
# content_type :js
# # => set the response with 'application/javascript' Content-Type
# content_type 'text/html'
#
# # => set directly the Content-Type to 'text/html'
#
def content_type(type=nil, params={})
unless type.nil?
super(type, params)
@_content_type = type
end
@_content_type
end
private
##
# Enhancing Sinatra render functionality for:
#
# * Using layout similar to rails
# * Use render 'path/to/my/template' (without symbols)
# * Use render 'path/to/my/template' (with engine lookup)
# * Use render 'path/to/template.haml' (with explicit engine lookup)
# * Use render 'path/to/template', :layout => false
# * Use render 'path/to/template', :layout => false, :engine => 'haml'
#
def render(engine, data=nil, options={}, locals={}, &block)
# If engine is nil, ignore engine parameter and shift up all arguments
# render nil, "index", { :layout => true }, { :localvar => "foo" }
engine, data, options = data, options, locals if engine.nil? && data
# Data is a hash of options when no engine isn't explicit
# render "index", { :layout => true }, { :localvar => "foo" }
# Data is options, and options is locals in this case
data, options, locals = nil, data, options if data.is_a?(Hash)
# If data is unassigned then this is a likely a template to be resolved
# This means that no engine was explicitly defined
data, engine = *resolve_template(engine, options.dup) if data.nil?
# Use @layout if it exists
layout_was = options[:layout]
options[:layout] = @layout if options[:layout].nil? || options[:layout] == true
# Resolve layouts similar to in Rails
if options[:layout].nil? && !settings.templates.has_key?(:layout)
layout_path = settings.fetch_layout_path(options[:layout])
is_included_extension = %w[.slim .erb .haml].include?(File.extname(layout_path.to_s))
layout_path, layout_engine = *(is_included_extension ? resolve_template(layout_path) : resolved_layout)
# We need to force layout false so sinatra don't try to render it
options[:layout] = layout_path || false
options[:layout] = false unless is_included_extension ? layout_engine : layout_engine == engine
options[:layout_engine] = layout_engine || engine if options[:layout]
elsif options[:layout].present?
options[:layout], options[:layout_engine] = *resolve_template(settings.fetch_layout_path(options[:layout]), options)
end
# Default to original layout value if none found.
options[:layout] ||= layout_was
# Cleanup the template.
@current_engine, engine_was = engine, @current_engine
@_out_buf, _buf_was = ActiveSupport::SafeBuffer.new, @_out_buf
# Pass arguments to Sinatra render method.
super(engine, data, options.dup, locals, &block)
ensure
@current_engine = engine_was
@_out_buf = _buf_was
end
##
# Returns the located layout tuple to be used for the rendered template
# (if available).
#
# @example
# resolve_layout
# # => ["/layouts/custom", :erb]
# # => [nil, nil]
#
def resolved_layout
located_layout = resolve_template(settings.fetch_layout_path, :raise_exceptions => false, :strict_format => true)
located_layout ? located_layout : [nil, nil]
end
##
# Returns the template path and engine that match content_type (if present),
# I18n.locale.
#
# @param [String] template_path
# The path of the template.
#
# @param [Hash] options
# Additional options.
#
# @option options [Boolean] :strict_format (false)
# The resolved template must match the content_type of the request.
#
# @option options [Boolean] :raise_exceptions (false)
# Raises a {TemplateNotFound} exception if the template cannot be located.
#
# @return [Array<Symbol, Symbol>]
# The path and format of the template.
#
# @raise [TemplateNotFound]
# The template could not be found.
#
# @example
# get "/foo", :provides => [:html, :js] do; render 'path/to/foo'; end
# # If you request "/foo.js" with I18n.locale == :ru => [:"/path/to/foo.ru.js", :erb]
# # If you request "/foo" with I18n.locale == :de => [:"/path/to/foo.de.haml", :haml]
#
def resolve_template(template_path, options={})
began_at = Time.now
_content_type = content_type || :html
# Fetch cached template for rendering options
template_path = template_path.to_s[0] == ?/ ? template_path.to_s : "/#{template_path}"
rendering_options = [template_path, _content_type, locale]
cached_template = settings.fetch_template_file(rendering_options)
if cached_template
logger.debug :cached, began_at, cached_template[0] if settings.logging? && defined?(logger)
return cached_template
end
# Resolve view path and options.
options = DEFAULT_RENDERING_OPTIONS.merge(options)
view_path = options.delete(:views) || settings.views || "./views"
target_extension = File.extname(template_path)[1..-1] || "none" # explicit template extension
template_path = template_path.chomp(".#{target_extension}")
template_glob =
if respond_to?(:request) && request.controller.present?
File.join("{,#{request.controller}}", template_path)
else
template_path
end
# Generate potential template candidates
templates = Dir[File.join(view_path, template_glob) + ".*"].map do |file|
template_engine = File.extname(file)[1..-1].to_sym # Retrieves engine extension
template_file = file.squeeze('/').sub(view_path, '').chomp(".#{template_engine}").to_sym # retrieves template filename
[template_file, template_engine] unless IGNORE_FILE_PATTERN.any? { |pattern| template_engine.to_s =~ pattern }
end
# Check if we have a simple content type
simple_content_type = [:html, :plain].include?(_content_type)
# Resolve final template to render
located_template =
templates.find { |file, e| file.to_s == "#{template_path}.#{locale}.#{_content_type}" } ||
templates.find { |file, e| file.to_s == "#{template_path}.#{locale}" && simple_content_type } ||
templates.find { |file, e| File.extname(file.to_s) == ".#{target_extension}" or e.to_s == target_extension.to_s } ||
templates.find { |file, e| file.to_s == "#{template_path}.#{_content_type}" } ||
templates.find { |file, e| file.to_s == "#{template_path}" && simple_content_type } ||
(!options[:strict_format] && templates.first) # If not strict, fall back to the first located template.
raise TemplateNotFound, "Template '#{template_path}' not found in '#{view_path}'!" if !located_template && options[:raise_exceptions]
settings.cache_template_file!(located_template, rendering_options) unless settings.reload_templates?
logger.debug :template, began_at, located_template[0] if located_template && settings.logging? && defined?(logger)
located_template
end
##
# Return the I18n.locale if I18n is defined.
#
def locale
I18n.locale if defined?(I18n)
end
end
end
end
require 'padrino-core/application/rendering/extensions/haml'
require 'padrino-core/application/rendering/extensions/erubis'
require 'padrino-core/application/rendering/extensions/slim'

View File

@ -1,68 +0,0 @@
begin
require 'erubis'
module Padrino
module Erubis
##
# SafeBufferEnhancer is an Erubis Enhancer that compiles templates that
# are fit for using ActiveSupport::SafeBuffer as a Buffer.
#
# @api private
module SafeBufferEnhancer
def add_expr_literal(src, code)
src << " #{@bufvar}.concat((" << code << ').to_s);'
end
def add_expr_escaped(src, code)
src << " #{@bufvar}.safe_concat " << code << ';'
end
def add_text(src, text)
src << " #{@bufvar}.safe_concat '" << escape_text(text) << "';" unless text.empty?
end
end
##
# SafeBufferTemplate is the classic Erubis template, augmented with
# SafeBufferEnhancer.
#
# @api private
class SafeBufferTemplate < ::Erubis::Eruby
include SafeBufferEnhancer
end
##
# Modded ErubisTemplate that doesn't insist in an String as output
# buffer.
#
# @api private
class Template < Tilt::ErubisTemplate
def render(*args)
app = args.first
app_class = app.class
@is_padrino_app = app.kind_of?(Padrino::Application) ||
(app_class.respond_to?(:erb) && app_class.erb[:engine_class] == Padrino::Erubis::SafeBufferTemplate)
super
end
##
# In preamble we need a flag `__in_erb_template` and SafeBuffer for padrino apps.
#
def precompiled_preamble(locals)
original = super
return original unless @is_padrino_app
"__in_erb_template = true\n" << original.rpartition("\n").first << "#{@outvar} = _buf = ActiveSupport::SafeBuffer.new\n"
end
end
end
end
Tilt.prefer(Padrino::Erubis::Template, :erb)
if defined? Padrino::Rendering
Padrino::Rendering.engine_configurations[:erb] = {
:engine_class => Padrino::Erubis::SafeBufferTemplate,
}
end
rescue LoadError
end

View File

@ -1,29 +0,0 @@
begin
require 'haml'
require 'haml/helpers/xss_mods'
require 'haml/helpers/action_view_extensions'
module Haml
module Helpers
include XssMods
include ActionViewExtensions
end
module Util
def self.rails_xss_safe?
true
end
end
end
if defined? Padrino::Rendering
Padrino::Rendering.engine_configurations[:haml] = {
:escape_html => true,
}
class Tilt::HamlTemplate
include Padrino::Rendering::SafeTemplate
end
end
rescue LoadError
end

View File

@ -1,21 +0,0 @@
begin
require 'slim'
if defined? Padrino::Rendering
Padrino::Rendering.engine_configurations[:slim] = {
:generator => Temple::Generators::RailsOutputBuffer,
:buffer => "@_out_buf",
:use_html_safe => true,
:disable_capture => true,
}
class Slim::Template
include Padrino::Rendering::SafeTemplate
def precompiled_preamble(locals)
"__in_slim_template = true\n" << super
end
end
end
rescue LoadError
end

View File

@ -1,21 +0,0 @@
module Padrino
##
# This module extend Sinatra::ShowExceptions adding Padrino as "Framework".
#
# @private
class ShowExceptions < Sinatra::ShowExceptions
private
def frame_class(frame)
if frame.filename =~ /lib\/sinatra.*\.rb|lib\/padrino.*\.rb/
"framework"
elsif (defined?(Gem) && frame.filename.include?(Gem.dir)) ||
frame.filename =~ /\/bin\/(\w+)$/ ||
frame.filename =~ /Ruby\/Gems/
"system"
else
"app"
end
end
end
end

View File

@ -1,53 +0,0 @@
module Padrino
# List of callers in a Padrino application that should be ignored as part of a stack trace.
PADRINO_IGNORE_CALLERS = [
%r{lib/padrino-.*$},
%r{/padrino-.*/(lib|bin)},
%r{/bin/padrino$},
%r{/sinatra(/(base|main|show_?exceptions))?\.rb$},
%r{lib/tilt.*\.rb$},
%r{lib/rack.*\.rb$},
%r{lib/mongrel.*\.rb$},
%r{lib/shotgun.*\.rb$},
%r{bin/shotgun$},
%r{\(.*\)},
%r{shoulda/context\.rb$},
%r{mocha/integration},
%r{test/unit},
%r{rake_test_loader\.rb},
%r{custom_require\.rb$},
%r{active_support},
%r{/thor}
] unless defined?(PADRINO_IGNORE_CALLERS)
##
# Add rubinius (and hopefully other VM implementations) ignore patterns ...
#
PADRINO_IGNORE_CALLERS.concat(RUBY_IGNORE_CALLERS) if defined?(RUBY_IGNORE_CALLERS)
private
##
# The filename for the file that is the direct caller (first caller).
#
# @return [String]
# The file the caller method exists in.
#
def self.first_caller
caller_files.first
end
#
# Like +Kernel#caller+ but excluding certain magic entries and without
# line / method information; the resulting array contains filenames only.
#
# @return [Array<String>]
# The files of the calling methods.
#
def self.caller_files
caller(1).
map { |line| line.split(/:(?=\d|in )/)[0,2] }.
reject { |file,line| PADRINO_IGNORE_CALLERS.any? { |pattern| file =~ pattern } }.
map { |file,line| file }
end
end

View File

@ -1,24 +0,0 @@
module Padrino
module Cli
module Adapter
class << self
# Start for the given options a rackup handler
def start(options)
Padrino.run!(options.symbolize_keys)
end
# Method that stop (if exist) a running Padrino.application
def stop(options)
options.symbolize_keys!
if File.exist?(options[:pid])
pid = File.read(options[:pid]).to_i
print "=> Sending INT to process with pid #{pid} wait "
Process.kill(2, pid) rescue nil
else
puts "=> #{options[:pid]} not found!"
end
end
end
end
end
end

View File

@ -1,190 +0,0 @@
require 'thor'
module Padrino
module Cli
class Base < Thor
include Thor::Actions
class_option :chdir, :type => :string, :aliases => "-c", :desc => "Change to dir before starting."
class_option :environment, :type => :string, :aliases => "-e", :required => true, :default => :development, :desc => "Padrino Environment."
class_option :help, :type => :boolean, :desc => "Show help usage"
desc "start", "Starts the Padrino application (alternatively use 's')."
map "s" => :start
method_option :server, :type => :string, :aliases => "-a", :desc => "Rack Handler (default: autodetect)"
method_option :host, :type => :string, :aliases => "-h", :required => true, :default => '127.0.0.1', :desc => "Bind to HOST address."
method_option :port, :type => :numeric, :aliases => "-p", :required => true, :default => 3000, :desc => "Use PORT."
method_option :daemonize, :type => :boolean, :aliases => "-d", :desc => "Run daemonized in the background."
method_option :pid, :type => :string, :aliases => "-i", :desc => "File to store pid."
method_option :debug, :type => :boolean, :desc => "Set debugging flags."
method_option :options, :type => :array, :aliases => "-O", :desc => "--options NAME=VALUE NAME2=VALUE2'. pass VALUE to the server as option NAME. If no VALUE, sets it to true. Run '#{$0} --server_options"
method_option :server_options, :type => :boolean, :desc => "Tells the current server handler's options that can be used with --options"
def start
prepare :start
require File.expand_path("../adapter", __FILE__)
require File.expand_path('config/boot.rb')
if options[:server_options]
puts server_options(options)
else
Padrino::Cli::Adapter.start(options)
end
end
desc "stop", "Stops the Padrino application (alternatively use 'st')."
map "st" => :stop
method_option :pid, :type => :string, :aliases => "-p", :desc => "File to store pid", :default => 'tmp/pids/server.pid'
def stop
prepare :stop
require File.expand_path("../adapter", __FILE__)
Padrino::Cli::Adapter.stop(options)
end
desc "rake", "Execute rake tasks."
method_option :environment, :type => :string, :aliases => "-e", :required => true, :default => :development
method_option :list, :type => :string, :aliases => "-T", :desc => "Display the tasks (matching optional PATTERN) with descriptions, then exit."
method_option :trace, :type => :boolean, :aliases => "-t", :desc => "Turn on invoke/execute tracing, enable full backtrace."
def rake(*args)
prepare :rake
args << "-T" if options[:list]
args << options[:list] unless options[:list].nil? || options[:list].to_s == "list"
args << "--trace" if options[:trace]
args << "--verbose" if options[:verbose]
ARGV.clear
ARGV.concat(args)
puts "=> Executing Rake #{ARGV.join(' ')} ..."
load File.expand_path('../rake.rb', __FILE__)
Rake.application.init
Rake.application.instance_variable_set(:@rakefile, __FILE__)
load File.expand_path('Rakefile')
Rake.application.top_level
end
desc "console", "Boots up the Padrino application irb console (alternatively use 'c')."
map "c" => :console
def console(*args)
prepare :console
require File.expand_path("../../version", __FILE__)
ARGV.clear
require 'irb'
require "irb/completion"
require File.expand_path('config/boot.rb')
puts "=> Loading #{Padrino.env} console (Padrino v.#{Padrino.version})"
require File.expand_path('../console', __FILE__)
IRB.start
end
desc "generate", "Executes the Padrino generator with given options (alternatively use 'gen' or 'g')."
map ["gen", "g"] => :generate
def generate(*args)
begin
# We try to load the vendored padrino-gen if exist
padrino_gen_path = File.expand_path('../../../../../padrino-gen/lib', __FILE__)
$:.unshift(padrino_gen_path) if File.directory?(padrino_gen_path) && !$:.include?(padrino_gen_path)
require 'padrino-core/command'
require 'padrino-gen/command'
ARGV.shift
ARGV << 'help' if ARGV.empty?
Padrino.bin_gen(*ARGV)
rescue
puts "<= You need padrino-gen! Run: gem install padrino-gen"
end
end
desc "version", "Show current Padrino version."
map ["-v", "--version"] => :version
def version
require 'padrino-core/version'
puts "Padrino v. #{Padrino.version}"
end
desc "runner", "Run a piece of code in the Padrino application environment (alternatively use 'run' or 'r')."
map ["run", "r"] => :runner
def runner(*args)
prepare :runner
code_or_file = args.shift
abort "Please specify code or file" if code_or_file.nil?
require File.expand_path('config/boot.rb')
if File.exist?(code_or_file)
eval(File.read(code_or_file), nil, code_or_file)
else
eval(code_or_file)
end
end
private
def prepare(task)
if options.help?
help(task.to_s)
raise SystemExit
end
ENV["RACK_ENV"] ||= options.environment.to_s
chdir(options.chdir)
unless File.exist?('config/boot.rb')
puts "=> Could not find boot file in: #{options.chdir}/config/boot.rb !!!"
raise SystemExit
end
end
# https://github.com/rack/rack/blob/master/lib/rack/server.rb\#L100
def server_options(options)
begin
info = []
server = Rack::Handler.get(options[:server]) || Rack::Handler.default(options)
if server && server.respond_to?(:valid_options)
info << ""
info << "Server-specific options for #{server.name}:"
has_options = false
server.valid_options.each do |name, description|
next if name.to_s.match(/^(Host|Port)[^a-zA-Z]/) # ignore handler's host and port options, we do our own.
info << " -O %-21s %s" % [name, description]
has_options = true
end
return "" if !has_options
end
info.join("\n")
rescue NameError
return "Warning: Could not find handler specified (#{options[:server] || 'default'}) to determine handler-specific options"
end
end
protected
def self.banner(task=nil, *args)
"padrino #{task.name}"
end
def chdir(dir)
return unless dir
begin
Dir.chdir(dir.to_s)
rescue Errno::ENOENT
puts "=> Specified Padrino root '#{dir}' does not appear to exist!"
rescue Errno::EACCES
puts "=> Specified Padrino root '#{dir}' cannot be accessed by the current user!"
end
end
def capture(stream)
begin
stream = stream.to_s
eval "$#{stream} = StringIO.new"
yield
result = eval("$#{stream}").string
ensure
eval("$#{stream} = #{stream.upcase}")
end
result
end
alias :silence :capture
end
end
end

View File

@ -1,20 +0,0 @@
# Reloads classes
def reload!
Padrino.reload!
end
# Show applications
def applications
puts "==== List of Mounted Applications ====\n\n"
Padrino.mounted_apps.each do |app|
puts " * %-10s mapped to %s" % [app.name, app.uri_root]
end
puts
Padrino.mounted_apps.map { |app| "#{app.name} => #{app.uri_root}" }
end
# Load apps
Padrino.mounted_apps.each do |app|
puts "=> Loading Application #{app.app_class}"
app.app_obj.setup_application!
end

View File

@ -1,47 +0,0 @@
require File.expand_path('../../tasks', __FILE__)
require 'rake'
require 'rake/dsl_definition'
require 'thor'
require 'securerandom' unless defined?(SecureRandom)
require 'padrino-gen'
module PadrinoTasks
def self.init(init=false)
$LOAD_PATH.unshift(File.expand_path("lib"))
Padrino::Tasks.files.flatten.uniq.each { |rakefile| Rake.application.add_import(rakefile) rescue puts "<= Failed load #{ext}" }
load(File.expand_path('../rake_tasks.rb', __FILE__))
Rake.application.load_imports
end
def self.use(task)
tasks << task
end
def self.tasks
@tasks ||= []
end
def self.load?(task, constant_present)
if constant_present && !PadrinoTasks.tasks.include?(task)
warn <<-WARNING.undent
Loading #{task} tasks automatically.
This functionality will be disabled in future versions. Please put
PadrinoTasks.use(#{task.inspect})
PadrinoTasks.init
and remove
require File.expand_path('../config/boot.rb', __FILE__)
in you Rakefile instead.
WARNING
end
constant_present || PadrinoTasks.tasks.include?(task)
end
end
def shell
@_shell ||= Thor::Base.shell.new
end

View File

@ -1,62 +0,0 @@
Dir["{lib/tasks/**,tasks/**,test,spec}/*.rake"].each do |file|
begin
load(file)
rescue LoadError => e
warn "#{file}: #{e.message}"
end
end
# Loads the Padrino applications mounted within the project.
# Setting up the required environment for Padrino.
task :environment do
require File.expand_path('config/boot.rb', Rake.application.original_dir)
Padrino.mounted_apps.each do |app|
app.app_obj.setup_application!
end
end
# Loads skeleton Padrino environment, no models, no application settings.
task :skeleton do
module Padrino::Reloader
def self.safe_load(file, options)
super unless file.include?('/models/')
end
end
require File.expand_path('config/boot.rb', Rake.application.original_dir)
end
desc "Generate a secret key"
task :secret do
shell.say SecureRandom.hex(32)
end
def list_app_routes(app, args)
app_routes = app.named_routes
app_routes.reject! { |r| r.identifier.to_s !~ /#{args.query}/ } if args.query.present?
app_routes.map! { |r| [r.verb, r.name, r.path] }
return if app_routes.empty?
shell.say "\nApplication: #{app.app_class}", :yellow
app_routes.unshift(["REQUEST", "URL", "PATH"])
max_col_1 = app_routes.max { |a, b| a[0].size <=> b[0].size }[0].size
max_col_2 = app_routes.max { |a, b| a[1].size <=> b[1].size }[1].size
app_routes.each_with_index do |row, i|
message = [row[1].ljust(max_col_2+2), row[0].center(max_col_1+2), row[2]]
shell.say(" " + message.join(" "), i==0 ? :bold : nil)
end
end
desc "Displays a listing of the named routes within a project, optionally only those matched by [query]"
task :routes, [:query] => :environment do |t, args|
Padrino.mounted_apps.each do |app|
list_app_routes(app, args)
end
end
desc "Displays a listing of the named routes a given app [app]"
namespace :routes do
task :app, [:app] => :environment do |t, args|
app = Padrino.mounted_apps.find { |app| app.app_class == args.app }
list_app_routes(app, args) if app
end
end

View File

@ -1,38 +0,0 @@
require 'rbconfig'
module Padrino
##
# This method return the correct location of padrino bin or
# exec it using Kernel#system with the given args.
#
# @param [Array] args
# command or commands to execute
#
# @return [Boolean]
#
# @example
# Padrino.bin('start', '-e production')
#
def self.bin(*args)
@_padrino_bin ||= [self.ruby_command, File.expand_path("../../../bin/padrino", __FILE__)]
args.empty? ? @_padrino_bin : system(args.unshift(@_padrino_bin).join(" "))
end
##
# Return the path to the ruby interpreter taking into account multiple
# installations and windows extensions.
#
# @return [String]
# path to ruby bin executable
#
def self.ruby_command
@ruby_command ||= begin
ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
ruby << RbConfig::CONFIG['EXEEXT']
# escape string in case path to ruby executable contain spaces.
ruby.sub!(/.*\s.*/m, '"\&"')
ruby
end
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,224 +0,0 @@
module Padrino
module Loader
##
# Hooks to be called before a load/reload.
#
# @yield []
# The given block will be called before Padrino was loaded/reloaded.
#
# @return [Array<Proc>]
# The load/reload before hooks.
#
# @example
# before_load do
# pre_initialize_something
# end
#
def before_load(&block)
@_before_load ||= []
@_before_load << block if block_given?
@_before_load
end
##
# Hooks to be called after a load/reload.
#
# @yield []
# The given block will be called after Padrino was loaded/reloaded.
#
# @return [Array<Proc>]
# The load/reload hooks.
#
# @example
# after_load do
# DataMapper.finalize
# end
#
def after_load(&block)
@_after_load ||= []
@_after_load << block if block_given?
@_after_load
end
##
# Requires necessary dependencies as well as application files from root
# lib and models.
#
# @return [Boolean]
# returns true if Padrino is not already bootstraped otherwise else.
#
def load!
return false if loaded?
began_at = Time.now
@_called_from = first_caller
set_encoding
set_load_paths(*load_paths)
Logger.setup!
require_dependencies("#{root}/config/database.rb")
Reloader.lock!
before_load.each(&:call)
require_dependencies(*dependency_paths)
after_load.each(&:call)
logger.devel "Loaded Padrino in #{Time.now - began_at} seconds"
Thread.current[:padrino_loaded] = true
end
##
# Clear the padrino env.
#
# @return [NilClass]
#
def clear!
clear_middleware!
mounted_apps.clear
@_load_paths = nil
@_dependency_paths = nil
@_global_configuration = nil
before_load.clear
after_load.clear
Reloader.clear!
Thread.current[:padrino_loaded] = nil
end
##
# Method for reloading required applications and their files.
#
def reload!
return unless Reloader.changed?
before_load.each(&:call)
Reloader.reload!
after_load.each(&:call)
end
##
# This adds the ability to instantiate {Padrino.load!} after
# {Padrino::Application} definition.
#
def called_from
@_called_from || first_caller
end
##
# Determines whether Padrino was loaded with {Padrino.load!}.
#
# @return [Boolean]
# Specifies whether Padrino was loaded.
#
def loaded?
Thread.current[:padrino_loaded]
end
##
# Attempts to require all dependency libs that we need.
# If you use this method we can perform correctly a Padrino.reload!
# Another good thing that this method are dependency check, for example:
#
# # models
# # \-- a.rb => require something of b.rb
# # \-- b.rb
#
# In the example above if we do:
#
# Dir["/models/*.rb"].each { |r| require r }
#
# We get an error, because we try to require first +a.rb+ that need
# _something_ of +b.rb+.
#
# With this method we don't have this problem.
#
# @param [Array<String>] paths
# The paths to require.
#
# @example For require all our app libs we need to do:
# require_dependencies("#{Padrino.root}/lib/**/*.rb")
#
def require_dependencies(*paths)
options = paths.extract_options!.merge( :cyclic => true )
files = paths.flatten.map{|path| Dir[path].sort_by{|v| v.count('/') }}.flatten.uniq
while files.present?
error, fatal, loaded = nil, nil, nil
files.dup.each do |file|
begin
Reloader.safe_load(file, options)
files.delete(file)
loaded = true
rescue NameError, LoadError => e
logger.devel "Cyclic dependency reload for #{e.class}: #{e.message}"
error = e
rescue Exception => e
fatal = e
break
end
end
if fatal || !loaded
e = fatal || error
logger.error "#{e.class}: #{e.message}; #{e.backtrace.first}"
raise e
end
end
end
##
# Concat to +$LOAD_PATH+ the given paths.
#
# @param [Array<String>] paths
# The paths to concat.
#
def set_load_paths(*paths)
load_paths.concat(paths).uniq!
$LOAD_PATH.concat(paths).uniq!
end
##
# The used +$LOAD_PATHS+ from Padrino.
#
# @return [Array<String>]
# The load paths used by Padrino.
#
def load_paths
@_load_paths ||= load_paths_was.dup
end
##
# Returns default list of path globs to load as dependencies.
# Appends custom dependency patterns to the be loaded for Padrino.
#
# @return [Array<String>]
# The dependencey paths.
#
# @example
# Padrino.dependency_paths << "#{Padrino.root}/uploaders/*.rb"
#
def dependency_paths
@_dependency_paths ||= dependency_paths_was + module_paths
end
private
def module_paths
modules.map(&:dependency_paths).flatten
end
def load_paths_was
@_load_paths_was ||= [
"#{root}/lib",
"#{root}/models",
"#{root}/shared",
].freeze
end
def dependency_paths_was
@_dependency_paths_was ||= [
"#{root}/config/database.rb",
"#{root}/lib/**/*.rb",
"#{root}/models/**/*.rb",
"#{root}/shared/lib/**/*.rb",
"#{root}/shared/models/**/*.rb",
"#{root}/config/apps.rb"
].freeze
end
end
end

View File

@ -1,33 +0,0 @@
cs:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d. %m. %Y"
short: "%d %b"
long: "%d. %B %Y"
only_day: "%e"
day_names: [Neděle, Pondělí, Úterý, Středa, Čtvrtek, Pátek, Sobota]
abbr_day_names: [Ne, Po, Út, St, Čt, Pá, So]
month_names: [~, Leden, Únor, Březen, Duben, Květen, Červen, Červenec, Srpen, Září, Říjen, Listopad, Prosinec]
abbr_month_names: [~, Led, Úno, Bře, Dub, Kvě, Čvn, Čvc, Srp, Zář, Říj, Lis, Pro]
order:
- day
- month
- year
time:
formats:
default: "%a %d. %B %Y %H:%M %z"
short: "%d. %m. %H:%M"
long: "%A %d. %B %Y %H:%M"
am: "dop"
pm: "odp"
support:
array:
words_connector: ", "
two_words_connector: " a "
last_word_connector: " a "

View File

@ -1,33 +0,0 @@
da:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d.%m.%Y"
short: "%e. %b %Y"
long: "%e. %B %Y"
only_day: "%e"
day_names: [søndag, mandag, tirsdag, onsdag, torsdag, fredag, lørdag]
abbr_day_names: [sø, ma, ti, 'on', to, fr, lø]
month_names: [~, januar, februar, marts, april, maj, juni, juli, august, september, oktober, november, december]
abbr_month_names: [~, jan, feb, mar, apr, maj, jun, jul, aug, sep, okt, nov, dec]
order:
- day
- month
- year
time:
formats:
default: "%e. %B %Y, %H:%M"
short: "%e. %b %Y, %H:%M"
long: "%A, %e. %B %Y, %H:%M"
am: ""
pm: ""
support:
array:
words_connector: ", "
two_words_connector: " og "
last_word_connector: " og "

View File

@ -1,33 +0,0 @@
de:
date:
formats:
# Benutze die strftime Parameter für die Formatierung
# Wenn keine Formate angegeben werden, wird "default" benutzt.
# Du kannst auch weitere Formate hinzufügen, wenn Du möchtest.
default: "&d.&m.%Y"
short: "%d. %b"
long: "%d. %B %Y"
only_day: "%e"
day_names: [Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag]
abbr_day_names: [So, Mo, Di, Mi, Do, Fr, Sa]
month_names: [~, Januar, Februar, März, April, Mai, Juni, Juli, August, September, Oktober, November, Dezember]
abbr_month_names: [~, Jan, Feb, Mär, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez]
order:
- day
- month
- year
time:
formats:
default: "%a, %d. %b %Y %H:%M:%S %z"
short: "%d. %b %H:%M"
long: "%d. %B %Y %H:%M"
am: "am"
pm: "pm"
support:
array:
words_connector: ", "
two_words_connector: " und "
last_word_connector: " und "

View File

@ -1,33 +0,0 @@
en:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%Y-%m-%d"
short: "%b %d"
long: "%B %d, %Y"
only_day: "%e"
day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
order:
- year
- month
- day
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%B %d, %Y %H:%M"
am: "am"
pm: "pm"
support:
array:
words_connector: ", "
two_words_connector: " and "
last_word_connector: ", and "

View File

@ -1,33 +0,0 @@
es:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d-%m-%Y"
short: "%b %d"
long: "%B %d, %Y"
only_day: "%e"
day_names: [Domingo, Lunes, Martes, Miércoles, Jueves, Viernes, Sábado]
abbr_day_names: [Dom, Lun, Mar, Mie, Jue, Vie, Sab]
month_names: [~, Enero, Febrero, Marzo, Abril, Mayo, Junio, Julio, Agosto, Septiembre, Octubre, Noviembre, Diciembre]
abbr_month_names: [~, Ene, Feb, Mar, Abr, May, Jun, Jul, Ago, Sep, Oct, Nov, Dic]
order:
- day
- month
- year
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%B %d, %Y %H:%M"
am: "am"
pm: "pm"
support:
array:
words_connector: ", "
two_words_connector: " y "
last_word_connector: ", y "

View File

@ -1,33 +0,0 @@
fr:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d-%m-%Y"
short: "%b %d"
long: "%B %d, %Y"
only_day: "%e"
day_names: [Dimanche, Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi]
abbr_day_names: [Dim, Lun, Mar, Mer, Jeu, Ven, Sam]
month_names: [~, Janvier, Février, Mars, Avril, Mai, Juin, Juillet, Août, Septembre, Octobre, Novembre, Décembre]
abbr_month_names: [~, Jan, Fev, Mar, Avr, Mai, Jun, Jul, Aou, Sep, Oct, Nov, Dec]
order:
- day
- month
- year
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%B %d, %Y %H:%M"
am: "am"
pm: "pm"
support:
array:
words_connector: ", "
two_words_connector: " et "
last_word_connector: ", et "

View File

@ -1,33 +0,0 @@
hu:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%Y-%m-%d"
short: "%b. %d."
long: "%Y. %B %d."
only_day: "%e"
day_names: [vasárnap, hétfő, kedd, szerda, csütörtök, péntek, szombat]
abbr_day_names: [vas, hét, kedd, sze, csüt, pén, szo]
month_names: [~, január, február, március, április, május, június, július, augusztus, szeptember, oktober, november, december]
abbr_month_names: [~, jan, febr, márc, ápr, máj, jún, júl, aug, szept, okt, nov, dec]
order:
- year
- month
- day
time:
formats:
default: "%Y. %B %d. %H:%M:%S %z, %A"
short: "%B %d. %H:%M"
long: "%Y. %B %d. %H:%M"
am: "de"
pm: "du"
support:
array:
words_connector: ", "
two_words_connector: " és "
last_word_connector: " és "

View File

@ -1,39 +0,0 @@
it:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d-%m-%Y"
short: "%d %b"
long: "%d %B %Y"
only_day: "%e"
day_names: [Domenica, Lunedì, Martedì, Mercoledì, Giovedì, Venerdì, Sabato]
abbr_day_names: [Dom, Lun, Mar, Mer, Gio, Ven, Sab]
month_names: [~, Gennaio, Febbraio, Marzo, Aprile, Maggio, Giugno, Luglio, Agosto, Settembre, Ottobre, Novembre, Dicembre]
abbr_month_names: [~, Gen, Feb, Mar, Apr, Mag, Giu, Lug, Ago, Set, Ott, Nov, Dic]
order:
- day
- month
- year
time:
formats:
default: "%a %d %b %Y, %H:%M:%S %z"
time: "%H:%M"
short: "%d %b %H:%M"
long: "%d %B %Y %H:%M"
only_second: "%S"
datetime:
formats:
default: "%d-%m-%YT%H:%M:%S%Z"
am: 'am'
pm: 'pm'
support:
array:
sentence_connector: "e"
skip_last_comma: false

View File

@ -1,33 +0,0 @@
ja:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%Y/%m/%d"
short: "%m/%d"
long: "%Y年%m月%d日"
only_day: "%e"
day_names: [日曜日, 月曜日, 火曜日, 水曜日, 木曜日, 金曜日, 土曜日]
abbr_day_names: [日, 月, 火, 水, 木, 金, 土]
month_names: [~, 一月, 二月, 三月, 四月, 五月, 六月, 七月, 八月, 九月, 十月, 十一月, 十二月]
abbr_month_names: [~, 一月, 二月, 三月, 四月, 五月, 六月, 七月, 八月, 九月, 十月, 十一月, 十二月]
order:
- year
- month
- day
time:
formats:
default: "%Y/%m/%d %H:%M:%S"
short: "%m/%d %H:%M"
long: "%Y年%m月%d日 %H時%M分%S秒"
am: "午前"
pm: "午後"
support:
array:
words_connector: ", "
two_words_connector: " と "
last_word_connector: ", と "

View File

@ -1,33 +0,0 @@
lv:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d.%m.%Y"
short: "%e. %B"
long: "%Y. gada %e. %B"
only_day: "%e"
day_names: [Svētdiena, Pirmdiena, Otrdiena, Trešdiena, Ceturtdiena, Piektdiena, Sestdiena]
abbr_day_names: [Sv, P, O, T, C, P, S]
month_names: [~, Janvāris, Februāris, Marts, Aprīlis, Maijs, Jūnijs, Jūlijs, Augusts, Septembris, Oktobris, Novembris, Decembris]
abbr_month_names: [~, Janv, Febr, Marts, Apr, Maijs, Jūn, Jūl, Aug, Sept, Okt, Nov, Dec]
order:
- day
- month
- year
time:
formats:
default: "%Y. gada %e. %B, %H:%M"
short: "%d.%m.%Y, %H:%M"
long: "%Y. gada %e. %B, %H:%M:%S"
am: "priekšpusdiena"
pm: "pēcpusdiena"
support:
array:
words_connector: ", "
two_words_connector: " un "
last_word_connector: ", un "

View File

@ -1,33 +0,0 @@
nl:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d-%m-%Y"
short: "%d %b"
long: "%d %B %Y"
only_day: "%e"
day_names: [zondag, maandag, dinsdag, woensdag, donderdag, vrijdag, zaterdag]
abbr_day_names: [zo, ma, di, wo, do, vr, za]
month_names: [~, januari, februari, maart, april, mei, juni, juli, augustus, september, oktober, november, december]
abbr_month_names: [~, jan, feb, maa, apr, mei, jun, jul, aug, sep, okt, nov, dec]
order:
- day
- month
- year
time:
formats:
default: "%a %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%d %B %Y %H:%M"
am: "am"
pm: "pm"
support:
array:
words_connector: ", "
two_words_connector: " en "
last_word_connector: " en "

View File

@ -1,33 +0,0 @@
"no":
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d.%m.%Y"
short: "%e. %b %Y"
long: "%e. %B %Y"
only_day: "%e"
day_names: [søndag, mandag, tirsdag, onsdag, torsdag, fredag, lørdag]
abbr_day_names: [sø, ma, ti, 'on', to, fr, lø]
month_names: [~, januar, februar, mars, april, mai, juni, juli, august, september, oktober, november, desember]
abbr_month_names: [~, jan, feb, mar, apr, maj, jun, jul, aug, sep, okt, nov, des]
order:
- day
- month
- year
time:
formats:
default: "%e. %B %Y, %H:%M"
short: "%e. %b %Y, %H:%M"
long: "%A, %e. %B %Y, %H:%M"
am: ""
pm: ""
support:
array:
words_connector: ", "
two_words_connector: " og "
last_word_connector: " og "

View File

@ -1,33 +0,0 @@
pl:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%Y-%m-%d"
short: "%d %b"
long: "%d %B %Y"
only_day: "%e"
day_names: [Niedziela, Poniedziałek, Wtorek, Środa, Czwartek, Piątek, Sobota]
abbr_day_names: [nie, pon, wto, śro, czw, pia, sob]
month_names: [~, Styczeń, Luty, Marzec, Kwiecień, Maj, Czerwiec, Lipiec, Sierpień, Wrzesień, Październik, Listopad, Grudzień]
abbr_month_names: [~, sty, lut, mar, kwi, maj, cze, lip, sie, wrz, paź, lis, gru]
order:
- year
- month
- day
time:
formats:
default: "%a, %d %b %Y, %H:%M:%S %z"
short: "%d %b, %H:%M"
long: "%d %B %Y, %H:%M"
am: "przed południem"
pm: "po południu"
support:
array:
words_connector: ", "
two_words_connector: " i "
last_word_connector: " i "

View File

@ -1,39 +0,0 @@
pt_br:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d-%m-%Y"
short: "%d %b"
long: "%d %B %Y"
only_day: "%e"
day_names: [Domingo, Segunda-feira, Terça-feira, Quarta-feira, Quinta-feira, Sexta-feira, Sábado]
abbr_day_names: [Dom, Seg, Ter, Qua, Qui, Sex, Sab]
month_names: [~, Janeiro, Fevereiro, Março, Abril, Maio, Junho, Julho, Agosto, Setembro, Outubro, Novembro, Dezembro]
abbr_month_names: [~, Jan, Fev, Mar, Abr, Maio, Jun, Jul, Ago, Set, Out, Nov, Dez]
order:
- day
- month
- year
time:
formats:
default: "%a %d %b %Y, %H:%M:%S %z"
time: "%H:%M"
short: "%d %b %H:%M"
long: "%d %B %Y %H:%M"
only_second: "%S"
datetime:
formats:
default: "%d-%m-%YT%H:%M:%S%Z"
am: 'am'
pm: 'pm'
support:
array:
sentence_connector: "e"
skip_last_comma: false

View File

@ -1,33 +0,0 @@
ro:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d.%m.%Y"
short: "%d %b"
long: "%d %B %Y"
only_day: "%e"
day_names: [Duminică, Luni, Marți, Miercuri, Joi, Vineri, Sâmbătă]
abbr_day_names: [Dum, Lun, Mar, Mie, Joi, Vin, Sâm]
month_names: [~, Ianuarie, Februarie, Martie, Aprilie, Mai, Iunie, Iulie, August, Septembrie, Octombrie, Noiembrie, Decembrie]
abbr_month_names: [~, Ian, Feb, Mar, Apr, Mai, Iun, Iul, Aug, Sep, Oct, Noi, Dec]
order:
- day
- month
- year
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%d, %B %Y %H:%M"
am: "am"
pm: "pm"
support:
array:
words_connector: ", "
two_words_connector: " și "
last_word_connector: " și "

View File

@ -1,34 +0,0 @@
ru:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d.%m.%Y"
short: "%d %b"
long: "%e %B, %Y"
only_day: "%e"
day_names: [Воскресенье, Понедельник, Вторник, Среда, Четверг, Пятница, Суббота]
abbr_day_names: [Вс, Пн, Вт, Ср, Чт, Пт, Сб]
month_names: [~, Январь, Февраль, Март, Апрель, Май, Июнь, Июль, Август, Сентябрь, Октябрь, Ноябрь, Декабрь]
abbr_month_names: [~, Янв, Фев, Мар, Апр, Май, Июн, Июл, Авг, Сен, Окт, Ноя, Дек]
order:
- year
- month
- day
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%e %B, %Y %H:%M"
am: "д.п."
pm: "п.п."
support:
array:
words_connector: ", "
two_words_connector: " и "
last_word_connector: " и "

View File

@ -1,33 +0,0 @@
sv:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%Y-%m-%d"
short: "%b %d"
long: "%B %d, %Y"
only_day: "%e"
day_names: [söndag, måndag, tisdag, onsdag, torsdag, fredag, lördag]
abbr_day_names: [sön, mån, tis, ons, tors, fre, lör]
month_names: [~, januari, februari, mars, april, maj, juni, juli, augusti, september, oktober, november, december]
abbr_month_names: [~, jan, feb, mar, apr, may, jun, jul, aug, sep, okt, nov, dec]
order:
- år
- månad
- dag
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%B %d, %Y %H:%M"
am: "fm"
pm: "em"
support:
array:
words_connector: ", "
two_words_connector: " och "
last_word_connector: ", och "

View File

@ -1,33 +0,0 @@
tr:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d/%m/%Y"
short: "%d %b"
long: "%d %B %Y"
only_day: "%e"
day_names: [Pazar, Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi]
abbr_day_names: [Paz, Pts, Sal, Çar, Per, Cum, Cts]
month_names: [~, Ocak, Şubat, Mart, Nisan, Mayıs, Haziran, Temmuz, Ağustos, Eylül, Ekim, Kasım, Aralık]
abbr_month_names: [~, Oca, Şub, Mar, Nis, May, Haz, Tem, Ağu, Eyl, Eki, Kas, Ara]
order:
- day
- month
- year
time:
formats:
default: "%a, %b %b %Y %H:%M:%S %z"
short: "%b %d %H:%M"
long: "%d %B, %Y %H:%M"
am: "öö"
pm: "ös"
support:
array:
words_connector: ", "
two_words_connector: " ve "
last_word_connector: " ve "

View File

@ -1,33 +0,0 @@
uk:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d.%m.%Y"
short: "%d %b"
long: "%e %B, %Y"
only_day: "%e"
day_names: [Неділя, Понеділок, Вівторок, Середа, Четвер, Пятница, Субота]
abbr_day_names: [Нд, Пн, Вт, Ср, Чт, Пт, Сб]
month_names: [~, Січено, Лютий, Березень, Квітень, Травень, Червень, Липень, Серпень, Вересень, Жовтень, Листопад, Грудень]
abbr_month_names: [~, Січ, Лют, Бер, Кві, Тра, Чер, Лип, Сер, Вер, Жов, Лис, Гру]
order:
- year
- month
- day
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"
long: "%e %B, %Y %H:%M"
am: "д.п."
pm: "п.п"
support:
array:
words_connector: ", "
two_words_connector: " і "
last_word_connector: ", і "

View File

@ -1,33 +0,0 @@
zh_cn:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%Y年%m月%d日"
short: "%b月%d日"
long: "%Y年%B月%d日"
only_day: "%e"
day_names: [星期日, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六]
abbr_day_names: [日, 一, 二, 三, 四, 五, 六]
month_names: [~, 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月]
abbr_month_names: [~, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
order:
- year
- month
- day
time:
formats:
default: "%Y年%b月%d日 %H:%M:%S %z"
short: "%b月%d日 %H:%M"
long: "%Y年%B%d日 %H时%M分"
am: "上午"
pm: "下午"
support:
array:
words_connector: ""
two_words_connector: "和"
last_word_connector: ",还有"

View File

@ -1,33 +0,0 @@
zh_tw:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%Y-%m-%d"
short: "%b%d日"
long: "%Y年%b%d日"
only_day: "%e"
day_names: [星期日, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六]
abbr_day_names: [日, 一, 二, 三, 四, 五, 六]
month_names: [~, 一月, 二月, 三月, 四月, 五月, 六月, 七月, 八月, 九月, 十月, 十一月, 十二月]
abbr_month_names: [~, 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月]
order:
- year
- month
- day
time:
formats:
default: "%Y年%b%d日 %A %H:%M:%S %Z"
short: "%b%d日 %H:%M"
long: "%Y年%b%d日 %H:%M"
am: "上午"
pm: "下午"
support:
array:
words_connector: ", "
two_words_connector: " 和 "
last_word_connector: ", 和 "

View File

@ -1,438 +0,0 @@
# Defines the log level for a Padrino project.
PADRINO_LOG_LEVEL = ENV['PADRINO_LOG_LEVEL'] unless defined?(PADRINO_LOG_LEVEL)
# Defines the logger used for a Padrino project.
PADRINO_LOGGER = ENV['PADRINO_LOGGER'] unless defined?(PADRINO_LOGGER)
module Padrino
##
# @return [Padrino::Logger]
#
# @example
# logger.debug "foo"
# logger.warn "bar"
#
def self.logger
Padrino::Logger.logger
end
##
# Set the padrino logger.
#
# @param [Object] value
# an object that respond to <<, write, puts, debug, warn etc..
#
# @return [Object]
# The given value.
#
# @example using ruby default logger
# require 'logger'
# Padrino.logger = Logger.new(STDOUT)
#
# @example using ActiveSupport
# require 'active_support/buffered_logger'
# Padrino.logger = Buffered.new(STDOUT)
#
def self.logger=(value)
Padrino::Logger.logger = value
end
##
# Padrinos internal logger, using all of Padrino log extensions.
#
class Logger
##
# Ruby (standard) logger levels:
#
# :fatal:: An not handleable error that results in a program crash
# :error:: A handleable error condition
# :warn:: A warning
# :info:: generic (useful) information about system operation
# :debug:: low-level information for developers
# :devel:: Development-related information that is unnecessary in debug mode
#
Levels = {
:fatal => 4,
:error => 3,
:warn => 2,
:info => 1,
:debug => 0,
:devel => -1,
} unless defined?(Levels)
module Extensions
##
# Generate the logging methods for {Padrino.logger} for each log level.
#
Padrino::Logger::Levels.each_pair do |name, number|
define_method(name) do |*args|
return if number < level
if args.size > 1
bench(args[0], args[1], args[2], name)
else
push(args * '', name)
end
end
define_method(:"#{name}?") do
number >= level
end
end
##
# Append a to development logger a given action with time.
#
# @param [string] action
# The action.
#
# @param [float] time
# Time duration for the given action.
#
# @param [message] string
# The message that you want to log.
#
# @example
# logger.bench 'GET', started_at, '/blog/categories'
# # => DEBUG - GET (0.0056s) - /blog/categories
#
def bench(action, began_at, message, level=:debug, color=:yellow)
@_pad ||= 8
@_pad = action.to_s.size if action.to_s.size > @_pad
duration = Time.now - began_at
color = :red if duration > 1
action = colorize(action.to_s.upcase.rjust(@_pad), color)
duration = colorize('%0.4fs' % duration, :bold, color)
push "#{action} (#{duration}) #{message}", level
end
##
# Appends a message to the log. The methods yield to an optional block and
# the output of this block will be appended to the message.
#
# @param [String] message
# The message that you want write to your stream.
#
# @param [String] level
# The level one of :debug, :warn etc. ...
#
#
def push(message = nil, level = nil)
add(Padrino::Logger::Levels[level], format(message, level))
end
##
# Formats the log message. This method is a noop and should be implemented by other
# logger components such as {Padrino::Logger}.
#
# @param [String] message
# The message to format.
#
# @param [String,Symbol] level
# The log level, one of :debug, :warn ...
def format(message, level)
message
end
##
# The debug level, with some style added. May be reimplemented.
#
# @example
# stylized_level(:debug) => DEBUG
#
# @param [String,Symbol] level
# The log level.
#
def stylized_level(level)
level.to_s.upcase.rjust(7)
end
##
# Colorizes a string for colored console output. This is a noop and can be reimplemented
# to colorize the string as needed.
#
# @see
# ColorizedLogger
#
# @param [string]
# The string to be colorized.
#
# @param [Array<Symbol>]
# The colors to use. Should be applied in the order given.
def colorize(string, *colors)
string
end
##
# Turns a logger with LoggingExtensions into a logger with colorized output.
#
# @example
# Padrino.logger = Logger.new($stdout)
# Padrino.logger.colorize!
# Padrino.logger.debug("Fancy Padrino debug string")
def colorize!
self.extend(Colorize)
end
end
module Colorize
# Colors for levels
ColoredLevels = {
:fatal => [:bold, :red],
:error => [:red],
:warn => [:yellow],
:info => [:green],
:debug => [:cyan],
:devel => [:magenta]
} unless defined?(ColoredLevels)
##
# Colorize our level.
#
# @param [String, Symbol] level
#
# @see Padrino::Logging::ColorizedLogger::ColoredLevels
#
def colorize(string, *colors)
colors.each do |c|
string = string.colorize(c)
end
string
end
def stylized_level(level)
style = ColoredLevels[level].map { |c| "\e[%dm" % String::Colorizer.colors[c] } * ''
[style, super, "\e[0m"] * ''
end
end
include Extensions
attr_accessor :auto_flush, :level, :log_static
attr_reader :buffer, :colorize_logging, :init_args, :log
##
# Configuration for a given environment, possible options are:
#
# :log_level:: Once of [:fatal, :error, :warn, :info, :debug]
# :stream:: Once of [:to_file, :null, :stdout, :stderr] our your custom stream
# :log_level::
# The log level from, e.g. :fatal or :info. Defaults to :warn in the
# production environment and :debug otherwise.
# :auto_flush::
# Whether the log should automatically flush after new messages are
# added. Defaults to true.
# :format_datetime:: Format of datetime. Defaults to: "%d/%b/%Y %H:%M:%S"
# :format_message:: Format of message. Defaults to: ""%s - - [%s] \"%s\"""
# :log_static:: Whether or not to show log messages for static files. Defaults to: false
# :colorize_logging:: Whether or not to colorize log messages. Defaults to: true
#
# @example
# Padrino::Logger::Config[:development] = { :log_level => :debug, :stream => :to_file }
# # or you can edit our defaults
# Padrino::Logger::Config[:development][:log_level] = :error
# # or you can use your stream
# Padrino::Logger::Config[:development][:stream] = StringIO.new
#
# Defaults are:
#
# :production => { :log_level => :warn, :stream => :to_file }
# :development => { :log_level => :debug, :stream => :stdout }
# :test => { :log_level => :fatal, :stream => :null }
#
# In some cases, configuring the loggers before loading the framework is necessary.
# You can do so by setting PADRINO_LOGGER:
#
# PADRINO_LOGGER = { :staging => { :log_level => :debug, :stream => :to_file }}
#
Config = {
:production => { :log_level => :warn, :stream => :to_file },
:development => { :log_level => :debug, :stream => :stdout, :format_datetime => '' },
:test => { :log_level => :debug, :stream => :null }
}
Config.merge!(PADRINO_LOGGER) if PADRINO_LOGGER
@@mutex = Mutex.new
def self.logger
@_logger || setup!
end
def self.logger=(logger)
logger.extend(Padrino::Logger::Extensions)
@_logger = logger
end
##
# Setup a new logger.
#
# @return [Padrino::Logger]
# A {Padrino::Logger} instance
#
def self.setup!
self.logger = begin
config_level = (PADRINO_LOG_LEVEL || Padrino.env || :test).to_sym # need this for PADRINO_LOG_LEVEL
config = Config[config_level]
unless config
warn("No logging configuration for :#{config_level} found, falling back to :production")
config = Config[:production]
end
stream = case config[:stream]
when :to_file
FileUtils.mkdir_p(Padrino.root('log')) unless File.exist?(Padrino.root('log'))
File.new(Padrino.root('log', "#{Padrino.env}.log"), 'a+')
when :null then StringIO.new
when :stdout then $stdout
when :stderr then $stderr
else config[:stream] # return itself, probabilly is a custom stream.
end
Padrino::Logger.new(config.merge(:stream => stream))
end
end
##
# To initialize the logger you create a new object, proxies to set_log.
#
# @param [Hash] options
#
# @option options [Symbol] :stream ($stdout)
# Either an IO object or a name of a logfile. Defaults to $stdout
#
# @option options [Symbol] :log_level (:production in the production environment and :debug otherwise)
# The log level from, e.g. :fatal or :info.
#
# @option options [Symbol] :auto_flush (true)
# Whether the log should automatically flush after new messages are
# added. Defaults to true.
#
# @option options [Symbol] :format_datetime (" [%d/%b/%Y %H:%M:%S] ")
# Format of datetime.
#
# @option options [Symbol] :format_message ("%s -%s%s")
# Format of message.
#
# @option options [Symbol] :log_static (false)
# Whether or not to show log messages for static files.
#
# @option options [Symbol] :colorize_logging (true)
# Whether or not to colorize log messages. Defaults to: true.
#
def initialize(options={})
@buffer = []
@auto_flush = options.has_key?(:auto_flush) ? options[:auto_flush] : true
@level = options[:log_level] ? Padrino::Logger::Levels[options[:log_level]] : Padrino::Logger::Levels[:debug]
@log = options[:stream] || $stdout
@log.sync = true
@format_datetime = options[:format_datetime] || "%d/%b/%Y %H:%M:%S"
@format_message = options[:format_message] || "%s - %s %s"
@log_static = options.has_key?(:log_static) ? options[:log_static] : false
@colorize_logging = options.has_key?(:colorize_logging) ? options[:colorize_logging] : true
colorize! if @colorize_logging
end
##
# Flush the entire buffer to the log object.
#
def flush
return unless @buffer.size > 0
@@mutex.synchronize do
@log.write(@buffer.join(''))
@buffer.clear
end
end
##
# Close and remove the current log object.
#
# @return [NilClass]
#
def close
flush
@log.close if @log.respond_to?(:close) && !@log.tty?
@log = nil
end
##
# Adds a message to the log - for compatibility with other loggers.
#
def add(level, message = nil)
write(message)
end
##
# Directly append message to the log.
#
# @param [String] message
# The message
#
def <<(message = nil)
message << "\n" unless message[-1] == ?\n
@@mutex.synchronize {
@buffer << message
}
flush if @auto_flush
message
end
alias :write :<<
def format(message, level)
@format_message % [stylized_level(level), colorize(Time.now.strftime(@format_datetime), :yellow), message.to_s.strip]
end
##
# Padrino::Logger::Rack forwards every request to an +app+ given, and
# logs a line in the Apache common log format to the +logger+, or
# rack.errors by default.
#
class Rack
def initialize(app, uri_root)
@app = app
@uri_root = uri_root.sub(/\/$/,"")
end
def call(env)
env['rack.logger'] = Padrino.logger
began_at = Time.now
status, header, body = @app.call(env)
log(env, status, header, began_at) if logger.debug?
[status, header, body]
end
private
def log(env, status, header, began_at)
return if env['sinatra.static_file'] && (!logger.respond_to?(:log_static) || !logger.log_static)
logger.bench(
env["REQUEST_METHOD"],
began_at,
[
@uri_root.to_s,
env["PATH_INFO"],
env["QUERY_STRING"].empty? ? "" : "?" + env["QUERY_STRING"],
' - ',
logger.colorize(status.to_s[0..3], :bold),
' ',
code_to_name(status)
] * '',
:debug,
:magenta
)
end
def code_to_name(status)
::Rack::Utils::HTTP_STATUS_CODES[status.to_i] || ''
end
end
end
end
module Kernel
##
# Define a logger available every where in our app
#
def logger
Padrino.logger
end
end

View File

@ -1,58 +0,0 @@
module Padrino
module Module
attr_accessor :root
##
# Register this module as being loaded from a gem. This automatically
# sets the root and therefore the dependency paths correctly.
#
# @param [String] name
# The name of the gem. Has to be the name as stated in the gemspec.
#
# @returns the gems root.
def gem!(name)
self.root = Padrino.gem(name, self)
end
##
# Helper method for file references within a Padrino module.
#
# @param [Array<String>] args
# The directories to join to {Module.root}.
#
# @return [String]
# The absolute path.
#
# @example
# module MyModule
# extend Padrino::Module
# gem! 'my_gem'
# end
# Module.root!
def root(*args)
File.expand_path(File.join(@root, *args))
end
##
# Returns the list of path globs to load as dependencies.
# Appends custom dependency patterns to the be loaded for Padrino.
#
# @return [Array<String>]
# The dependency paths.
#
# @example
# module MyModule
# extend Padrino::Module
# gem! 'my_gem'
# end
#
# Module.dependency_paths << "#{MyModule.root}/uploaders/*.rb"
#
def dependency_paths
[
"#{root}/lib/**/*.rb", "#{root}/shared/lib/**/*.rb",
"#{root}/models/**/*.rb", "#{root}/shared/models/**/*.rb"
]
end
end
end

View File

@ -1,239 +0,0 @@
module Padrino
##
# Represents a particular mounted Padrino application.
# Stores the name of the application (app folder name) and url mount path.
#
# @example
# Mounter.new("blog_app", :app_class => "Blog").to("/blog")
# Mounter.new("blog_app", :app_file => "/path/to/blog/app.rb").to("/blog")
#
class Mounter
DEFAULT_CASCADE = [404, 405]
class MounterException < RuntimeError
end
attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host, :cascade
##
# @param [String, Padrino::Application] name
# The app name or the {Padrino::Application} class.
#
# @param [Hash] options
# @option options [Symbol] :app_class (Detected from name)
# @option options [Symbol] :app_file (Automatically detected)
# @option options [Symbol] :app_obj (Detected)
# @option options [Symbol] :app_root (Directory of :app_file)
# @option options [Symbol] :gem The gem to load the app from (Detected from name)
#
def initialize(name, options={})
@name = name.to_s
@app_class = options[:app_class] || @name.camelize
@gem = options[:gem] || @app_class.split("::").first.underscore
@app_file = options[:app_file] || locate_app_file
@app_obj = options[:app_obj] || app_constant || locate_app_object
ensure_app_file! || ensure_app_object!
@app_root = options[:app_root] || (@app_obj.respond_to?(:root) && @app_obj.root || File.dirname(@app_file))
@uri_root = "/"
@cascade = options[:cascade] ? true == options[:cascade] ? DEFAULT_CASCADE.dup : Array(options[:cascade]) : []
Padrino::Reloader.exclude_constants << @app_class
end
##
# Registers the mounted application onto Padrino.
#
# @param [String] mount_url
# Path where we mount the app.
#
# @example
# Mounter.new("blog_app").to("/blog")
#
def to(mount_url)
@uri_root = mount_url
Padrino.insert_mounted_app(self)
self
end
##
# Registers the mounted application onto Padrino for the given host.
#
# @param [String] mount_host
# Host name.
#
# @example
# Mounter.new("blog_app").to("/blog").host("blog.padrino.org")
# Mounter.new("blog_app").host("blog.padrino.org")
# Mounter.new("catch_all").host(/.*\.padrino.org/)
#
def host(mount_host)
@app_host = mount_host
Padrino.insert_mounted_app(self)
self
end
##
# Maps Padrino application onto a Padrino::Router.
# For use in constructing a Rack application.
#
# @param [Padrino::Router]
#
# @return [Padrino::Router]
#
# @example
# @app.map_onto(router)
#
def map_onto(router)
app_data, app_obj = self, @app_obj
app_obj.set :uri_root, app_data.uri_root
app_obj.set :app_name, app_data.app_obj.app_name.to_s
app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
app_obj.set :public_folder, Padrino.root('public', app_data.uri_root) unless File.exist?(app_obj.public_folder)
app_obj.set :static, File.exist?(app_obj.public_folder) if app_obj.nil?
app_obj.set :cascade, app_data.cascade
app_obj.setup_application! # Initializes the app here with above settings.
router.map(:to => app_obj, :path => app_data.uri_root, :host => app_data.app_host)
end
###
# Returns the route objects for the mounted application.
#
def routes
app_obj.routes
end
###
# Returns the basic route information for each named route.
#
# @return [Array]
# Array of routes.
#
def named_routes
app_obj.routes.map { |route|
route_name = route.name.to_s
route_name.sub!(/^#{route.controller} /, "") if route.controller
name_array = "(#{route.controller ? %Q[:#{route.controller}] + ", " : ""}:#{route_name})"
request_method = route.request_methods.first
next if route.name.blank? || request_method == 'HEAD'
original_path = route.original_path.is_a?(Regexp) ? route.original_path.inspect : route.original_path
full_path = File.join(uri_root, original_path)
OpenStruct.new(:verb => request_method, :identifier => route.name, :name => name_array, :path => full_path)
}.compact
end
##
# Makes two Mounters equal if they have the same name and uri_root.
#
# @param [Padrino::Mounter] other
#
def ==(other)
other.is_a?(Mounter) && self.app_class == other.app_class && self.uri_root == other.uri_root
end
##
# @return [Padrino::Application]
# the class object for the app if defined, nil otherwise.
#
def app_constant
klass = Object
for piece in app_class.split("::")
piece = piece.to_sym
if klass.const_defined?(piece)
klass = klass.const_get(piece)
else
return
end
end
klass
end
protected
##
# Locates and requires the file to load the app constant.
#
def locate_app_object
@_app_object ||= begin
ensure_app_file!
Padrino.require_dependencies(app_file)
app_constant
end
end
##
# Returns the determined location of the mounted application main file.
#
def locate_app_file
candidates = []
candidates << app_constant.app_file if app_constant.respond_to?(:app_file) && File.exist?(app_constant.app_file.to_s)
candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
candidates << Padrino.mounted_root(name.downcase, "app.rb")
simple_name = name.split("::").last.downcase
mod_name = name.split("::")[0..-2].join("::")
Padrino.modules.each do |mod|
if mod.name == mod_name
candidates << mod.root(simple_name, "app.rb")
end
end
candidates << Padrino.root("app", "app.rb")
candidates.find { |candidate| File.exist?(candidate) }
end
###
# Raises an exception unless app_file is located properly.
#
def ensure_app_file!
message = "Unable to locate source file for app '#{app_class}', try with :app_file => '/path/app.rb'"
raise MounterException, message unless @app_file
end
###
# Raises an exception unless app_obj is defined properly.
#
def ensure_app_object!
message = "Unable to locate app for '#{app_class}', try with :app_class => 'MyAppClass'"
raise MounterException, message unless @app_obj
end
end
class << self
attr_writer :mounted_root # Set root directory where padrino searches mounted apps
##
# @param [Array] args
#
# @return [String]
# the root to the mounted apps base directory.
#
def mounted_root(*args)
Padrino.root(@mounted_root ||= "", *args)
end
##
# @return [Array]
# the mounted padrino applications (MountedApp objects)
#
def mounted_apps
@mounted_apps ||= []
end
##
# Inserts a Mounter object into the mounted applications (avoids duplicates).
#
# @param [Padrino::Mounter] mounter
#
def insert_mounted_app(mounter)
Padrino.mounted_apps.push(mounter) unless Padrino.mounted_apps.include?(mounter)
end
##
# Mounts a new sub-application onto Padrino project.
#
# @see Padrino::Mounter#new
#
# @example
# Padrino.mount("blog_app").to("/blog")
#
def mount(name, options={})
Mounter.new(name, options)
end
end
end

View File

@ -1,250 +0,0 @@
require 'pathname'
require 'padrino-core/reloader/rack'
require 'padrino-core/reloader/storage'
module Padrino
##
# High performance source code reloader middleware
#
module Reloader
##
# This reloader is suited for use in a many environments because each file
# will only be checked once and only one system call to stat(2) is made.
#
# Please note that this will not reload files in the background, and does so
# only when explicitly invoked.
#
extend self
# The modification times for every file in a project.
MTIMES = {}
##
# Specified folders can be excluded from the code reload detection process.
# Default excluded directories at Padrino.root are: test, spec, features, tmp, config, db and public
#
def exclude
@_exclude ||= Set.new %w(test spec tmp features config public db).map{ |path| Padrino.root(path) }
end
##
# Specified constants can be excluded from the code unloading process.
#
def exclude_constants
@_exclude_constants ||= Set.new
end
##
# Specified constants can be configured to be reloaded on every request.
# Default included constants are: [none]
#
def include_constants
@_include_constants ||= Set.new
end
##
# Reload apps and files with changes detected.
#
def reload!
rotation do |file|
next unless file_changed?(file)
reload_special(file) || reload_regular(file)
end
end
##
# Remove files and classes loaded with stat
#
def clear!
MTIMES.clear
Storage.clear!
end
##
# Returns true if any file changes are detected.
#
def changed?
rotation do |file|
break true if file_changed?(file)
end
end
##
# We lock dependencies sets to prevent reloading of protected constants
#
def lock!
klasses = ObjectSpace.classes do |klass|
klass._orig_klass_name.split('::').first
end
klasses |= Padrino.mounted_apps.map(&:app_class)
exclude_constants.merge(klasses)
end
##
# A safe Kernel::require which issues the necessary hooks depending on results
#
def safe_load(file, options={})
began_at = Time.now
file = figure_path(file)
return unless options[:force] || file_changed?(file)
Storage.prepare(file) # might call #safe_load recursively
logger.devel(file_new?(file) ? :loading : :reload, began_at, file)
begin
with_silence{ require(file) }
Storage.commit(file)
update_modification_time(file)
rescue Exception => e
unless options[:cyclic]
logger.error "#{e.class}: #{e.message}; #{e.backtrace.first}"
logger.error "Failed to load #{file}; removing partially defined constants"
end
Storage.rollback(file)
raise e
end
end
##
# Removes the specified class and constant.
#
def remove_constant(const)
return if constant_excluded?(const)
base, _, object = const.to_s.rpartition('::')
base = base.empty? ? Object : base.constantize
base.send :remove_const, object
logger.devel "Removed constant #{const} from #{base}"
rescue NameError
end
##
# Returns the list of special tracked files for Reloader.
#
def special_files
@special_files ||= Set.new
end
##
# Sets the list of special tracked files for Reloader.
#
def special_files=(files)
@special_files = Set.new(files)
end
private
##
# Returns absolute path of the file.
#
def figure_path(file)
return file if Pathname.new(file).absolute?
$LOAD_PATH.each do |path|
found = File.join(path, file)
return File.expand_path(found) if File.file?(found)
end
file
end
##
# Reloads the file if it's special. For now it's only I18n locale files.
#
def reload_special(file)
return unless special_files.any?{ |f| File.identical?(f, file) }
if defined?(I18n)
began_at = Time.now
I18n.reload!
update_modification_time(file)
logger.devel :reload, began_at, file
end
true
end
##
# Reloads ruby file and applications dependent on it.
#
def reload_regular(file)
apps = mounted_apps_of(file)
if apps.present?
apps.each { |app| app.app_obj.reload! }
update_modification_time(file)
else
safe_load(file)
reloadable_apps.each do |app|
app.app_obj.reload! if app.app_obj.dependencies.include?(file)
end
end
end
###
# Macro for mtime update.
#
def update_modification_time(file)
MTIMES[file] = File.mtime(file)
end
###
# Returns true if the file is new or it's modification time changed.
#
def file_changed?(file)
file_new?(file) || File.mtime(file) > MTIMES[file]
end
###
# Returns true if the file is new.
#
def file_new?(file)
MTIMES[file].nil?
end
##
# Return the mounted_apps providing the app location.
# Can be an array because in one app.rb we can define multiple Padrino::Application.
#
def mounted_apps_of(file)
Padrino.mounted_apps.select { |app| File.identical?(file, app.app_file) }
end
##
# Searches Ruby files in your +Padrino.load_paths+ , Padrino::Application.load_paths
# and monitors them for any changes.
#
def rotation
files_for_rotation.each do |file|
file = File.expand_path(file)
next if Reloader.exclude.any? { |base| file.start_with?(base) } || !File.file?(file)
yield file
end
nil
end
##
# Creates an array of paths for use in #rotation.
#
def files_for_rotation
files = Set.new
Padrino.load_paths.each{ |path| files += Dir.glob("#{path}/**/*.rb") }
reloadable_apps.each do |app|
files << app.app_file
files += app.app_obj.dependencies
end
files + special_files
end
def constant_excluded?(const)
(exclude_constants - include_constants).any?{ |c| const._orig_klass_name.start_with?(c) }
end
def reloadable_apps
Padrino.mounted_apps.select{ |app| app.app_obj.respond_to?(:reload) && app.app_obj.reload? }
end
##
# Disables output, yields block, switches output back.
#
def with_silence
verbosity_level, $-v = $-v, nil
yield
ensure
$-v = verbosity_level
end
end
end

View File

@ -1,26 +0,0 @@
module Padrino
module Reloader
##
# This class acts as a Rack middleware to be added to the application stack.
# This middleware performs a check and reload for source files at the start
# of each request, but also respects a specified cool down time
# during which no further action will be taken.
#
class Rack
def initialize(app, cooldown=1)
@app = app
@cooldown = cooldown
@last = (Time.now - cooldown)
end
# Invoked in order to perform the reload as part of the request stack.
def call(env)
if @cooldown && Time.now > @last + @cooldown
Thread.list.size > 1 ? Thread.exclusive { Padrino.reload! } : Padrino.reload!
@last = Time.now
end
@app.call(env)
end
end
end
end

View File

@ -1,55 +0,0 @@
module Padrino
module Reloader
module Storage
extend self
def clear!
files.each_key do |file|
remove(file)
$LOADED_FEATURES.delete(file)
end
@files = {}
end
def remove(name)
file = files[name] || return
file[:constants].each{ |constant| Reloader.remove_constant(constant) }
file[:features].each{ |feature| $LOADED_FEATURES.delete(feature) }
files.delete(name)
end
def prepare(name)
file = remove(name)
@old_entries ||= {}
@old_entries[name] = {
:constants => ObjectSpace.classes,
:features => old_features = Set.new($LOADED_FEATURES.dup)
}
features = file && file[:features] || []
features.each{ |feature| Reloader.safe_load(feature, :force => true) }
$LOADED_FEATURES.delete(name) if old_features.include?(name)
end
def commit(name)
entry = {
:constants => ObjectSpace.new_classes(@old_entries[name][:constants]),
:features => Set.new($LOADED_FEATURES) - @old_entries[name][:features] - [name]
}
files[name] = entry
@old_entries.delete(name)
end
def rollback(name)
new_constants = ObjectSpace.new_classes(@old_entries[name][:constants])
new_constants.each{ |klass| Reloader.remove_constant(klass) }
@old_entries.delete(name)
end
private
def files
@files ||= {}
end
end
end
end

View File

@ -1,94 +0,0 @@
module Padrino
##
# This class is an extended version of Rack::URLMap.
#
# Padrino::Router like Rack::URLMap dispatches in such a way that the
# longest paths are tried first, since they are most specific.
#
# Features:
#
# * Map a path to the specified App
# * Ignore server names (this solve issues with vhost and domain aliases)
# * Use hosts instead of server name for mappings (this help us with our vhost and domain aliases)
#
# @example
#
# routes = Padrino::Router.new do
# map(:path => "/", :to => PadrinoWeb, :host => "padrino.local")
# map(:path => "/", :to => Admin, :host => "admin.padrino.local")
# end
# run routes
#
# routes = Padrino::Router.new do
# map(:path => "/", :to => PadrinoWeb, :host => /*.padrino.local/)
# end
# run routes
#
# @api semipublic
class Router
def initialize(*mapping, &block)
@mapping = []
mapping.each { |m| map(m) }
instance_eval(&block) if block
end
##
# Map a route path and host to a specified application.
#
# @param [Hash] options
# The options to map.
# @option options [Sinatra::Application] :to
# The class of the application to mount.
# @option options [String] :path ("/")
# The path to map the specified application.
# @option options [String] :host
# The host to map the specified application.
#
# @example
# map(:path => "/", :to => PadrinoWeb, :host => "padrino.local")
#
# @return [Array] The sorted route mappings.
# @api semipublic
def map(options={})
path = options[:path] || "/"
host = options[:host]
app = options[:to]
raise ArgumentError, "paths need to start with /" if path[0] != ?/
raise ArgumentError, "app is required" if app.nil?
path = path.chomp('/')
match = Regexp.new("^#{Regexp.quote(path).gsub('/', '/+')}(.*)", nil, 'n')
host = Regexp.new("^#{Regexp.quote(host)}$", true, 'n') unless host.nil? || host.is_a?(Regexp)
@mapping << [host, path, match, app]
end
# The call handler setup to route a request given the mappings specified.
def call(env)
began_at = Time.now
path_info = env["PATH_INFO"].to_s
script_name = env['SCRIPT_NAME']
http_host = env['HTTP_HOST']
last_result = nil
@mapping.each do |host, path, match, app|
next unless host.nil? || http_host =~ host
next unless path_info =~ match && rest = $1
next unless rest.empty? || rest[0] == ?/
rest = "/" if rest.empty?
last_result = app.call(env.merge('SCRIPT_NAME' => script_name + path, 'PATH_INFO' => rest))
cascade_setting = app.respond_to?(:cascade) ? app.cascade : true
cascade_statuses = cascade_setting.respond_to?(:include?) ? cascade_setting : Mounter::DEFAULT_CASCADE
break unless cascade_setting && cascade_statuses.include?(last_result[0])
end
last_result || begin
Padrino::Logger::Rack.new(nil,'/').send(:log, env, 404, {}, began_at) if logger.debug?
[404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path_info}"]]
end
end
end
end

View File

@ -1,82 +0,0 @@
module Padrino
##
# Runs the Padrino apps as a self-hosted server using:
# thin, mongrel, or WEBrick in that order.
#
# @example
# Padrino.run! # with these defaults => host: "127.0.0.1", port: "3000", adapter: the first found
# Padrino.run!("0.0.0.0", "4000", "mongrel") # use => host: "0.0.0.0", port: "4000", adapter: "mongrel"
#
def self.run!(options={})
Padrino.load!
Server.start(Padrino.application, options)
end
##
# This module builds a Padrino server to run the project based on available handlers.
#
class Server < Rack::Server
# Server Handlers
Handlers = [:thin, :puma, :mongrel, :trinidad, :webrick]
# Starts the application on the available server with specified options.
def self.start(app, opts={})
options = {}.merge(opts) # We use a standard hash instead of Middleman::Util::HashWithIndifferentAccess
options.symbolize_keys!
options[:Host] = options.delete(:host) || '127.0.0.1'
options[:Port] = options.delete(:port) || 3000
options[:AccessLog] = []
if options[:daemonize]
options[:pid] = File.expand_path(options[:pid].blank? ? 'tmp/pids/server.pid' : opts[:pid])
FileUtils.mkdir_p(File.dirname(options[:pid]))
end
options[:server] = detect_rack_handler if options[:server].blank?
if options[:options].is_a?(Array)
parsed_server_options = options.delete(:options).map { |opt| opt.split('=', 2) }.flatten
server_options = Hash[*parsed_server_options].symbolize_keys!
options.merge!(server_options)
end
new(options, app).start
end
def initialize(options, app)
@options, @app = options, app
end
# Starts the application on the available server with specified options.
def start
puts "=> Padrino/#{Padrino.version} has taken the stage #{Padrino.env} at http://#{options[:Host]}:#{options[:Port]}"
[:INT, :TERM].each { |sig| trap(sig) { exit } }
super
ensure
puts "<= Padrino leaves the gun, takes the cannoli" unless options[:daemonize]
end
# The application the server will run.
def app
@app
end
alias :wrapped_app :app
def options
@options
end
private
# Detects the supported handler to use.
#
# @example
# detect_rack_handler => <ThinHandler>
#
def self.detect_rack_handler
Handlers.each do |handler|
begin
return handler if Rack::Handler.get(handler.to_s.downcase)
rescue LoadError
rescue NameError
end
end
fail "Server handler (#{Handlers.join(', ')}) not found."
end
end
end

View File

@ -1,259 +0,0 @@
##
# This file loads certain extensions required by Padrino from ActiveSupport.
#
require 'active_support/core_ext/module/aliasing' # alias_method_chain
require 'active_support/core_ext/hash/reverse_merge' # reverse_merge
require 'active_support/core_ext/hash/keys' # symbolize_keys
require 'active_support/core_ext/hash/indifferent_access' # params[:foo]
require 'active_support/core_ext/hash/slice' # slice
require 'active_support/core_ext/object/blank' # present?
require 'active_support/core_ext/array/extract_options' # extract_options
require 'active_support/inflector/methods' # constantize
require 'active_support/inflector/inflections' # pluralize
require 'active_support/core_ext/string/output_safety' # SafeBuffer and html_safe
require 'active_support/inflections' # load default inflections
require 'yaml' unless defined?(YAML) # load yaml for i18n
require 'win32console' if RUBY_PLATFORM =~ /(win|m)32/ # ruby color support for win
##
# This is an adapted version of active_support/core_ext/string/inflections.rb
# to prevent loading several dependencies including I18n gem.
#
# Issue: https://github.com/rails/rails/issues/1526
#
class String
##
# Returns the plural form of the word in the string.
#
# "post".pluralize # => "posts"
# "octopus".pluralize # => "octopi"
# "sheep".pluralize # => "sheep"
# "words".pluralize # => "words"
# "the blue mailman".pluralize # => "the blue mailmen"
# "CamelOctopus".pluralize # => "CamelOctopi"
#
def pluralize
ActiveSupport::Inflector.pluralize(self)
end
##
# Returns the singular form of the word in the string.
#
# "posts".singularize # => "post"
# "octopi".singularize # => "octopus"
# "sheep".singularize # => "sheep"
# "words".singularize # => "word"
# "the blue mailmen".singularize # => "the blue mailman"
# "CamelOctopi".singularize # => "CamelOctopus"
#
def singularize
ActiveSupport::Inflector.singularize(self)
end
##
# +constantize+ tries to find a declared constant with the name specified
# in the string. It raises a NameError when the name is not in CamelCase
# or is not initialized.
#
# "Module".constantize # => Module
# "Class".constantize # => Class
#
def constantize
ActiveSupport::Inflector.constantize(self)
end
##
# The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
#
# +underscore+ will also change '::' to '/' to convert namespaces to paths.
#
# "ActiveRecord".underscore # => "active_record"
# "ActiveRecord::Errors".underscore # => active_record/errors
#
def underscore
ActiveSupport::Inflector.underscore(self)
end
##
# By default, +camelize+ converts strings to UpperCamelCase. If the argument to camelize
# is set to <tt>:lower</tt> then camelize produces lowerCamelCase.
#
# +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
#
# "active_record".camelize # => "ActiveRecord"
# "active_record".camelize(:lower) # => "activeRecord"
# "active_record/errors".camelize # => "ActiveRecord::Errors"
# "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
#
def camelize(first_letter = :upper)
case first_letter
when :upper then ActiveSupport::Inflector.camelize(self, true)
when :lower then ActiveSupport::Inflector.camelize(self, false)
end
end
alias_method :camelcase, :camelize
##
# Create a class name from a plural table name like Rails does for table names to models.
# Note that this returns a string and not a class. (To convert to an actual class
# follow +classify+ with +constantize+.)
#
# "egg_and_hams".classify # => "EggAndHam"
# "posts".classify # => "Post"
#
# Singular names are not handled correctly.
#
# "business".classify # => "Busines"
#
def classify
ActiveSupport::Inflector.classify(self)
end
end
module ObjectSpace
class << self
##
# Returns all the classes in the object space.
# Optionally, a block can be passed, for example the following code
# would return the classes that start with the character "A":
#
# ObjectSpace.classes do |klass|
# if klass.to_s[0] == "A"
# klass
# end
# end
#
def classes(&block)
rs = Set.new
ObjectSpace.each_object(Class).each do |klass|
if block
if r = block.call(klass)
# add the returned value if the block returns something
rs << r
end
else
rs << klass
end
end
rs
end
##
# Returns a list of existing classes that are not included in "snapshot"
# This method is useful to get the list of new classes that were loaded
# after an event like requiring a file.
# Usage:
#
# snapshot = ObjectSpace.classes
# # require a file
# ObjectSpace.new_classes(snapshot)
#
def new_classes(snapshot)
self.classes do |klass|
if !snapshot.include?(klass)
klass
end
end
end
end
end
##
# FileSet helper method for iterating and interacting with files inside a directory
#
module FileSet
extend self
##
# Iterates over every file in the glob pattern and yields to a block
# Returns the list of files matching the glob pattern
# FileSet.glob('padrino-core/application/*.rb', __FILE__) { |file| load file }
#
def glob(glob_pattern, file_path=nil, &block)
glob_pattern = File.join(File.dirname(file_path), glob_pattern) if file_path
file_list = Dir.glob(glob_pattern).sort
file_list.each { |file| block.call(file) }
file_list
end
##
# Requires each file matched in the glob pattern into the application
# FileSet.glob_require('padrino-core/application/*.rb', __FILE__)
#
def glob_require(glob_pattern, file_path=nil)
glob(glob_pattern, file_path) { |f| require f }
end
end
##
# Removes indentation
# Add colors
#
# @example
# help <<-EOS.undent
# Here my help usage
# sample_code
#
# Fix
# EOS
# puts help.red.bold
#
class String
# colorize(:red)
def colorize(color)
Colorizer.send(color, self)
end
# Used to colorize strings for the shell
class Colorizer
# Returns colors integer mapping
def self.colors
@_colors ||= {
:clear => 0,
:bold => 1,
:black => 30,
:red => 31,
:green => 32,
:yellow => 33,
:blue => 34,
:magenta => 35,
:cyan => 36,
:white => 37
}
end
# Defines class level color methods
# i.e Colorizer.red("hello")
class << self
Colorizer.colors.each do |color, value|
define_method(color) do |target|
"\e[#{value}m" << target << "\e[0m"
end
end
end
end
# Strip unnecessary indentation of the front of a string
def undent
gsub(/^.{#{slice(/^ +/).size}}/, '')
end
end
##
# Make sure we can always use the class name
# In reloader for accessing class_name Foo._orig_klass_name
#
class Module
alias :_orig_klass_name :to_s
end
##
# Loads our locale configuration files
#
I18n.load_path += Dir["#{File.dirname(__FILE__)}/locale/*.yml"] if defined?(I18n)
##
# Used to determine if this file has already been required
#
module SupportLite; end

View File

@ -1,21 +0,0 @@
module Padrino
##
# This module it's used for bootstrap with padrino rake
# third party tasks, in your gem/plugin/extension you
# need only do this:
#
# @example
# Padrino::Tasks.files << yourtask.rb
# Padrino::Tasks.files.concat(Dir["/path/to/all/my/tasks/*.rb"])
# Padrino::Tasks.files.unshift("yourtask.rb")
#
module Tasks
##
# Returns a list of files to handle with padrino rake
#
def self.files
@files ||= []
end
end
end

View File

@ -1,20 +0,0 @@
#
# Manages current Padrino version for use in gem generation.
#
# We put this in a separate file so you can get padrino version
# without include full padrino core.
#
module Padrino
# The version constant for the current version of Padrino.
VERSION = '0.12.0' unless defined?(Padrino::VERSION)
#
# The current Padrino version.
#
# @return [String]
# The version number.
#
def self.version
VERSION
end
end # Padrino

View File

@ -1,44 +0,0 @@
#!/usr/bin/env gem build
# encoding: utf-8
require File.expand_path("../lib/padrino-core/version.rb", __FILE__)
Gem::Specification.new do |s|
s.name = "padrino-core"
s.rubyforge_project = "padrino-core"
s.authors = ["Padrino Team", "Nathan Esquenazi", "Davide D'Agostino", "Arthur Chiu"]
s.email = "padrinorb@gmail.com"
s.summary = "The required Padrino core gem"
s.homepage = "http://www.padrinorb.com"
s.description = "The Padrino core gem required for use of this framework"
s.required_rubygems_version = ">= 1.3.6"
s.version = Padrino.version
s.date = Time.now.strftime("%Y-%m-%d")
s.license = "MIT"
s.extra_rdoc_files = Dir["*.rdoc"]
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
s.rdoc_options = ["--charset=UTF-8"]
# TODO remove after a couple versions
# s.post_install_message = "\e[32m" + ("*" * 20)
# s.post_install_message << "\n UPGRADE NOTES\n\n\e[31m When upgrading, please 'enable :sessions' for each application"
# s.post_install_message << " as shown here:\e[0m http://bit.ly/kODKMx\n"
# s.post_install_message << "\e[31m When upgrading, please 'register Padrino::Rendering' for each application"
# s.post_install_message << " as shown here:\e[0m https://gist.github.com/1d36a35794dbbd664ea4"
# s.post_install_message << "\n\e[32m" + ("*" * 20) + "\n\e[0m"
s.add_dependency("tilt", "~> 1.4.1")
if ENV["SINATRA_EDGE"]
s.add_dependency("sinatra")
else
s.add_dependency("sinatra", "~> 1.4.2")
end
s.add_dependency("http_router", "~> 0.11.0")
s.add_dependency("thor", "~> 0.17.0")
s.add_dependency("activesupport", ">= 3.1")
s.add_dependency("rack-protection", ">= 1.5.0")
end

View File

@ -1,4 +0,0 @@
source 'https://rubygems.org'
# Specify your gem's dependencies in app_gem.gemspec
gemspec

View File

@ -1,3 +0,0 @@
class AppGem::App < Padrino::Application
set :version, AppGem::VERSION
end

View File

@ -1,17 +0,0 @@
# -*- encoding: utf-8 -*-
require File.expand_path('../lib/app_gem/version', __FILE__)
Gem::Specification.new do |gem|
gem.authors = ["Florian Gilcher"]
gem.email = ["florian.gilcher@asquera.de"]
gem.description = %q{TODO: Write a gem description}
gem.summary = %q{TODO: Write a gem summary}
gem.homepage = ""
gem.files = `git ls-files`.split($\)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.name = "app_gem"
gem.require_paths = ["app", "lib"]
gem.version = AppGem::VERSION
end

View File

@ -1,7 +0,0 @@
require 'padrino'
module AppGem
extend Padrino::Module
gem! 'app_gem'
end

View File

@ -1,3 +0,0 @@
module AppGem
VERSION = "0.0.1"
end

View File

@ -1,6 +0,0 @@
---
:test: bacon
:mock: mocha
:orm: datamapper
:renderer: erb
:script: jquery

View File

@ -1,7 +0,0 @@
.DS_Store
log/**/*
tmp/**/*
vendor/gems/gems
vendor/gems/specifications
vendor/gems/doc
vendor/gems/environment.rb

View File

@ -1,32 +0,0 @@
PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
module LibDemo
def self.give_me_a_random
@rand ||= rand(100)
end
end
class Complex1Demo < Padrino::Application
set :reload, true
get("/old"){ "Old Sinatra Way" }
end
class Complex2Demo < Padrino::Application
set :reload, true
get("/old"){ "Old Sinatra Way" }
controllers :var do
get(:destroy){ params.inspect }
end
get("/"){ "The magick number is: 12!" } # Change only the number!!!
end
Complex1Demo.controllers do
get("/"){ "Given random #{LibDemo.give_me_a_random}" }
end
Complex2Demo.controllers do
end
Padrino.load!

View File

@ -1,8 +0,0 @@
require 'resolv'
SystemDemo.helpers do
def resolv
Resolv.name
end
end

View File

@ -1,3 +0,0 @@
class Kiq < ::Sinatra::Base
set :root, '/weird'
end

View File

@ -1,2 +0,0 @@
class MyKlass < OpenStruct
end

View File

@ -1,4 +0,0 @@
class MyKlass
class MySubKlass
end
end

View File

@ -1,5 +0,0 @@
class Parent
def family
'Danes'
end
end

View File

@ -1,13 +0,0 @@
PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
class RenderDemo < Padrino::Application
set :reload, true
end
RenderDemo.controllers :blog do
get '/' do
render 'post'
end
end
Padrino.load!

View File

@ -1,33 +0,0 @@
PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
# Remove this comment if you want do some like this: ruby RACK_ENV=test app.rb
#
# require 'rubygems'
# require 'padrino-core'
#
class SimpleDemo < Padrino::Application
set :reload, true
before { true }
after { true }
error(404) { "404" }
end
SimpleDemo.controllers do
get "/" do
'The magick number is: 2767356926488785838763860464013972991031534522105386787489885890443740254365!' # Change only the number!!!
end
get "/rand" do
rand(2 ** 256).to_s
end
end
## If you want use this as a standalone app uncomment:
#
# Padrino.mount("SimpleDemo").to("/")
# Padrino.run! unless Padrino.loaded? # If you enable reloader prevent to re-run the app
#
# Then run it from your console: ruby -I"lib" test/fixtures/apps/simple.rb
#
Padrino.load!

View File

@ -1,10 +0,0 @@
PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
class StaticDemo < Padrino::Application
disable :reload
def self.reload!
fail 'reload! called'
end
end
Padrino.load!

View File

@ -1,13 +0,0 @@
PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
class SystemDemo < Padrino::Application
set :reload, true
end
SystemDemo.controllers do
get '/' do
resolv
end
end
Padrino.load!

View File

@ -1,9 +0,0 @@
# This file will be safe loaded three times.
# The first one fail because B and C constant are not defined
# The second one file because B requires C constant so will not be loaded
# The third one B and C are defined
# But here we need some of b.rb
A_result = [B, C]
A = "A"

View File

@ -1,4 +0,0 @@
# But here we need some of c.rb and a.rb
B_result = C
B = "B"

Some files were not shown because too many files have changed in this diff Show More