sinatra-trails 0.0.5 → 0.0.6

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.rdoc ADDED
@@ -0,0 +1,312 @@
1
+ sinatra-trails
2
+ --------------
3
+
4
+ Is a very thin Rails inspired route naming DSL for using with Sinatra apps.
5
+ It doesn't monkeypatch or overrides any Sinatra::Base methods
6
+ It provides helpers for generating routes for resources and single resource, namespaces and named routes.
7
+
8
+ Instalation
9
+ ----------
10
+
11
+ $ [sudo] gem install sinatra-trails
12
+
13
+ Usage
14
+ ----
15
+
16
+ Basic
17
+ =====
18
+
19
+ Named routes are generated with map, not passing :to option sets the path to be the same as the name:
20
+
21
+ require 'sinatra/trails'
22
+
23
+ class MyApp < Sinatra::Base
24
+ register Sinatra::Trails
25
+
26
+ map :dashboard # => '/dashboard'
27
+ map :home, :to => '/' # => '/'
28
+ map :post, :to => '/posts/:id' # => '/posts/:id'
29
+ end
30
+
31
+ MyApp.print_routes
32
+ # prints
33
+ # dashboard => /dashboard
34
+ # home => /
35
+ # post => /posts/:id
36
+
37
+ Routes can be define beforehand:
38
+
39
+ map :dashboard
40
+
41
+ # GET '/dashboard'
42
+ get route_for(:dashboard) do
43
+ ...
44
+ end
45
+
46
+ Or when defining the action:
47
+
48
+ # GET '/dashboard'
49
+ get map(:dashboard) do
50
+ ...
51
+ end
52
+
53
+ All defined routes will be available in the views and action blocks:
54
+
55
+ get map(:posts, :to => '/posts/:id') do
56
+ ...
57
+ end
58
+
59
+ get map(:dashboard) do
60
+ path_for(:dashboard) # => '/dashboard'
61
+ url_for(:dashboard) # => 'http://www.example.com/dashboard'
62
+ path_for(:dashboard, :option => 'hi') # => '/dashboard?option=hi'
63
+ # all required params must be meet, an object can be passed to meet :id but it must respond to #to_param
64
+ path_for(:posts, 1) # => '/posts/1'
65
+ end
66
+
67
+
68
+ Namespaces
69
+ ==========
70
+
71
+ Pasing a symbol namespaces both the path and the route name:
72
+
73
+ namespace :admin do
74
+ map(:dashboard)
75
+ end
76
+
77
+ route_for(:admin_dashboard) # => '/admin/dashboard'
78
+
79
+ Passing a string only namespaces the path:
80
+
81
+ namespace 'admin' do
82
+ map(:dashboard)
83
+ end
84
+
85
+ route_for(:dashboard) # => '/admin/dashboard'
86
+
87
+ Passing nil to namespace only sets a context:
88
+
89
+ namespace nil do
90
+ map(:dashboard)
91
+ end
92
+
93
+ route_for(:dashboard) # => '/dashboard'
94
+
95
+
96
+ Resources
97
+ =========
98
+
99
+ Restful routes for plural resources can be generated as follows, inside the resource
100
+ definition block a route can be accessed by its name as a method call or using the path_for method:
101
+
102
+ resources :users do
103
+ # GET /users
104
+ get users do
105
+ ...
106
+ end
107
+
108
+ # POST /users
109
+ post users do
110
+ ...
111
+ end
112
+
113
+ # GET /users/new
114
+ get new_user do
115
+ ...
116
+ end
117
+
118
+ # GET /users/:id
119
+ get user do
120
+ ...
121
+ end
122
+
123
+ # GET /users/:id/edit
124
+ get edit_user do
125
+ ...
126
+ end
127
+
128
+ # PUT /users/:id
129
+ put user do
130
+ ...
131
+ end
132
+
133
+ # DELETE /users/:id
134
+ delete user do
135
+ ...
136
+ end
137
+ end
138
+
139
+ It is important to note that the order in wich the sinatra action blocks are defined is important.
140
+ in this case `get(new_user)` must be defined before `get(user)`
141
+
142
+ As with previous examples routes can be defined beforehand:
143
+
144
+ resources :users
145
+ # GET '/users'
146
+ get path_for(:users) do
147
+ ...
148
+ end
149
+
150
+
151
+ Nested Resources
152
+ ================
153
+
154
+ Resources can be nested in a similar way as with Rails nested resources:
155
+
156
+ resources :users do
157
+ ...
158
+ resources :comments do
159
+ # GET /users/:user_id/comments
160
+ get user_comments do
161
+ ...
162
+ end
163
+
164
+ # GET /users/:user_id/comments/:id
165
+ get user_comment do
166
+ ...
167
+ end
168
+ end
169
+ end
170
+
171
+ print_routes
172
+ # users => /users
173
+ # new_user => /users/new
174
+ # user => /users/:id
175
+ # edit_user => /users/:id/edit
176
+ # user_comments => /users/:user_id/comments
177
+ # new_user_comment => /users/:user_id/comments/new
178
+ # user_comment => /users/:user_id/comments/:id
179
+ # edit_user_comment => /users/:user_id/comments/:id/edit
180
+
181
+
182
+ And for actions that don't need to load the parent resource the route generation can be shallow:
183
+
184
+ resources :users, :shallow => true do
185
+ resources :comments
186
+ end
187
+
188
+ print_routes
189
+ # users => /users
190
+ # new_user => /users/new
191
+ # user => /users/:id
192
+ # edit_user => /users/:id/edit
193
+ # user_comments => /users/:user_id/comments
194
+ # new_user_comment => /users/:user_id/comments/new
195
+ # comment => /comments/:id
196
+ # edit_comment => /comments/:id/edit
197
+
198
+ There's an alternative way of generating routes for nested resources:
199
+
200
+ resources :users => {:posts => :comments}, :shallow => true do
201
+ ...
202
+ end
203
+ print_routes
204
+ # users => /users
205
+ # new_user => /users/new
206
+ # user => /users/:id
207
+ # edit_user => /users/:id/edit
208
+ # user_posts => /users/:user_id/posts
209
+ # new_user_post => /users/:user_id/posts/new
210
+ # post => /posts/:id
211
+ # edit_post => /posts/:id/edit
212
+ # post_comments => /posts/:post_id/comments
213
+ # new_post_comment => /posts/:post_id/comments/new
214
+ # comment => /comments/:id
215
+ # edit_comment => /comments/:id/edit
216
+
217
+ Some keys to the params hash are added when routes are defined using sinatra-trails:
218
+
219
+ params[:resource] # the name of the resource in REST actions
220
+ params[:action] # the name of the action in REST actions
221
+ params[:namespace] # the name of the current namespace
222
+
223
+
224
+ Singleton Resource
225
+ =================
226
+
227
+ Same principles apply for singleton resource:
228
+
229
+ resource :user
230
+ print_routes
231
+ # user => /user
232
+ # new_user => /user/new
233
+ # edit_user => /user/edit
234
+
235
+
236
+ Before and After Filters
237
+ ========================
238
+
239
+ Defining a filter within a context (namespace, resources, resource) without passing any path will execute that filter for
240
+ all actions defined in that context:
241
+
242
+ namespace :admin do
243
+ before do
244
+ @admin = true
245
+ end
246
+
247
+ get map(:dashboard) do
248
+ @admin # => true
249
+ end
250
+ end
251
+
252
+ get map(:home, :to => '/') do
253
+ @admin # => nil
254
+ end
255
+
256
+
257
+ Within a context named routes, strings or regexps can be used as arguments for before and after filters:
258
+
259
+ resources :users do
260
+ before new_user, edit_user do
261
+ end
262
+ end
263
+
264
+ A symbol can be passed to the filter definition and it will be lazily evaluated against the routes within the context:
265
+
266
+ namespace :admin do
267
+ before :dashboard do
268
+ ...
269
+ end
270
+
271
+ get map(:dashboard) do
272
+ ...
273
+ end
274
+ end
275
+
276
+
277
+ Accessing Routes from Outside the App
278
+ =====================================
279
+
280
+ On registering Sinatra::Trails a dynamic module for the Sinatra app is created and it is assigned to the constant `Routes`
281
+ including that module in another class gives that class access to the app's paths, a single class can access paths for
282
+ several Sinatra apps:
283
+
284
+ class MyApp < Sinatra::Base
285
+ register Sinatra::Trails
286
+
287
+ get map(:users) do
288
+ ...
289
+ end
290
+
291
+ get map(:user, :to => '/users/:id') do
292
+ ...
293
+ end
294
+ end
295
+
296
+ class OtherApp < Sinatra::Base
297
+ include MyApp::Routes
298
+
299
+ get 'index' do
300
+ redirect to path_for(:users)
301
+ end
302
+ end
303
+
304
+ class User < Sequel::Model
305
+ include MyApp::Routes
306
+
307
+ def to_param() id end
308
+
309
+ def route
310
+ path_for(:user, self) # => '/users/1'
311
+ end
312
+ end
@@ -1,5 +1,5 @@
1
1
  module Sinatra
