sinatra-contrib 1.4.7 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -16
- data/Rakefile +0 -1
- data/lib/sinatra/config_file.rb +8 -2
- data/lib/sinatra/content_for.rb +63 -1
- data/lib/sinatra/contrib.rb +1 -1
- data/lib/sinatra/contrib/version.rb +1 -12
- data/lib/sinatra/cookies.rb +1 -1
- data/lib/sinatra/link_header.rb +2 -2
- data/lib/sinatra/namespace.rb +90 -18
- data/lib/sinatra/reloader.rb +15 -1
- data/lib/sinatra/required_params.rb +71 -0
- data/lib/sinatra/respond_with.rb +7 -5
- data/sinatra-contrib.gemspec +14 -10
- data/spec/capture_spec.rb +5 -5
- data/spec/config_file/key_value.yml +1 -0
- data/spec/config_file_spec.rb +27 -13
- data/spec/content_for/footer.haml +1 -1
- data/spec/content_for/footer.slim +1 -1
- data/spec/content_for_spec.rb +65 -36
- data/spec/cookies_spec.rb +167 -173
- data/spec/extension_spec.rb +4 -4
- data/spec/json_spec.rb +11 -11
- data/spec/link_header_spec.rb +13 -13
- data/spec/multi_route_spec.rb +13 -13
- data/spec/namespace_spec.rb +190 -140
- data/spec/reloader_spec.rb +56 -31
- data/spec/required_params_spec.rb +68 -0
- data/spec/respond_with_spec.rb +58 -56
- data/spec/streaming_spec.rb +57 -57
- metadata +37 -22
- data/lib/sinatra/decompile.rb +0 -127
- data/spec/decompile_spec.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2219eae01829dc23fe37858de893ee0bae5ae98
|
4
|
+
data.tar.gz: 04ee39f956e7420d07cbc39f853dc97f43a9702b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c2e640a53fd704cb2fe4f152da9dac0b75bc69b59386ce805b30f2e7e9716dcebbaf493f9f63738cf57407515082dcf4f6bdbde142546708356fb5423434c23
|
7
|
+
data.tar.gz: b35240ae66107dc1ebdd39e69a6efaebe6580ec852bf8f552b0c6f0e28404636b5ba3fafba3ccf0c84358b954772fc7c76204e8801f4f4348b35d20d42f3e075
|
data/README.md
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
|
1
|
+
# Sinatra::Contrib
|
2
2
|
|
3
3
|
Collection of common Sinatra extensions, semi-officially supported.
|
4
4
|
|
5
|
-
|
5
|
+
## Goals
|
6
6
|
|
7
7
|
* For every future Sinatra release, have at least one fully compatible release
|
8
8
|
* High code quality, high test coverage
|
9
9
|
* Include plugins people usually ask for a lot
|
10
10
|
|
11
|
-
|
11
|
+
## Included extensions
|
12
12
|
|
13
|
-
|
13
|
+
### Common Extensions
|
14
14
|
|
15
15
|
These are common extension which will not add significant overhead or change any
|
16
16
|
behavior of already existing APIs. They do not add any dependencies not already
|
@@ -49,34 +49,45 @@ Currently included:
|
|
49
49
|
logger instance using +logger+ setting. That logger then will
|
50
50
|
be available as #logger helper method in your routes and views.
|
51
51
|
|
52
|
-
|
52
|
+
* `sinatra/required_params`: Ensure if required query parameters exist
|
53
|
+
|
54
|
+
### Custom Extensions
|
53
55
|
|
54
56
|
These extensions may add additional dependencies and enhance the behavior of the
|
55
57
|
existing APIs.
|
56
58
|
|
57
59
|
Currently included:
|
58
60
|
|
59
|
-
* `sinatra/decompile`: Recreates path patterns from Sinatra's internal data
|
60
|
-
structures (used by other extensions).
|
61
|
-
|
62
61
|
* `sinatra/reloader`: Automatically reloads Ruby files on code changes.
|
63
62
|
|
64
|
-
|
63
|
+
### Other Tools
|
65
64
|
|
66
65
|
* `sinatra/extension`: Mixin for writing your own Sinatra extensions.
|
67
66
|
|
68
67
|
* `sinatra/test_helpers`: Helper methods to ease testing your Sinatra
|
69
68
|
application. Partly extracted from Sinatra. Testing framework agnostic
|
70
69
|
|
71
|
-
|
72
|
-
|
70
|
+
## Installation
|
71
|
+
|
72
|
+
Add `gem 'sinatra-contrib'` to *Gemfile*, then execute `bundle install`.
|
73
73
|
|
74
74
|
If you don't use Bundler, install the gem manually by executing `gem install sinatra-contrib` in your command line.
|
75
75
|
|
76
|
+
### Git
|
77
|
+
|
78
|
+
If you want to use the gem from git, for whatever reason, you can do the following:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
github 'sinatra/sinatra' do
|
82
|
+
gem 'sinatra-contrib'
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
Within this block you can also specify other gems from this git repository.
|
76
87
|
|
77
|
-
|
88
|
+
## Usage
|
78
89
|
|
79
|
-
|
90
|
+
### Classic Style
|
80
91
|
|
81
92
|
A single extension (example: sinatra-content-for):
|
82
93
|
|
@@ -99,7 +110,7 @@ require 'sinatra'
|
|
99
110
|
require 'sinatra/contrib/all'
|
100
111
|
```
|
101
112
|
|
102
|
-
|
113
|
+
### Modular Style
|
103
114
|
|
104
115
|
A single extension (example: sinatra-content-for):
|
105
116
|
|
@@ -138,7 +149,7 @@ class MyApp < Sinatra::Base
|
|
138
149
|
end
|
139
150
|
```
|
140
151
|
|
141
|
-
|
152
|
+
### Documentation
|
142
153
|
|
143
154
|
For more info check the [official docs](http://www.sinatrarb.com/contrib/) and
|
144
|
-
[api docs](http://rubydoc.info/gems/sinatra-contrib
|
155
|
+
[api docs](http://www.rubydoc.info/gems/sinatra-contrib).
|
data/Rakefile
CHANGED
@@ -57,7 +57,6 @@ task :release => :gemspec do
|
|
57
57
|
gem push sinatra-contrib*.gem &&
|
58
58
|
git commit --allow-empty -a -m '#{Sinatra::Contrib::VERSION} release' &&
|
59
59
|
git tag -s v#{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
|
60
|
-
git tag -s #{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
|
61
60
|
git push && (git push origin master || true) &&
|
62
61
|
git push --tags && (git push origin --tags || true)
|
63
62
|
SH
|
data/lib/sinatra/config_file.rb
CHANGED
@@ -128,9 +128,9 @@ module Sinatra
|
|
128
128
|
Dir.chdir(root || '.') do
|
129
129
|
paths.each do |pattern|
|
130
130
|
Dir.glob(pattern) do |file|
|
131
|
+
raise UnsupportedConfigType unless ['.yml', '.erb'].include?(File.extname(file))
|
131
132
|
$stderr.puts "loading config file '#{file}'" if logging?
|
132
|
-
document = IO.read(file)
|
133
|
-
document = ERB.new(document).result if file.split('.').include?('erb')
|
133
|
+
document = ERB.new(IO.read(file)).result
|
134
134
|
yaml = config_for_env(YAML.load(document)) || {}
|
135
135
|
yaml.each_pair do |key, value|
|
136
136
|
for_env = config_for_env(value)
|
@@ -141,6 +141,12 @@ module Sinatra
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
+
class UnsupportedConfigType < Exception
|
145
|
+
def message
|
146
|
+
'Invalid config file type, use .yml or .yml.erb'
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
144
150
|
private
|
145
151
|
|
146
152
|
# Given a +hash+ with some application configuration it returns the
|
data/lib/sinatra/content_for.rb
CHANGED
@@ -27,6 +27,15 @@ module Sinatra
|
|
27
27
|
# # layout.erb
|
28
28
|
# <%= yield_content :some_key %>
|
29
29
|
#
|
30
|
+
# If you have provided +yield_content+ with a block and no content for the
|
31
|
+
# specified key is found, it will render the results of the block provided
|
32
|
+
# to yield_content.
|
33
|
+
#
|
34
|
+
# # layout.erb
|
35
|
+
# <%= yield_content :some_key_with_no_content do %>
|
36
|
+
# <chunk of="default html">...</chunk>
|
37
|
+
# <% end %>
|
38
|
+
#
|
30
39
|
# === Classic Application
|
31
40
|
#
|
32
41
|
# To use the helpers in a classic application all you need to do is require
|
@@ -59,6 +68,46 @@ module Sinatra
|
|
59
68
|
# layout, inside the <head> tag, and each view can call <tt>content_for</tt>
|
60
69
|
# setting the appropriate set of tags that should be added to the layout.
|
61
70
|
#
|
71
|
+
# == Limitations
|
72
|
+
#
|
73
|
+
# Due to the rendering process limitation using <tt><%= yield_content %></tt>
|
74
|
+
# from within nested templates do not work above the <tt><%= yield %> statement.
|
75
|
+
# For more details https://github.com/sinatra/sinatra-contrib/issues/140#issuecomment-48831668
|
76
|
+
#
|
77
|
+
# # app.rb
|
78
|
+
# get '/' do
|
79
|
+
# erb :body, :layout => :layout do
|
80
|
+
# erb :foobar
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# # foobar.erb
|
85
|
+
# <% content_for :one do %>
|
86
|
+
# <script>
|
87
|
+
# alert('one');
|
88
|
+
# </script>
|
89
|
+
# <% end %>
|
90
|
+
# <% content_for :two do %>
|
91
|
+
# <script>
|
92
|
+
# alert('two');
|
93
|
+
# </script>
|
94
|
+
# <% end %>
|
95
|
+
#
|
96
|
+
# Using <tt><%= yield_content %></tt> before <tt><%= yield %></tt> will cause only the second
|
97
|
+
# alert to display:
|
98
|
+
#
|
99
|
+
# # body.erb
|
100
|
+
# # Display only second alert
|
101
|
+
# <%= yield_content :one %>
|
102
|
+
# <%= yield %>
|
103
|
+
# <%= yield_content :two %>
|
104
|
+
#
|
105
|
+
# # body.erb
|
106
|
+
# # Display both alerts
|
107
|
+
# <%= yield %>
|
108
|
+
# <%= yield_content :one %>
|
109
|
+
# <%= yield_content :two %>
|
110
|
+
#
|
62
111
|
module ContentFor
|
63
112
|
include Capture
|
64
113
|
|
@@ -68,6 +117,10 @@ module Sinatra
|
|
68
117
|
# <script type="text/javascript" src="/foo.js"></script>
|
69
118
|
# <% end %>
|
70
119
|
#
|
120
|
+
# You can also pass an immediate value instead of a block:
|
121
|
+
#
|
122
|
+
# <% content_for :title, "foo" %>
|
123
|
+
#
|
71
124
|
# You can call +content_for+ multiple times with the same key
|
72
125
|
# (in the example +:head+), and when you render the blocks for
|
73
126
|
# that key all of them will be rendered, in the same order you
|
@@ -75,7 +128,8 @@ module Sinatra
|
|
75
128
|
#
|
76
129
|
# Your blocks can also receive values, which are passed to them
|
77
130
|
# by <tt>yield_content</tt>
|
78
|
-
def content_for(key, &block)
|
131
|
+
def content_for(key, value = nil, &block)
|
132
|
+
block ||= proc { |*| value }
|
79
133
|
content_blocks[key.to_sym] << capture_later(&block)
|
80
134
|
end
|
81
135
|
|
@@ -93,6 +147,13 @@ module Sinatra
|
|
93
147
|
content_blocks[key.to_sym].any?
|
94
148
|
end
|
95
149
|
|
150
|
+
# Unset a named block of content. For example:
|
151
|
+
#
|
152
|
+
# <% clear_content_for :head %>
|
153
|
+
def clear_content_for(key)
|
154
|
+
content_blocks.delete(key.to_sym) if content_for?(key)
|
155
|
+
end
|
156
|
+
|
96
157
|
# Render the captured blocks for a given key. For example:
|
97
158
|
#
|
98
159
|
# <head>
|
@@ -111,6 +172,7 @@ module Sinatra
|
|
111
172
|
# Would pass <tt>1</tt> and <tt>2</tt> to all the blocks registered
|
112
173
|
# for <tt>:head</tt>.
|
113
174
|
def yield_content(key, *args)
|
175
|
+
return yield(*args) if block_given? && content_blocks[key.to_sym].empty?
|
114
176
|
content_blocks[key.to_sym].map { |b| capture(*args, &b) }.join
|
115
177
|
end
|
116
178
|
|
data/lib/sinatra/contrib.rb
CHANGED
@@ -19,13 +19,13 @@ module Sinatra
|
|
19
19
|
helpers :JSON
|
20
20
|
helpers :LinkHeader
|
21
21
|
helpers :Streaming
|
22
|
+
helpers :RequiredParams
|
22
23
|
end
|
23
24
|
|
24
25
|
##
|
25
26
|
# Other extensions you don't want to be loaded unless needed.
|
26
27
|
module Custom
|
27
28
|
# register :Compass
|
28
|
-
register :Decompile
|
29
29
|
register :Reloader
|
30
30
|
end
|
31
31
|
|
@@ -1,17 +1,6 @@
|
|
1
1
|
module Sinatra
|
2
2
|
module Contrib
|
3
|
-
|
4
|
-
VERSION
|
5
|
-
end
|
6
|
-
|
7
|
-
SIGNATURE = [1, 4, 7]
|
8
|
-
VERSION = SIGNATURE.join('.')
|
9
|
-
|
10
|
-
VERSION.extend Comparable
|
11
|
-
def VERSION.<=>(other)
|
12
|
-
other = other.split('.').map { |i| i.to_i } if other.respond_to? :split
|
13
|
-
SIGNATURE <=> Array(other)
|
14
|
-
end
|
3
|
+
VERSION = ::Sinatra::VERSION
|
15
4
|
end
|
16
5
|
end
|
17
6
|
|
data/lib/sinatra/cookies.rb
CHANGED
data/lib/sinatra/link_header.rb
CHANGED
@@ -90,7 +90,7 @@ module Sinatra
|
|
90
90
|
link = (response["Link"] ||= "")
|
91
91
|
|
92
92
|
urls.map do |url|
|
93
|
-
link << "
|
93
|
+
link << ",\n" unless link.empty?
|
94
94
|
link << (http_pattern % url)
|
95
95
|
html_pattern % url
|
96
96
|
end.join "\n"
|
@@ -117,7 +117,7 @@ module Sinatra
|
|
117
117
|
def link_headers
|
118
118
|
yield if block_given?
|
119
119
|
return "" unless response.include? "Link"
|
120
|
-
response["Link"].
|
120
|
+
response["Link"].split(",\n").map do |line|
|
121
121
|
url, *opts = line.split(';').map(&:strip)
|
122
122
|
"<link href=\"#{url[1..-2]}\" #{opts.join " "} />"
|
123
123
|
end.join "\n"
|
data/lib/sinatra/namespace.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'backports'
|
2
2
|
require 'sinatra/base'
|
3
|
-
require '
|
3
|
+
require 'mustermann'
|
4
4
|
|
5
5
|
module Sinatra
|
6
6
|
|
@@ -48,6 +48,14 @@ module Sinatra
|
|
48
48
|
# # More admin routes...
|
49
49
|
# end
|
50
50
|
#
|
51
|
+
# Regex is also accepted:
|
52
|
+
#
|
53
|
+
# namespace /\/posts\/([^\/&?]+)\// do
|
54
|
+
# get { haml :blog }
|
55
|
+
#
|
56
|
+
# # More blog routes...
|
57
|
+
# end
|
58
|
+
#
|
51
59
|
# When you define a filter or an error handler, or register an extension or a
|
52
60
|
# set of helpers within a namespace, they only affect the routes defined in
|
53
61
|
# it. For instance, lets define a before filter to prevent the access of
|
@@ -89,6 +97,18 @@ module Sinatra
|
|
89
97
|
# # More admin routes...
|
90
98
|
# end
|
91
99
|
#
|
100
|
+
# Redirecting within the namespace can be done using redirect_to:
|
101
|
+
#
|
102
|
+
# namespace '/admin' do
|
103
|
+
# get '/foo' do
|
104
|
+
# redirect_to '/bar' # Redirects to /admin/bar
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# get '/foo' do
|
108
|
+
# redirect '/bar' # Redirects to /bar
|
109
|
+
# end
|
110
|
+
# end
|
111
|
+
#
|
92
112
|
# === Classic Application Setup
|
93
113
|
#
|
94
114
|
# To be able to use namespaces in a classic application all you need to do is
|
@@ -97,7 +117,8 @@ module Sinatra
|
|
97
117
|
# require "sinatra"
|
98
118
|
# require "sinatra/namespace"
|
99
119
|
#
|
100
|
-
#
|
120
|
+
# namespace '/users' do
|
121
|
+
# end
|
101
122
|
#
|
102
123
|
# === Modular Application Setup
|
103
124
|
#
|
@@ -110,9 +131,60 @@ module Sinatra
|
|
110
131
|
# class MyApp < Sinatra::Base
|
111
132
|
# register Sinatra::Namespace
|
112
133
|
#
|
113
|
-
#
|
134
|
+
# namespace '/users' do
|
135
|
+
# end
|
114
136
|
# end
|
115
137
|
#
|
138
|
+
# === Within an extension
|
139
|
+
#
|
140
|
+
# To be able to use namespaces within an extension, you need to first create
|
141
|
+
# an extension. This includes defining the `registered(app)` method in the
|
142
|
+
# module.
|
143
|
+
#
|
144
|
+
# require 'sinatra/base' # For creating Sinatra extensions
|
145
|
+
# require 'sinatra/namespace' # To create namespaces
|
146
|
+
#
|
147
|
+
# module Zomg # Keep everything under "Zomg" namespace for sanity
|
148
|
+
# module Routes # Define a new "Routes" module
|
149
|
+
#
|
150
|
+
# self.registered(app)
|
151
|
+
# # First, register the Namespace extension
|
152
|
+
# app.register Sinatra::Namespace
|
153
|
+
#
|
154
|
+
# # This defines an `/api` namespace on the application
|
155
|
+
# app.namespace '/api' do
|
156
|
+
# get '/users' do
|
157
|
+
# # do something with `GET "/api/users"`
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# end
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# # Lastly, register the extension to use in our app
|
165
|
+
# Sinatra.register Routes
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
# In order to use this extension, is the same as any other Sinatra extension:
|
169
|
+
#
|
170
|
+
# module Zomg
|
171
|
+
# # Define our app class, we use modular app for this example
|
172
|
+
# class App < Sinatra::Base
|
173
|
+
# # this gives us all the namespaces we defined earlier
|
174
|
+
# register Routes
|
175
|
+
#
|
176
|
+
# get '/' do
|
177
|
+
# "Welcome to my application!"
|
178
|
+
# end
|
179
|
+
# end
|
180
|
+
# end
|
181
|
+
#
|
182
|
+
# Zomg::App.run! # Don't forget to start your app ;)
|
183
|
+
#
|
184
|
+
# Phew! That was a mouthful.
|
185
|
+
#
|
186
|
+
# I hope that helps you use `Sinatra::Namespace` in every way imaginable!
|
187
|
+
#
|
116
188
|
module Namespace
|
117
189
|
def self.new(base, pattern, conditions = {}, &block)
|
118
190
|
Module.new do
|
@@ -137,6 +209,10 @@ module Sinatra
|
|
137
209
|
def template_cache
|
138
210
|
super.fetch(:nested, @namespace) { Tilt::Cache.new }
|
139
211
|
end
|
212
|
+
|
213
|
+
def redirect_to(uri, *args)
|
214
|
+
redirect("#{@namespace.pattern}#{uri}", *args)
|
215
|
+
end
|
140
216
|
end
|
141
217
|
|
142
218
|
module SharedMethods
|
@@ -147,7 +223,6 @@ module Sinatra
|
|
147
223
|
|
148
224
|
module NamespacedMethods
|
149
225
|
include SharedMethods
|
150
|
-
include Sinatra::Decompile
|
151
226
|
attr_reader :base, :templates
|
152
227
|
|
153
228
|
def self.prefixed(*names)
|
@@ -187,9 +262,10 @@ module Sinatra
|
|
187
262
|
end
|
188
263
|
|
189
264
|
def error(*codes, &block)
|
190
|
-
args = Sinatra::Base.send(:compile!, "ERROR",
|
265
|
+
args = Sinatra::Base.send(:compile!, "ERROR", /.*/, block)
|
191
266
|
codes = codes.map { |c| Array(c) }.flatten
|
192
267
|
codes << Exception if codes.empty?
|
268
|
+
codes << Sinatra::NotFound if codes.include?(404)
|
193
269
|
|
194
270
|
codes.each do |c|
|
195
271
|
errors = @errors[c] ||= []
|
@@ -226,6 +302,10 @@ module Sinatra
|
|
226
302
|
template name, &block
|
227
303
|
end
|
228
304
|
|
305
|
+
def pattern
|
306
|
+
@pattern
|
307
|
+
end
|
308
|
+
|
229
309
|
private
|
230
310
|
|
231
311
|
def app
|
@@ -246,22 +326,14 @@ module Sinatra
|
|
246
326
|
end
|
247
327
|
|
248
328
|
def prefixed_path(a, b)
|
249
|
-
return a || b ||
|
250
|
-
|
251
|
-
a, b = regexpify(a), regexpify(b) unless a.class == b.class
|
252
|
-
path = a.class.new "#{a}#{b}"
|
253
|
-
path = /^#{path}$/ if path.is_a? Regexp and base == app
|
254
|
-
path
|
255
|
-
end
|
329
|
+
return a || b || /.*/ unless a and b
|
330
|
+
return Mustermann.new(b) if a == /.*/
|
256
331
|
|
257
|
-
|
258
|
-
pattern = Sinatra::Base.send(:compile, pattern).first.inspect
|
259
|
-
pattern.gsub! /^\/(\^|\\A)?|(\$|\\z)?\/$/, ''
|
260
|
-
Regexp.new pattern
|
332
|
+
Mustermann.new(a) + Mustermann.new(b)
|
261
333
|
end
|
262
334
|
|
263
335
|
def prefixed(method, pattern = nil, conditions = {}, &block)
|
264
|
-
default =
|
336
|
+
default = /.*/ if method == :before or method == :after
|
265
337
|
pattern, conditions = compile pattern, conditions, default
|
266
338
|
result = base.send(method, pattern, conditions, &block)
|
267
339
|
invoke_hook :route_added, method.to_s.upcase, pattern, block
|
@@ -281,7 +353,7 @@ module Sinatra
|
|
281
353
|
include SharedMethods
|
282
354
|
end
|
283
355
|
|
284
|
-
def self.
|
356
|
+
def self.extended(base)
|
285
357
|
base.extend BaseMethods
|
286
358
|
end
|
287
359
|
end
|