sinatra-namespace 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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 --prerelease
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 }
@@ -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[after before call configure disable enable error new not_found register reset! run! set use]
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 wrap(unbound_method, app, *args)
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.set :merge_namespaces => false, :auto_namespace => true
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 allowes adding routes with no path" do
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
@@ -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: 13
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 4
9
- - 1
10
- version: 0.4.1
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-06-04 00:00:00 +02:00
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: 15
29
+ hash: 11
30
30
  segments:
31
31
  - 0
32
- - 4
32
+ - 5
33
33
  - 0
34
- version: 0.4.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: 15
45
+ hash: 11
46
46
  segments:
47
47
  - 0
48
- - 4
48
+ - 5
49
49
  - 0
50
- version: 0.4.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: 15
61
+ hash: 11
62
62
  segments:
63
63
  - 0
64
- - 4
64
+ - 5
65
65
  - 0
66
- version: 0.4.0
66
+ version: 0.5.0
67
67
  type: :development
68
68
  version_requirements: *id003
69
69
  - !ruby/object:Gem::Dependency