2
2
  module Trails
3
- VERSION = "0.0.5"
3
+ VERSION = "0.0.6"
4
4
  end
5
5
  end
@@ -89,10 +89,7 @@ module Sinatra
89
89
  @actual_keys ||= routes.map{ |m| m.keys }.flatten
90
90
  end
91
91
 
92
- def keys
93
- self
94
- end
95
-
92
+ def keys() self end
96
93
  def any?() actual_keys.any? end
97
94
  def zip(arr) actual_keys.zip(arr) end
98
95
  end
@@ -108,8 +105,8 @@ module Sinatra
108
105
  end
109
106
 
110
107
  def map name, opts = {}, &block
111
- path = opts.delete(:to) || name
112
- route = Route.new(path, name, [*ancestors, self], self)
108
+ path = opts.delete(:to) || name
109
+ route = Route.new(path, name.to_sym, [*ancestors, self], self)
113
110
  instance_eval &block if block_given?
114
111
  route
115
112
  end
@@ -131,6 +128,12 @@ module Sinatra
131
128
  @sinatra_app.before ScopeMatcher.new(self, args), opts, &block
132
129
  end
133
130
 
131
+ def after *args, &block
132
+ # TODO: no specs
133
+ opts = Hash === args.last ? args.pop : {}
134
+ @sinatra_app.after ScopeMatcher.new(self, args), opts, &block
135
+ end
136
+
134
137
  def generate_routes! &block
