rubycut-sinatra-contrib 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.md +136 -0
- data/Rakefile +75 -0
- data/ideas.md +29 -0
- data/lib/sinatra/capture.rb +124 -0
- data/lib/sinatra/config_file.rb +167 -0
- data/lib/sinatra/content_for.rb +125 -0
- data/lib/sinatra/contrib.rb +39 -0
- data/lib/sinatra/contrib/all.rb +2 -0
- data/lib/sinatra/contrib/setup.rb +53 -0
- data/lib/sinatra/contrib/version.rb +17 -0
- data/lib/sinatra/cookies.rb +331 -0
- data/lib/sinatra/decompile.rb +120 -0
- data/lib/sinatra/engine_tracking.rb +96 -0
- data/lib/sinatra/extension.rb +95 -0
- data/lib/sinatra/json.rb +130 -0
- data/lib/sinatra/link_header.rb +132 -0
- data/lib/sinatra/multi_route.rb +87 -0
- data/lib/sinatra/namespace.rb +284 -0
- data/lib/sinatra/reloader.rb +394 -0
- data/lib/sinatra/respond_with.rb +249 -0
- data/lib/sinatra/streaming.rb +267 -0
- data/lib/sinatra/test_helpers.rb +87 -0
- data/sinatra-contrib.gemspec +127 -0
- data/spec/capture_spec.rb +93 -0
- data/spec/config_file/key_value.yml +6 -0
- data/spec/config_file/key_value.yml.erb +6 -0
- data/spec/config_file/key_value_override.yml +2 -0
- data/spec/config_file/missing_env.yml +4 -0
- data/spec/config_file/with_envs.yml +7 -0
- data/spec/config_file/with_nested_envs.yml +11 -0
- data/spec/config_file_spec.rb +63 -0
- data/spec/content_for/different_key.erb +1 -0
- data/spec/content_for/different_key.erubis +1 -0
- data/spec/content_for/different_key.haml +2 -0
- data/spec/content_for/different_key.slim +2 -0
- data/spec/content_for/layout.erb +1 -0
- data/spec/content_for/layout.erubis +1 -0
- data/spec/content_for/layout.haml +1 -0
- data/spec/content_for/layout.slim +1 -0
- data/spec/content_for/multiple_blocks.erb +4 -0
- data/spec/content_for/multiple_blocks.erubis +4 -0
- data/spec/content_for/multiple_blocks.haml +8 -0
- data/spec/content_for/multiple_blocks.slim +8 -0
- data/spec/content_for/multiple_yields.erb +3 -0
- data/spec/content_for/multiple_yields.erubis +3 -0
- data/spec/content_for/multiple_yields.haml +3 -0
- data/spec/content_for/multiple_yields.slim +3 -0
- data/spec/content_for/passes_values.erb +1 -0
- data/spec/content_for/passes_values.erubis +1 -0
- data/spec/content_for/passes_values.haml +1 -0
- data/spec/content_for/passes_values.slim +1 -0
- data/spec/content_for/same_key.erb +1 -0
- data/spec/content_for/same_key.erubis +1 -0
- data/spec/content_for/same_key.haml +2 -0
- data/spec/content_for/same_key.slim +2 -0
- data/spec/content_for/takes_values.erb +1 -0
- data/spec/content_for/takes_values.erubis +1 -0
- data/spec/content_for/takes_values.haml +3 -0
- data/spec/content_for/takes_values.slim +3 -0
- data/spec/content_for_spec.rb +213 -0
- data/spec/cookies_spec.rb +802 -0
- data/spec/decompile_spec.rb +44 -0
- data/spec/extension_spec.rb +33 -0
- data/spec/json_spec.rb +117 -0
- data/spec/link_header_spec.rb +100 -0
- data/spec/multi_route_spec.rb +60 -0
- data/spec/namespace/foo.erb +1 -0
- data/spec/namespace/nested/foo.erb +1 -0
- data/spec/namespace_spec.rb +676 -0
- data/spec/okjson.rb +581 -0
- data/spec/reloader/app.rb.erb +40 -0
- data/spec/reloader_spec.rb +441 -0
- data/spec/respond_with/bar.erb +1 -0
- data/spec/respond_with/bar.json.erb +1 -0
- data/spec/respond_with/foo.html.erb +1 -0
- data/spec/respond_with/not_html.sass +2 -0
- data/spec/respond_with_spec.rb +297 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/streaming_spec.rb +436 -0
- metadata +313 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008-2011 Nicolas Sanguinetti, entp.com, Konstantin Haase
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
'Software'), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
[![Build Status](https://secure.travis-ci.org/sinatra/sinatra-contrib.png)](http://travis-ci.org/sinatra/sinatra-contrib)
|
2
|
+
|
3
|
+
Collection of common Sinatra extensions, semi-officially supported.
|
4
|
+
|
5
|
+
# Goals
|
6
|
+
|
7
|
+
* For every future Sinatra release, have at least one fully compatible release
|
8
|
+
* High code quality, high test coverage
|
9
|
+
* Include plugins people usually ask for a lot
|
10
|
+
|
11
|
+
# Included extensions
|
12
|
+
|
13
|
+
## Common Extensions
|
14
|
+
|
15
|
+
These are common extension which will not add significant overhead or change any
|
16
|
+
behavior of already existing APIs. They do not add any dependencies not already
|
17
|
+
installed with this gem.
|
18
|
+
|
19
|
+
Currently included:
|
20
|
+
|
21
|
+
* `sinatra/capture`: Let's you capture the content of blocks in templates.
|
22
|
+
|
23
|
+
* `sinatra/config_file`: Allows loading configuration from yaml files.
|
24
|
+
|
25
|
+
* `sinatra/content_for`: Adds Rails-style `content_for` helpers to Haml, Erb,
|
26
|
+
Erubis and Slim.
|
27
|
+
|
28
|
+
* `sinatra/cookies`: A `cookies` helper for reading and writing cookies.
|
29
|
+
|
30
|
+
* `sinatra/engine_tracking`: Adds methods like `haml?` that allow helper
|
31
|
+
methods to check whether they are called from within a template.
|
32
|
+
|
33
|
+
* `sinatra/json`: Adds a `#json` helper method to return JSON documents.
|
34
|
+
|
35
|
+
* `sinatra/link_header`: Helpers for generating `link` HTML tags and
|
36
|
+
corresponding `Link` HTTP headers. Adds `link`, `stylesheet` and `prefetch`
|
37
|
+
helper methods.
|
38
|
+
|
39
|
+
* `sinatra/multi_route`: Adds ability to define one route block for multiple
|
40
|
+
routes and multiple or custom HTTP verbs.
|
41
|
+
|
42
|
+
* `sinatra/namespace`: Adds namespace support to Sinatra.
|
43
|
+
|
44
|
+
* `sinatra/respond_with`: Choose action and/or template automatically
|
45
|
+
depending on the incoming request. Adds helpers `respond_to` and
|
46
|
+
`respond_with`.
|
47
|
+
|
48
|
+
|
49
|
+
## Custom Extensions
|
50
|
+
|
51
|
+
These extensions may add additional dependencies and enhance the behavior of the
|
52
|
+
existing APIs.
|
53
|
+
|
54
|
+
Currently included:
|
55
|
+
|
56
|
+
* `sinatra/decompile`: Recreates path patterns from Sinatra's internal data
|
57
|
+
structures (used by other extensions).
|
58
|
+
|
59
|
+
* `sinatra/reloader`: Automatically reloads Ruby files on code changes.
|
60
|
+
|
61
|
+
## Other Tools
|
62
|
+
|
63
|
+
* `sinatra/extension`: Mixin for writing your own Sinatra extensions.
|
64
|
+
|
65
|
+
* `sinatra/test_helpers`: Helper methods to ease testing your Sinatra
|
66
|
+
application. Partly extracted from Sinatra. Testing framework agnostic
|
67
|
+
|
68
|
+
# Installation
|
69
|
+
Add `gem 'sinatra-contrib'` to *Gemfile*, then execute `bundle install`.
|
70
|
+
|
71
|
+
If you don't use Bundler, install the gem manually by executing `gem install sinatra-contrib` in your command line.
|
72
|
+
|
73
|
+
|
74
|
+
# Usage
|
75
|
+
|
76
|
+
## Classic Style
|
77
|
+
|
78
|
+
A single extension (example: sinatra-content-for):
|
79
|
+
|
80
|
+
``` ruby
|
81
|
+
require 'sinatra'
|
82
|
+
require 'sinatra/content_for'
|
83
|
+
```
|
84
|
+
|
85
|
+
Common extensions:
|
86
|
+
|
87
|
+
``` ruby
|
88
|
+
require 'sinatra'
|
89
|
+
require 'sinatra/contrib'
|
90
|
+
```
|
91
|
+
|
92
|
+
All extensions:
|
93
|
+
|
94
|
+
``` ruby
|
95
|
+
require 'sinatra'
|
96
|
+
require 'sinatra/contrib/all'
|
97
|
+
```
|
98
|
+
|
99
|
+
## Modular Style
|
100
|
+
|
101
|
+
A single extension (example: sinatra-content-for):
|
102
|
+
|
103
|
+
``` ruby
|
104
|
+
require 'sinatra/base'
|
105
|
+
require 'sinatra/content_for'
|
106
|
+
require 'sinatra/namespace'
|
107
|
+
|
108
|
+
class MyApp < Sinatra::Base
|
109
|
+
# Note: Some modules are extensions, some helpers, see the specific
|
110
|
+
# documentation or the source
|
111
|
+
helpers Sinatra::ContentFor
|
112
|
+
register Sinatra::Namespace
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
Common extensions:
|
117
|
+
|
118
|
+
``` ruby
|
119
|
+
require 'sinatra/base'
|
120
|
+
require 'sinatra/contrib'
|
121
|
+
|
122
|
+
class MyApp < Sinatra::Base
|
123
|
+
register Sinatra::Contrib
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
All extensions:
|
128
|
+
|
129
|
+
``` ruby
|
130
|
+
require 'sinatra/base'
|
131
|
+
require 'sinatra/contrib/all'
|
132
|
+
|
133
|
+
class MyApp < Sinatra::Base
|
134
|
+
register Sinatra::Contrib
|
135
|
+
end
|
136
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
require 'open-uri'
|
3
|
+
require 'yaml'
|
4
|
+
require 'sinatra/contrib/version'
|
5
|
+
|
6
|
+
desc "run specs"
|
7
|
+
task(:spec) { ruby '-S rspec spec -c' }
|
8
|
+
task(:test => :spec)
|
9
|
+
task(:default => :spec)
|
10
|
+
|
11
|
+
namespace :doc do
|
12
|
+
task :readmes do
|
13
|
+
Dir.glob 'lib/sinatra/*.rb' do |file|
|
14
|
+
excluded_files = %w[lib/sinatra/contrib.rb lib/sinatra/capture.rb lib/sinatra/engine_tracking.rb]
|
15
|
+
next if excluded_files.include?(file)
|
16
|
+
doc = File.read(file)[/^module Sinatra(\n)+( #[^\n]*\n)*/m].scan(/^ *#(?!#) ?(.*)\n/).join("\n")
|
17
|
+
file = "doc/#{file[4..-4].tr("/_", "-")}.rdoc"
|
18
|
+
Dir.mkdir "doc" unless File.directory? "doc"
|
19
|
+
puts "writing #{file}"
|
20
|
+
File.open(file, "w") { |f| f << doc }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
task :all => [:readmes]
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "generate documentation"
|
28
|
+
task :doc => 'doc:all'
|
29
|
+
|
30
|
+
desc "generate gemspec"
|
31
|
+
task 'sinatra-contrib.gemspec' do
|
32
|
+
content = File.read 'sinatra-contrib.gemspec'
|
33
|
+
|
34
|
+
fields = {
|
35
|
+
:authors => `git shortlog -sn`.scan(/[^\d\s].*/),
|
36
|
+
:email => `git shortlog -sne`.scan(/[^<]+@[^>]+/),
|
37
|
+
:files => `git ls-files`.split("\n").reject { |f| f =~ /^(\.|Gemfile)/ }
|
38
|
+
}
|
39
|
+
|
40
|
+
fields.each do |field, values|
|
41
|
+
updated = " s.#{field} = ["
|
42
|
+
updated << values.map { |v| "\n %p" % v }.join(',')
|
43
|
+
updated << "\n ]"
|
44
|
+
content.sub!(/ s\.#{field} = \[\n( .*\n)* \]/, updated)
|
45
|
+
end
|
46
|
+
|
47
|
+
content.sub! /(s\.version.*=\s+).*/, "\\1\"#{Sinatra::Contrib::VERSION}\""
|
48
|
+
File.open('sinatra-contrib.gemspec', 'w') { |f| f << content }
|
49
|
+
end
|
50
|
+
|
51
|
+
task :gemspec => 'sinatra-contrib.gemspec'
|
52
|
+
|
53
|
+
desc 'update travis config to correspond to sinatra'
|
54
|
+
task :travis, [:branch] do |t, a|
|
55
|
+
a.with_defaults :branch => :master
|
56
|
+
data = YAML.load open("https://raw.github.com/sinatra/sinatra/#{a.branch}/.travis.yml")
|
57
|
+
data["notifications"]["recipients"] << "ohhgabriel@gmail.com"
|
58
|
+
File.open('.travis.yml', 'w') { |f| f << data.to_yaml }
|
59
|
+
system 'git add .travis.yml && git diff --cached .travis.yml'
|
60
|
+
end
|
61
|
+
|
62
|
+
task :release => :gemspec do
|
63
|
+
sh <<-SH
|
64
|
+
rm -Rf sinatra-contrib*.gem &&
|
65
|
+
gem build sinatra-contrib.gemspec &&
|
66
|
+
gem install sinatra-contrib*.gem --local &&
|
67
|
+
gem push sinatra-contrib*.gem &&
|
68
|
+
git commit --allow-empty -a -m '#{Sinatra::Contrib::VERSION} release' &&
|
69
|
+
git tag -s v#{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
|
70
|
+
git tag -s #{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
|
71
|
+
git push && (git push sinatra || true) &&
|
72
|
+
git push --tags && (git push sinatra --tags || true)
|
73
|
+
SH
|
74
|
+
end
|
75
|
+
|
data/ideas.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
* Extension that does something like this:
|
2
|
+
|
3
|
+
def build(*)
|
4
|
+
if settings.memcached?
|
5
|
+
use Rack::Cache, :backend => :memcached
|
6
|
+
use Rack::Session::Memcached
|
7
|
+
# ...
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
* `sinatra-smart-cache`: update cache header only if arguments are more
|
13
|
+
restrictive than curent value, set caching headers that way for most helper
|
14
|
+
methods (i.e. `sass` or `send_file`)
|
15
|
+
|
16
|
+
* Some verbose logging extension: Log what filters, routes, error handlers,
|
17
|
+
templates, and so on is used.
|
18
|
+
|
19
|
+
* Form helpers, with forms as first class objects that accepts hashes or
|
20
|
+
something, so the form meta data can also be used to expose a JSON API or
|
21
|
+
similar, possibly defining routes (like "Sinatra's Hat"), strictly using
|
22
|
+
the ActiveModel API.
|
23
|
+
|
24
|
+
* Extend `sinatra-content-for` to support Liquid, Radius, Markaby, Nokogiri and
|
25
|
+
Builder. At least the first two probably involve patching Tilt.
|
26
|
+
|
27
|
+
* Rewrite of `sinatra-compass`?
|
28
|
+
|
29
|
+
* Helpers for HTML escaping and such.
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/engine_tracking'
|
3
|
+
require 'backports'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
#
|
7
|
+
# = Sinatra::Capture
|
8
|
+
#
|
9
|
+
# Extension that enables blocks inside other extensions.
|
10
|
+
# It currently works for erb, slim and haml.
|
11
|
+
# Enables mixing of different template languages.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
#
|
15
|
+
# # in hello_world.erb
|
16
|
+
#
|
17
|
+
# Say
|
18
|
+
# <% a = capture do %>World<% end %>
|
19
|
+
# Hello <%= a %>!
|
20
|
+
#
|
21
|
+
# # in hello_world.slim
|
22
|
+
#
|
23
|
+
# | Say
|
24
|
+
# - a = capture do
|
25
|
+
# | World
|
26
|
+
# | Hello #{a}!
|
27
|
+
#
|
28
|
+
# # in hello_world.haml
|
29
|
+
#
|
30
|
+
# Say
|
31
|
+
# - a = capture do
|
32
|
+
# World
|
33
|
+
# Hello #{a.strip}!
|
34
|
+
#
|
35
|
+
#
|
36
|
+
# You can also use nested blocks.
|
37
|
+
#
|
38
|
+
# Example
|
39
|
+
#
|
40
|
+
# # in hello_world.erb
|
41
|
+
#
|
42
|
+
# Say
|
43
|
+
# <% a = capture do %>
|
44
|
+
# <% b = capture do %>World<% end %>
|
45
|
+
# <%= b %>!
|
46
|
+
# <% end %>
|
47
|
+
# Hello <%= a.strip %>
|
48
|
+
#
|
49
|
+
#
|
50
|
+
# The main advantage of capture is mixing of different template engines.
|
51
|
+
#
|
52
|
+
# Example
|
53
|
+
#
|
54
|
+
# # in mix_me_up.slim
|
55
|
+
#
|
56
|
+
# - two = capture do
|
57
|
+
# - erb "<%= 1 + 1 %>"
|
58
|
+
# | 1 + 1 = #{two}
|
59
|
+
#
|
60
|
+
# == Usage
|
61
|
+
#
|
62
|
+
# === Classic Application
|
63
|
+
#
|
64
|
+
# In a classic application simply require the helpers, and start using them:
|
65
|
+
#
|
66
|
+
# require "sinatra"
|
67
|
+
# require "sinatra/capture"
|
68
|
+
#
|
69
|
+
# # The rest of your classic application code goes here...
|
70
|
+
#
|
71
|
+
# === Modular Application
|
72
|
+
#
|
73
|
+
# In a modular application you need to require the helpers, and then tell
|
74
|
+
# the application you will use them:
|
75
|
+
#
|
76
|
+
# require "sinatra/base"
|
77
|
+
# require "sinatra/capture"
|
78
|
+
#
|
79
|
+
# class MyApp < Sinatra::Base
|
80
|
+
# helpers Sinatra::Capture
|
81
|
+
#
|
82
|
+
# # The rest of your modular application code goes here...
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
module Capture
|
86
|
+
include Sinatra::EngineTracking
|
87
|
+
|
88
|
+
DUMMIES = {
|
89
|
+
:haml => "!= capture_haml(*args, &block)",
|
90
|
+
:erubis => "<% @capture = yield(*args) %>",
|
91
|
+
:slim => "== yield(*args)"
|
92
|
+
}
|
93
|
+
|
94
|
+
def capture(*args, &block)
|
95
|
+
@capture = nil
|
96
|
+
if current_engine == :ruby
|
97
|
+
result = block[*args]
|
98
|
+
elsif current_engine == :erb
|
99
|
+
@_out_buf, _buf_was = '', @_out_buf
|
100
|
+
block[*args]
|
101
|
+
result = eval('@_out_buf', block.binding)
|
102
|
+
@_out_buf = _buf_was
|
103
|
+
else
|
104
|
+
buffer = eval '_buf if defined?(_buf)', block.binding
|
105
|
+
old_buffer = buffer.dup if buffer
|
106
|
+
dummy = DUMMIES.fetch(current_engine)
|
107
|
+
options = { :layout => false, :locals => {:args => args, :block => block }}
|
108
|
+
|
109
|
+
buffer.try :clear
|
110
|
+
result = render(current_engine, dummy, options, &block)
|
111
|
+
end
|
112
|
+
result.strip.empty? && @capture ? @capture : result
|
113
|
+
ensure
|
114
|
+
buffer.try :replace, old_buffer
|
115
|
+
end
|
116
|
+
|
117
|
+
def capture_later(&block)
|
118
|
+
engine = current_engine
|
119
|
+
proc { |*a| with_engine(engine) { @capture = capture(*a, &block) }}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
helpers Capture
|
124
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'yaml'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
|
7
|
+
# = Sinatra::ConfigFile
|
8
|
+
#
|
9
|
+
# <tt>Sinatra::ConfigFile</tt> is an extension that allows you to load the
|
10
|
+
# application's configuration from YAML files. It automatically detects if
|
11
|
+
# the files contains specific environment settings and it will use the
|
12
|
+
# corresponding to the current one.
|
13
|
+
#
|
14
|
+
# You can access those options through +settings+ within the application. If
|
15
|
+
# you try to get the value for a setting that hasn't been defined in the
|
16
|
+
# config file for the current environment, you will get whatever it was set
|
17
|
+
# to in the application.
|
18
|
+
#
|
19
|
+
# == Usage
|
20
|
+
#
|
21
|
+
# Once you have written your configurations to a YAML file you can tell the
|
22
|
+
# extension to load them. See below for more information about how these
|
23
|
+
# files are interpreted.
|
24
|
+
#
|
25
|
+
# For the examples, lets assume the following config.yml file:
|
26
|
+
#
|
27
|
+
# greeting: Welcome to my file configurable application
|
28
|
+
#
|
29
|
+
# === Classic Application
|
30
|
+
#
|
31
|
+
# require "sinatra"
|
32
|
+
# require "sinatra/config_file"
|
33
|
+
#
|
34
|
+
# config_file 'path/to/config.yml'
|
35
|
+
#
|
36
|
+
# get '/' do
|
37
|
+
# @greeting = settings.greeting
|
38
|
+
# haml :index
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # The rest of your classic application code goes here...
|
42
|
+
#
|
43
|
+
# === Modular Application
|
44
|
+
#
|
45
|
+
# require "sinatra/base"
|
46
|
+
# require "sinatra/config_file"
|
47
|
+
#
|
48
|
+
# class MyApp < Sinatra::Base
|
49
|
+
# register Sinatra::ConfigFile
|
50
|
+
#
|
51
|
+
# config_file 'path/to/config.yml'
|
52
|
+
#
|
53
|
+
# get '/' do
|
54
|
+
# @greeting = settings.greeting
|
55
|
+
# haml :index
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# # The rest of your modular application code goes here...
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# === Config File Format
|
62
|
+
#
|
63
|
+
# In its most simple form this file is just a key-value list:
|
64
|
+
#
|
65
|
+
# foo: bar
|
66
|
+
# something: 42
|
67
|
+
# nested:
|
68
|
+
# a: 1
|
69
|
+
# b: 2
|
70
|
+
#
|
71
|
+
# But it also can provide specific environment configuration. There are two
|
72
|
+
# ways to do that: at the file level and at the setting level. They are
|
73
|
+
# illustrated, repsectively, as follows:
|
74
|
+
#
|
75
|
+
# development:
|
76
|
+
# foo: development
|
77
|
+
# bar: bar
|
78
|
+
# test:
|
79
|
+
# foo: test
|
80
|
+
# bar: bar
|
81
|
+
# production:
|
82
|
+
# foo: production
|
83
|
+
# bar: bar
|
84
|
+
#
|
85
|
+
# and
|
86
|
+
#
|
87
|
+
# foo:
|
88
|
+
# development: development
|
89
|
+
# test: test
|
90
|
+
# production: production
|
91
|
+
# bar: bar
|
92
|
+
#
|
93
|
+
# In either case, <tt>settings.foo</tt> will return the environment name, and
|
94
|
+
# <tt>settings.bar</tt> will return <tt>"bar"</tt>.
|
95
|
+
#
|
96
|
+
# Be aware that if you have a different environment, besides development,
|
97
|
+
# test and production, you will also need to adjust the +environments+
|
98
|
+
# setting, otherwise the settings will not load. For instance, when
|
99
|
+
# you also have a staging environment:
|
100
|
+
#
|
101
|
+
# set :environments, %w{development test production staging}
|
102
|
+
#
|
103
|
+
# If you wish to provide defaults that may be shared among all the environments,
|
104
|
+
# this can be done by using one of the existing environments as the default using
|
105
|
+
# the YAML alias, and then overwriting values in the other environments:
|
106
|
+
#
|
107
|
+
# development: &common_settings
|
108
|
+
# foo: 'foo'
|
109
|
+
# bar: 'bar'
|
110
|
+
#
|
111
|
+
# production:
|
112
|
+
# <<: *common_settings
|
113
|
+
# bar: 'baz' # override the default value
|
114
|
+
#
|
115
|
+
module ConfigFile
|
116
|
+
|
117
|
+
# When the extension is registered sets the +environments+ setting to the
|
118
|
+
# traditional environments: development, test and production.
|
119
|
+
def self.registered(base)
|
120
|
+
base.set :environments, %w[test production development]
|
121
|
+
end
|
122
|
+
|
123
|
+
# Loads the configuration from the YAML files whose +paths+ are passed as
|
124
|
+
# arguments, filtering the settings for the current environment. Note that
|
125
|
+
# these +paths+ can actually be globs.
|
126
|
+
def config_file(*paths)
|
127
|
+
Dir.chdir(root || '.') do
|
128
|
+
paths.each do |pattern|
|
129
|
+
Dir.glob(pattern) do |file|
|
130
|
+
$stderr.puts "loading config file '#{file}'" if logging?
|
131
|
+
document = IO.read(file)
|
132
|
+
document = ERB.new(document).result if file.split('.').include?('erb')
|
133
|
+
yaml = config_for_env(YAML.load(document)) || {}
|
134
|
+
yaml.each_pair do |key, value|
|
135
|
+
for_env = config_for_env(value)
|
136
|
+
set key, for_env unless value and for_env.nil? and respond_to? key
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
# Given a +hash+ with some application configuration it returns the
|
146
|
+
# settings applicable to the current environment. Note that this can only
|
147
|
+
# be done when all the keys of +hash+ are environment names included in the
|
148
|
+
# +environments+ setting (which is an Array of Strings). Also, the
|
149
|
+
# returned config is a indifferently accessible Hash, which means that you
|
150
|
+
# can get its values using Strings or Symbols as keys.
|
151
|
+
def config_for_env(hash)
|
152
|
+
if hash.respond_to? :keys and hash.keys.all? { |k| environments.include? k.to_s }
|
153
|
+
hash = hash[environment.to_s] || hash[environment.to_sym]
|
154
|
+
end
|
155
|
+
|
156
|
+
if hash.respond_to? :to_hash
|
157
|
+
indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
158
|
+
indifferent_hash.merge hash.to_hash
|
159
|
+
else
|
160
|
+
hash
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
register ConfigFile
|
166
|
+
Delegator.delegate :config_file
|
167
|
+
end
|