sinatra-namespace 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +12 -2
- data/lib/sinatra/namespace.rb +87 -4
- data/spec/sinatra/namespace_spec.rb +67 -1
- data/spec/spec_helper.rb +1 -1
- metadata +14 -14
data/README.md
CHANGED
@@ -34,6 +34,16 @@ Classic style:
|
|
34
34
|
end
|
35
35
|
|
36
36
|
namspace "/ruby" do
|
37
|
+
before { @an_important_note = "filters work, too" }
|
38
|
+
|
39
|
+
after do
|
40
|
+
@an_important_note = nil # don't tell
|
41
|
+
end
|
42
|
+
|
43
|
+
not_found do
|
44
|
+
"ruby does not know this ditty"
|
45
|
+
end
|
46
|
+
|
37
47
|
helpers do
|
38
48
|
def posts
|
39
49
|
super.where :topic => "ruby"
|
@@ -108,7 +118,7 @@ So, how does one create a namespace from a module without that auto detection? S
|
|
108
118
|
Installation
|
109
119
|
------------
|
110
120
|
|
111
|
-
gem install sinatra-namespace
|
121
|
+
gem install sinatra-namespace
|
112
122
|
|
113
123
|
Alternatives
|
114
124
|
------------
|
@@ -119,7 +129,7 @@ If that is no what you are looking for, you have two alternative directions.
|
|
119
129
|
Simple prefixing, shares all state/helpers:
|
120
130
|
|
121
131
|
require "sinatra/base"
|
122
|
-
require "monkey"
|
132
|
+
require "monkey-lib"
|
123
133
|
|
124
134
|
admin_prefix = "/this/is/the/admin/prefix"
|
125
135
|
get(admin_prefix) { haml :admin_index }
|
data/lib/sinatra/namespace.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
-
require "monkey"
|
1
|
+
require "monkey-lib"
|
2
2
|
require "sinatra/base"
|
3
3
|
require "sinatra/sugar"
|
4
4
|
require "sinatra/advanced_routes"
|
5
5
|
|
6
6
|
module Sinatra
|
7
7
|
module Namespace
|
8
|
-
DONT_FORWARD = %w[
|
8
|
+
DONT_FORWARD = %w[call configure disable enable new register reset! run! set use template]
|
9
9
|
|
10
10
|
module NestedMethods
|
11
|
+
def errors
|
12
|
+
@errors ||= {}
|
13
|
+
end
|
14
|
+
|
11
15
|
def prefix(value = nil)
|
12
16
|
@prefix = value if value
|
13
17
|
@prefix
|
@@ -29,6 +33,14 @@ module Sinatra
|
|
29
33
|
def delete(name = nil, options = {}, &block); prefixed(:delete, name, options, &block); end
|
30
34
|
def head(name = nil, options = {}, &block); prefixed(:head, name, options, &block); end
|
31
35
|
|
36
|
+
def error(codes=Exception, &block)
|
37
|
+
[*codes].each { |c| errors[c] = block }
|
38
|
+
end
|
39
|
+
|
40
|
+
def not_found(&block)
|
41
|
+
error(404, &block)
|
42
|
+
end
|
43
|
+
|
32
44
|
def respond_to?(name)
|
33
45
|
super or (base.respond_to? name and forward? name)
|
34
46
|
end
|
@@ -37,8 +49,28 @@ module Sinatra
|
|
37
49
|
(super + base.methods(*args).select { |m| forward? m }).uniq
|
38
50
|
end
|
39
51
|
|
52
|
+
def before_filters
|
53
|
+
@before_filters ||= []
|
54
|
+
end
|
55
|
+
|
56
|
+
def after_filters
|
57
|
+
@after_filters ||= []
|
58
|
+
end
|
59
|
+
|
60
|
+
def before(&block)
|
61
|
+
before_filters << block
|
62
|
+
end
|
63
|
+
|
64
|
+
def after(&block)
|
65
|
+
after_filters << block
|
66
|
+
end
|
67
|
+
|
40
68
|
private
|
41
69
|
|
70
|
+
def always_activate
|
71
|
+
get(/.*/) { pass }
|
72
|
+
end
|
73
|
+
|
42
74
|
def application
|
43
75
|
klass = self
|
44
76
|
klass = klass.base while klass.respond_to? :base
|
@@ -63,8 +95,22 @@ module Sinatra
|
|
63
95
|
base.send(verb, path, options, &wrapper)
|
64
96
|
end
|
65
97
|
|
66
|
-
def
|
98
|
+
def prepare_instance(app)
|
99
|
+
return if app.is_a? self
|
100
|
+
base.prepare_instance app if base.respond_to? :prepare_instance
|
101
|
+
class << app
|
102
|
+
@filters ||= {}
|
103
|
+
@filters[:after] ||= []
|
104
|
+
@after_filters ||= []
|
105
|
+
end
|
106
|
+
before_filters.each { |block| app.instance_eval(&block) }
|
107
|
+
after_filters.each { |block| app.singleton_class.after(&block) }
|
67
108
|
app.extend self
|
109
|
+
end
|
110
|
+
|
111
|
+
def wrap(unbound_method, app, *args)
|
112
|
+
prepare_instance app
|
113
|
+
app.current_namespace = self
|
68
114
|
unbound_method.bind(app).call(*args)
|
69
115
|
end
|
70
116
|
|
@@ -82,7 +128,8 @@ module Sinatra
|
|
82
128
|
|
83
129
|
def self.registered(klass)
|
84
130
|
klass.register Sinatra::Sugar
|
85
|
-
klass.
|
131
|
+
klass.__send__ :include, InstanceMethods
|
132
|
+
klass.enable :merge_namespaces, :auto_namespace, :always_activate_namespaces
|
86
133
|
end
|
87
134
|
|
88
135
|
def self.make_namespace(mod, options = {})
|
@@ -96,9 +143,44 @@ module Sinatra
|
|
96
143
|
mod.extend self
|
97
144
|
mod.extend NestedMethods
|
98
145
|
options.each { |k,v| mod.send(k, v) }
|
146
|
+
mod.send(:always_activate) if options[:base].always_activate_namespaces?
|
99
147
|
mod
|
100
148
|
end
|
101
149
|
|
150
|
+
module InstanceMethods
|
151
|
+
attr_accessor :current_namespace
|
152
|
+
|
153
|
+
if Sinatra::VERSION > '1.0' or Sinatra::Base.respond_to? :filters # master is still 1.0
|
154
|
+
def filter!(type, base = self.class)
|
155
|
+
super
|
156
|
+
if type == :after and base == self.class and singleton_class.filters and singleton_class.after_filters
|
157
|
+
singleton_class.after_filters.each { |b| instance_eval(&b) }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
else
|
161
|
+
def after_filter!(base = self.class)
|
162
|
+
super
|
163
|
+
if base == self.class and singleton_class.after_filters
|
164
|
+
singleton_class.after_filters.each { |b| instance_eval(&b) }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def error_block!(*keys)
|
170
|
+
keys.detect do |key|
|
171
|
+
base = current_namespace || self.class
|
172
|
+
while base.respond_to? :errors
|
173
|
+
if block = base.errors[key]
|
174
|
+
# found a handler, eval and return result
|
175
|
+
return instance_eval(&block)
|
176
|
+
else
|
177
|
+
base = base.respond_to?(:base) ? base.base : base.superclass
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
102
184
|
def make_namespace(mod, options = {})
|
103
185
|
Sinatra::Namespace.make_namespace mod, options.merge(:base => self)
|
104
186
|
end
|
@@ -108,6 +190,7 @@ module Sinatra
|
|
108
190
|
@namespaces ||= {}
|
109
191
|
@namespaces[prefix] ||= namespace prefix, false
|
110
192
|
@namespaces[prefix].class_eval(&block) if block
|
193
|
+
@namespaces[prefix]
|
111
194
|
else
|
112
195
|
mod = make_namespace Module.new, :prefix => prefix
|
113
196
|
mod.class_eval(&block) if block
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require File.expand_path("../../spec_helper", __FILE__)
|
2
2
|
|
3
3
|
describe Sinatra::Namespace do
|
4
|
+
it_should_behave_like 'sinatra'
|
5
|
+
|
4
6
|
[:get, :head, :post, :put, :delete].each do |verb|
|
5
7
|
describe "HTTP #{verb.to_s.upcase}" do
|
6
8
|
before :each do
|
@@ -20,7 +22,7 @@ describe Sinatra::Namespace do
|
|
20
22
|
browse_route(verb, "/foo/bar").body.should == "baz" unless verb == :head
|
21
23
|
end
|
22
24
|
|
23
|
-
it "should
|
25
|
+
it "should allows adding routes with no path" do
|
24
26
|
app.namespace "/foo" do
|
25
27
|
send(verb) { "bar" }
|
26
28
|
end
|
@@ -28,6 +30,18 @@ describe Sinatra::Namespace do
|
|
28
30
|
browse_route(verb, "/foo").body.should == "bar" unless verb == :head
|
29
31
|
end
|
30
32
|
|
33
|
+
it "allows nesting" do
|
34
|
+
app.namespace "/foo" do
|
35
|
+
namespace "/bar" do
|
36
|
+
namespace "/baz" do
|
37
|
+
send(verb) { 'foobarbaz' }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
browse_route(verb, "/foo/bar/baz").should be_ok
|
42
|
+
browse_route(verb, "/foo/bar/baz").body.should == "foobarbaz" unless verb == :head
|
43
|
+
end
|
44
|
+
|
31
45
|
it "allows regular expressions" do
|
32
46
|
app.namespace %r{/\d\d} do
|
33
47
|
send(verb) { "foo" }
|
@@ -48,6 +62,28 @@ describe Sinatra::Namespace do
|
|
48
62
|
end
|
49
63
|
end
|
50
64
|
|
65
|
+
describe :filters do
|
66
|
+
it 'should trigger before filters for namespaces' do
|
67
|
+
app.before { settings.set :foo, 0 }
|
68
|
+
app.namespace('/foo') do
|
69
|
+
before { settings.set :foo, settings.foo + 1 }
|
70
|
+
send(verb) { }
|
71
|
+
end
|
72
|
+
browse_route(verb, '/foo').should be_ok
|
73
|
+
app.foo.should == 1
|
74
|
+
end
|
75
|
+
it 'should trigger after filters for namespaces' do
|
76
|
+
$foo = 0
|
77
|
+
app.after { $foo += 2 }
|
78
|
+
app.namespace('/foo') do
|
79
|
+
after { $foo += 1 }
|
80
|
+
send(verb) { }
|
81
|
+
end
|
82
|
+
browse_route(verb, '/foo').should be_ok
|
83
|
+
$foo.should == 3
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
51
87
|
describe :make_namespace do
|
52
88
|
it "extends modules make_namespace is called on" do
|
53
89
|
mod = Module.new
|
@@ -181,4 +217,34 @@ describe Sinatra::Namespace do
|
|
181
217
|
|
182
218
|
end
|
183
219
|
end
|
220
|
+
|
221
|
+
describe :errors do
|
222
|
+
it "should allow custom error handlers with not found" do
|
223
|
+
app.namespace('/en') { always_activate }
|
224
|
+
app.namespace('/de') do
|
225
|
+
always_activate
|
226
|
+
not_found { 'nicht gefunden' }
|
227
|
+
end
|
228
|
+
get('/foo').status.should == 404
|
229
|
+
last_response.body.should_not == 'nicht gefunden'
|
230
|
+
get('/en/foo').status.should == 404
|
231
|
+
last_response.body.should_not == 'nicht gefunden'
|
232
|
+
get('/de/foo').status.should == 404
|
233
|
+
last_response.body.should == 'nicht gefunden'
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should allow custom error handlers with error" do
|
237
|
+
app.namespace('/en') { always_activate }
|
238
|
+
app.namespace('/de') do
|
239
|
+
always_activate
|
240
|
+
error(404) { 'nicht gefunden' }
|
241
|
+
end
|
242
|
+
get('/foo').status.should == 404
|
243
|
+
last_response.body.should_not == 'nicht gefunden'
|
244
|
+
get('/en/foo').status.should == 404
|
245
|
+
last_response.body.should_not == 'nicht gefunden'
|
246
|
+
get('/de/foo').status.should == 404
|
247
|
+
last_response.body.should == 'nicht gefunden'
|
248
|
+
end
|
249
|
+
end
|
184
250
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require "sinatra/rspec"
|
1
|
+
require "sinatra/rspec/shared"
|
2
2
|
require "sinatra/namespace"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-namespace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Konstantin Haase
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-07-09 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -26,12 +26,12 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 11
|
30
30
|
segments:
|
31
31
|
- 0
|
32
|
-
-
|
32
|
+
- 5
|
33
33
|
- 0
|
34
|
-
version: 0.
|
34
|
+
version: 0.5.0
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
@@ -42,12 +42,12 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
45
|
+
hash: 11
|
46
46
|
segments:
|
47
47
|
- 0
|
48
|
-
-
|
48
|
+
- 5
|
49
49
|
- 0
|
50
|
-
version: 0.
|
50
|
+
version: 0.5.0
|
51
51
|
type: :runtime
|
52
52
|
version_requirements: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
@@ -58,12 +58,12 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
hash:
|
61
|
+
hash: 11
|
62
62
|
segments:
|
63
63
|
- 0
|
64
|
-
-
|
64
|
+
- 5
|
65
65
|
- 0
|
66
|
-
version: 0.
|
66
|
+
version: 0.5.0
|
67
67
|
type: :development
|
68
68
|
version_requirements: *id003
|
69
69
|
- !ruby/object:Gem::Dependency
|