135
138
  instance_eval &block if block_given?
136
139
  @routes
@@ -242,7 +245,6 @@ module Sinatra
242
245
 
243
246
  def map action
244
247
  ancestors = [*self.ancestors, plural_name, action]
245
-
246
248
  ancestors[0, ancestors.size - 2] = ancestors[0..-3].reject{ |ancestor| Resource === ancestor } if opts[:shallow]
247
249
  Route.new([plural_name, action], action.to_s, ancestors, self)
248
250
  end
@@ -13,7 +13,7 @@ describe 'trails' do
13
13
  describe 'basic' do
14
14
  before :all do
15
15
  app.map :home, :to => '/'
16
- app.map :dashboard
16
+ app.map 'dashboard'
17
17
  app.map :edit_user, :to => '/users/:id/edit'
18
18
  end
19
19
 
@@ -166,7 +166,6 @@ describe 'trails' do
166
166
  app.resources :users do
167
167
  map(:confirm)
168
168
  end
169
- puts app.print_routes
170
169
  end
171
170
  it_should_behave_like 'generates routes for users'
172
171
  it { app.route_for(:users_confirm).should == '/users/confirm' }
@@ -314,17 +313,29 @@ describe 'trails' do
314
313
  end
315
314
 
316
315
  describe 'single resource' do
317
- before :all do
318
- app.resource :user => :profile
319
- end
320
- it { app.route_for(:user).should == '/user' }
321
- it { app.route_for(:new_user).should == '/user/new' }
322
- it { app.route_for(:edit_user).should == '/user/edit' }
323
- it { app.route_for(:user_profile).should == '/user/profile' }
324
- it { app.route_for(:new_user_profile).should == '/user/profile/new' }
325
- it { app.route_for(:edit_user_profile).should == '/user/profile/edit' }
316
+ describe 'basic' do
317
+ before :all do
318
+ app.resource :user => :profile
319
+ end
320
+ it { app.route_for(:user).should == '/user' }
321
+ it { app.route_for(:new_user).should == '/user/new' }
322
+ it { app.route_for(:edit_user).should == '/user/edit' }
323
+ it { app.route_for(:user_profile).should == '/user/profile' }
324
+ it { app.route_for(:new_user_profile).should == '/user/profile/new' }
325
+ it { app.route_for(:edit_user_profile).should == '/user/profile/edit' }
326
+ end
327
+
328
+ describe 'as namespace' do
329
+ before :all do
330
+ app.resource :user do
331
+ map(:confirm)
332
+ end
333
+ end
334
+ it { app.route_for(:user_confirm).should == '/user/confirm' }
335
+ end
326
336
  end
327
337
 
338
+
328
339
  describe 'finding route for scope' do
329
340
  before :all do
330
341
  @scope = Sinatra::Trails::Scope.new(app, :admin)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-trails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-05 00:00:00.000000000Z
12
+ date: 2011-11-29 00:00:00.000000000 -06:00
13
+ default_executable:
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: sinatra
16
- requirement: &2156534160 !ruby/object:Gem::Requirement
17
+ requirement: &70095708882740 !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
20
  - - ! '>='
@@ -21,10 +22,10 @@ dependencies:
21
22
  version: '0'
22
23
  type: :runtime
23
24
  prerelease: false
24
- version_requirements: *2156534160
25
+ version_requirements: *70095708882740
25
26
  - !ruby/object:Gem::Dependency
26
27
  name: i18n
27
- requirement: &2156533740 !ruby/object:Gem::Requirement
28
+ requirement: &70095708881640 !ruby/object:Gem::Requirement
28
29
  none: false
29
30
  requirements:
30
31
  - - ! '>='
@@ -32,10 +33,10 @@ dependencies:
32
33
  version: '0'
33
34
  type: :runtime
34
35
  prerelease: false
35
- version_requirements: *2156533740
36
+ version_requirements: *70095708881640
36
37
  - !ruby/object:Gem::Dependency
37
38
  name: activesupport
38
- requirement: &2156533240 !ruby/object:Gem::Requirement
39
+ requirement: &70095708880780 !ruby/object:Gem::Requirement
39
40
  none: false
40
41
  requirements:
41
42
  - - ! '>='
@@ -43,10 +44,10 @@ dependencies:
43
44
  version: '3.0'
44
45
  type: :runtime
45
46
  prerelease: false
46
- version_requirements: *2156533240
47
+ version_requirements: *70095708880780
47
48
  - !ruby/object:Gem::Dependency
48
49
  name: rake
49
- requirement: &2156532820 !ruby/object:Gem::Requirement
50
+ requirement: &70095708880260 !ruby/object:Gem::Requirement
50
51
  none: false
51
52
  requirements:
52
53
  - - ! '>='
@@ -54,10 +55,10 @@ dependencies:
54
55
  version: '0'
55
56
  type: :development
56
57
  prerelease: false
57
- version_requirements: *2156532820
58
+ version_requirements: *70095708880260
58
59
  - !ruby/object:Gem::Dependency
59
60
  name: rspec
60
- requirement: &2156532360 !ruby/object:Gem::Requirement
61
+ requirement: &70095708879500 !ruby/object:Gem::Requirement
61
62
  none: false
62
63
  requirements:
63
64
  - - ! '>='
@@ -65,10 +66,10 @@ dependencies:
65
66
  version: '0'
66
67
  type: :development
67
68
  prerelease: false
68
- version_requirements: *2156532360
69
+ version_requirements: *70095708879500
69
70
  - !ruby/object:Gem::Dependency
70
71
  name: rack-test
71
- requirement: &2156555720 !ruby/object:Gem::Requirement
72
+ requirement: &70095708878680 !ruby/object:Gem::Requirement
72
73
  none: false
73
74
  requirements:
74
75
  - - ! '>='
@@ -76,7 +77,7 @@ dependencies:
76
77
  version: '0'
77
78
  type: :development
78
79
  prerelease: false
79
- version_requirements: *2156555720
80
+ version_requirements: *70095708878680
80
81
  description: A named routes Sinatra DSL inspired by Rails routing
81
82
  email:
82
83
  - macarui@gmail.com
@@ -87,12 +88,14 @@ files:
87
88
  - .gitignore
88
89
  - .rspec
89
90
  - Gemfile
91
+ - README.rdoc
90
92
  - Rakefile
91
93
  - lib/sinatra/trails.rb
92
94
  - lib/sinatra/trails/version.rb
93
95
  - spec/route_generation_spec.rb
94
96
  - spec/spec_helper.rb
95
97
  - trails.gemspec
98
+ has_rdoc: true
96
99
  homepage: http://github.com/maca/trails
97
100
  licenses: []
98
101
  post_install_message:
@@ -113,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
116
  version: '0'
114
117
  requirements: []
115
118
  rubyforge_project: sinatra-trails
116
- rubygems_version: 1.8.8
119
+ rubygems_version: 1.6.2
117
120
  signing_key:
118
121
  specification_version: 3
119
122
  summary: A named routes Sinatra DSL inspired by Rails routing