inherited_resources 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/CHANGELOG +103 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +524 -0
  4. data/Rakefile +40 -0
  5. data/lib/inherited_resources.rb +23 -0
  6. data/lib/inherited_resources/actions.rb +79 -0
  7. data/lib/inherited_resources/base.rb +42 -0
  8. data/lib/inherited_resources/base_helpers.rb +363 -0
  9. data/lib/inherited_resources/belongs_to_helpers.rb +89 -0
  10. data/lib/inherited_resources/class_methods.rb +338 -0
  11. data/lib/inherited_resources/dsl.rb +26 -0
  12. data/lib/inherited_resources/dumb_responder.rb +20 -0
  13. data/lib/inherited_resources/has_scope_helpers.rb +83 -0
  14. data/lib/inherited_resources/legacy/respond_to.rb +156 -0
  15. data/lib/inherited_resources/legacy/responder.rb +200 -0
  16. data/lib/inherited_resources/polymorphic_helpers.rb +155 -0
  17. data/lib/inherited_resources/singleton_helpers.rb +95 -0
  18. data/lib/inherited_resources/url_helpers.rb +179 -0
  19. data/test/aliases_test.rb +139 -0
  20. data/test/association_chain_test.rb +125 -0
  21. data/test/base_test.rb +225 -0
  22. data/test/belongs_to_test.rb +87 -0
  23. data/test/class_methods_test.rb +138 -0
  24. data/test/customized_base_test.rb +162 -0
  25. data/test/customized_belongs_to_test.rb +76 -0
  26. data/test/defaults_test.rb +70 -0
  27. data/test/flash_test.rb +88 -0
  28. data/test/has_scope_test.rb +139 -0
  29. data/test/nested_belongs_to_test.rb +108 -0
  30. data/test/optional_belongs_to_test.rb +164 -0
  31. data/test/polymorphic_test.rb +186 -0
  32. data/test/redirect_to_test.rb +51 -0
  33. data/test/respond_to_test.rb +155 -0
  34. data/test/singleton_test.rb +83 -0
  35. data/test/test_helper.rb +38 -0
  36. data/test/url_helpers_test.rb +537 -0
  37. metadata +89 -0
data/CHANGELOG ADDED
@@ -0,0 +1,103 @@
1
+ # Version 0.9
2
+
3
+ * Added :if and :unless to has_scope (thanks to Jack Danger);
4
+ * Added create_resource, update_resource and delete_resource hooks (thanks to Carlos Antonio da Silva);
5
+ * Backported ActionController::Responder from Rails 3;
6
+ * Added parent_url helper;
7
+ * Added association_chain helper (as suggested by http://github.com/emmanuel);
8
+
9
+ # Version 0.8
10
+
11
+ * Fixed a small bug on optional belongs to with namespaced controllers.
12
+ * Allow a parameter to be given to collection_url in polymorphic cases to replace
13
+ the parent.
14
+ * Allow InheritedResources to be called without inheritance.
15
+ * Ensure that controllers that inherit from a controller with InheritedResources
16
+ works properly.
17
+
18
+ # Version 0.7
19
+
20
+ * Allow procs as default value in has scope to be able to use values from session, for example.
21
+ * Allow blocks with arity 0 or -1 to be given as the redirect url:
22
+
23
+ def destroy
24
+ destroy!{ project_url(@project) }
25
+ end
26
+
27
+ * Allow interpolation_options to be set in the application controller.
28
+ * Added has_scope to controller (an interface for named_scopes).
29
+ * Added polymorphic_belongs_to, optional_belongs_to and singleton_belongs_to
30
+ as quick methods.
31
+ * Only load belongs_to, singleton and polymorphic helpers if they are actually
32
+ required. base_helpers, class_methods, dumb_responder and url_helpers are loaded
33
+ when you inherited from base for the first time.
34
+
35
+ # Version 0.6
36
+
37
+ * Ensure that the default template is not rendered if the default_template_format
38
+ is not accepted. This is somehow related with the security breach report:
39
+
40
+ http://www.rorsecurity.info/journal/2009/4/24/hidden-actions-render-templates.html
41
+
42
+ IR forbids based on mime types. For example: respond_to :html, :except => :index
43
+ ensures that the index.html.erb view is not rendered, making your IR controllers
44
+ safer.
45
+
46
+ * Fixed a bug that happens only when format.xml is given to blocks and then it
47
+ acts as default, instead of format.html.
48
+ * Fixed a strange bug where when you have create.html.erb or update.html.erb,
49
+ it makes IE6 and IE7 return unprocessable entity (because they send Mime::ALL).
50
+ * Stop rescueing any error when constantizing the resource class and allow
51
+ route_prefix to be nil.
52
+ * Cleaned up tests and responder structure. Whenever you pass a block to aliases
53
+ and this block responds to the request, the other blocks are not parsed improving performance.
54
+ * [BACKWARDS INCOMPATIBLE] By default, Inherited Resources respond only :html requests.
55
+ * Added a quick way to overwrite the redirect to url in :create, :update and :destroy.
56
+
57
+ # Version 0.5
58
+
59
+ * Decoupled routes name from :instance_name and :collection_name. This way we
60
+ have more flexibility. Use route_instance_name and route_collection_name to
61
+ to change routes.
62
+ * Avoid calling human_name on nil when a resource class is not defined.
63
+ * Only call I18n if it's defined.
64
+
65
+ # Version 0.4
66
+
67
+ * Dealing with namespaced controllers out of the box.
68
+ * Added support to namespaced routes through :route_prefix.
69
+ * Added fix when resource_url is not defined.
70
+ * Added better handling for namespaced controllers.
71
+ * Added flash messages scoped by namespaced controllers.
72
+ * Deprecated {{resource}} in I18n, use {{resource_name}} instead.
73
+ * rspec bug fix is not automatically required anymore. User has to do it
74
+ explicitly.
75
+ * Added a file which fix a rspec bug when render is called inside a method
76
+ which receives a block.
77
+ * parent? does not take begin_of_association_chain into account anymore
78
+ * Added options to url helpers.
79
+ * Added :optional to belongs_to associations. It allows you to deal with
80
+ categories/1/products/2 and /products/2 with just one controller.
81
+ * Cleaned up tests.
82
+
83
+ # Version 0.3
84
+
85
+ * Minor bump after three bug fixes.
86
+ * Bug fix when showing warning of constant redefinition.
87
+ * Bug fix with ApplicationController not being unloaded properly on development.
88
+ * Bug fix when having root singleton resources. Calling collection_url would
89
+ raise "NoMethodError _url", not it will call root_url.
90
+ * More comments on UrlHelpers.
91
+
92
+ # Version 0.2
93
+
94
+ * Bug fix when ApplicationController is already loaded when we load respond_to.
95
+ * Added support success/failure blocks.
96
+ * Eager loading of files to work properly in multithreaded environments.
97
+
98
+ # Version 0.1
99
+
100
+ * Added more helper_methods.
101
+ * Added Rails 2.3.0 and changed tests to work with ActionController::TestCase.
102
+ * First release. Support to I18n, singleton controllers, polymorphic
103
+ controllers, belongs_to, nested_belongs_to and url helpers.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 José Valim
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
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,524 @@
1
+ Inherited Resources
2
+ License: MIT
3
+ Version: 0.9.1
4
+
5
+ == Description
6
+
7
+ Inherited Resources speeds up development by making your controllers inherit
8
+ all restful actions so you just have to focus on what is important. It makes
9
+ your controllers more powerful and cleaner at the same time.
10
+
11
+ Plus, making your controllers follow a pattern, it helps you to write better
12
+ code by following fat models and skinny controllers convention. There is
13
+ a screencast made by Fabio Akita about its features:
14
+
15
+ http://akitaonrails.com/2009/09/01/screencast-real-thin-restful-controllers-with-inherited-resources
16
+
17
+ Inherited Resources is tested and compatible with Rails 2.2.x and Rails 2.3.x.
18
+
19
+ keywords: resources, controller, singleton, belongs_to, polymorphic, named_scope and I18n
20
+
21
+ == Installation
22
+
23
+ Install Inherited Resources is very easy. It is stored in GitHub, so just run
24
+ the following:
25
+
26
+ gem sources -a http://gems.github.com
27
+ sudo gem install josevalim-inherited_resources
28
+
29
+ If you want it as plugin, just do:
30
+
31
+ script/plugin install git://github.com/josevalim/inherited_resources.git
32
+
33
+ == Rspec known bug
34
+
35
+ When used with integrate_views equals to false, rspec overwrites default_render,
36
+ render and some other controller methods which makes Inherited Resources not work
37
+ properly. In such cases, you have to set integrate_views to true.
38
+
39
+ == Basic Usage
40
+
41
+ To use Inherited Resources you just have to inherit (duh) it:
42
+
43
+ class ProjectsController < InheritedResources::Base
44
+ end
45
+
46
+ And all actions are defined and working, check it! Your projects collection
47
+ (in the index action) is still available in the instance variable @projects
48
+ and your project resource (all other actions) is available as @ project.
49
+
50
+ The next step is to define which mime types this controller provides:
51
+
52
+ class ProjectsController < InheritedResources::Base
53
+ respond_to :html, :xml, :json
54
+ end
55
+
56
+ You can also specify them based per action:
57
+
58
+ class ProjectsController < InheritedResources::Base
59
+ respond_to :html, :xml, :json
60
+ respond_to :js, :only => :create
61
+ respond_to :iphone, :except => [ :edit, :update ]
62
+ end
63
+
64
+ For each request, it first checkes if the "controller/action.format" file is
65
+ available (for example "projects/create.xml") and if it's not, it checks if
66
+ the resource respond to :to_format (in this case, :to_xml). Otherwise returns 404.
67
+
68
+ Another option is to specify which actions the controller will inherit from
69
+ the InheritedResources::Base:
70
+
71
+ class ProjectsController < InheritedResources::Base
72
+ actions :index, :show, :new, :create
73
+ end
74
+
75
+ Or:
76
+
77
+ class ProjectsController < InheritedResources::Base
78
+ actions :all, :except => [ :edit, :update, :destroy ]
79
+ end
80
+
81
+ In your views, you will get the following helpers:
82
+
83
+ resource #=> @project
84
+ collection #=> @projects
85
+ resource_class #=> Project
86
+
87
+ As you might expect, collection (@projects instance variable) is only available
88
+ on index actions.
89
+
90
+ If for some reason you cannot inherit from InheritedResources::Base, you can
91
+ call inherit_resources in your controller class scope:
92
+
93
+ class AccountsController < ApplicationController
94
+ inherit_resources
95
+ end
96
+
97
+ == Overwriting defaults
98
+
99
+ Whenever you inherit from InheritedResources, several defaults are assumed.
100
+ For example you can have an AccountsController to account management while the
101
+ resource is an User:
102
+
103
+ class AccountsController < InheritedResources::Base
104
+ defaults :resource_class => User, :collection_name => 'users', :instance_name => 'user'
105
+ end
106
+
107
+ In the case above, in your views you will have @users and @user variables, but
108
+ the routes used will still be accounts_url and account_url. If you plan also to
109
+ change the routes, you can use :route_collection_name and :route_instance_name.
110
+
111
+ Namespaced controllers work out of the box, but if you need to specify a
112
+ different route prefix, you can do the following:
113
+
114
+ class Administrators::PeopleController < InheritedResources::Base
115
+ defaults :route_prefix => 'admin'
116
+ end
117
+
118
+ Then your named routes will be: 'admin_people_url', 'admin_person_url' instead
119
+ of 'administrators_people_url' and 'administrators_person_url'.
120
+
121
+ If you want to customize how resources are retrieved you can overwrite
122
+ collection and resource methods. The first is called on index action and the
123
+ second on all other actions. Let's suppose you want to add pagination to your
124
+ projects collection:
125
+
126
+ class ProjectsController < InheritedResources::Base
127
+ protected
128
+ def collection
129
+ @projects ||= end_of_association_chain.paginate(:page => params[:page])
130
+ end
131
+ end
132
+
133
+ The end_of_association_chain returns your resource after nesting all associations
134
+ and scopes (more about this below).
135
+
136
+ InheritedResources also introduces another method called begin_of_association_chain.
137
+ It's mostly used when you want to create resources based on the @current_user and
138
+ you have urls like "account/projects". In such cases, you have to do
139
+ @current_user.projects.find or @current_user.projects.build in your actions.
140
+
141
+ You can deal with it just doing:
142
+
143
+ class ProjectsController < InheritedResources::Base
144
+ protected
145
+ def begin_of_association_chain
146
+ @current_user
147
+ end
148
+ end
149
+
150
+ == Overwriting actions
151
+
152
+ Let's suppose that after destroying a project you want to redirect to your
153
+ root url instead of redirecting to projects url. You just have to do:
154
+
155
+ class ProjectsController < InheritedResources::Base
156
+ def destroy
157
+ super do |format|
158
+ format.html { redirect_to root_url }
159
+ end
160
+ end
161
+ end
162
+
163
+ You are opening your action and giving the parent action a new behavior. On
164
+ the other hand, I have to agree that calling super is not very readable. That's
165
+ why all methods have aliases. So this is equivalent:
166
+
167
+ class ProjectsController < InheritedResources::Base
168
+ def destroy
169
+ destroy! do |format|
170
+ format.html { redirect_to root_url }
171
+ end
172
+ end
173
+ end
174
+
175
+ Even more, since most of the times when you change a create, update or destroy
176
+ action is because you want to to change to where it redirects, a shortcut is
177
+ provided. So you can do:
178
+
179
+ class ProjectsController < InheritedResources::Base
180
+ def destroy
181
+ destroy!{ root_url }
182
+ end
183
+ end
184
+
185
+ Now let's suppose that before create a project you have to do something special
186
+ but you don't want to create a before filter for it:
187
+
188
+ class ProjectsController < InheritedResources::Base
189
+ def create
190
+ @project = Project.new(params[:project])
191
+ @project.something_special!
192
+ create!
193
+ end
194
+ end
195
+
196
+ Yes, that simple! The nice part is since you already set the instance variable
197
+ @project, it will not build a project again.
198
+
199
+ Before we finish this topic, we should talk about one more thing: "success/failure
200
+ blocks". Let's suppose that when we update our project, in case of failure, we
201
+ want to redirect to the project url instead of re-rendering the edit template.
202
+
203
+ Our first attempt to do this would be:
204
+
205
+ class ProjectsController < InheritedResources::Base
206
+ def update
207
+ update! do |format|
208
+ unless @project.errors.empty? # failure
209
+ format.html { redirect_to project_url(@project) }
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ Looks to verbose, right? We can actually do:
216
+
217
+ class ProjectsController < InheritedResources::Base
218
+ def update
219
+ update! do |success, failure|
220
+ failure.html { redirect_to project_url(@project) }
221
+ end
222
+ end
223
+ end
224
+
225
+ Much better! So explaining everything: when you give a block which expects one
226
+ argument it will be executed in both scenarios: success and failure. But If you
227
+ give a block that expects two arguments, the first will be executed only in
228
+ success scenarios and the second in failure scenarios. You keep everything
229
+ clean and organized inside the same action.
230
+
231
+ == Some DSL
232
+
233
+ For those DSL lovers, InheritedResources won't leave you alone. You can overwrite
234
+ your success/failure blocks straight from your class binding. For it, you just
235
+ need to add a DSL block to your application controller:
236
+
237
+ class ApplicationController < ActionController::Base
238
+ include InheritedResources::DSL
239
+ end
240
+
241
+ And then you can rewrite the last example as:
242
+
243
+ class ProjectsController < InheritedResources::Base
244
+ update! do |success, failure|
245
+ failure.html { redirect_to project_url(@project) }
246
+ end
247
+ end
248
+
249
+ == Flash messages and I18n
250
+
251
+ Flash messages are powered by I18n api. It checks for messages in the following
252
+ order:
253
+
254
+ flash.controller_name.action_name.status
255
+ flash.actions.action_name.status
256
+
257
+ If none is available, a default message in english set. In a create action
258
+ on projects controller, it will search for:
259
+
260
+ flash.projects.create.status
261
+ flash.actions.create.status
262
+
263
+ The status can be :notice (when the object can be created, updated
264
+ or destroyed with success) or :error (when the objecy cannot be created
265
+ or updated).
266
+
267
+ Those messages are interpolated by using the resource class human name, which
268
+ is also localized and it means you can set:
269
+
270
+ flash:
271
+ actions:
272
+ create:
273
+ notice: "Hooray! {{resource_name}} was successfully created!"
274
+
275
+ It will replace {{resource_name}} by the human name of the resource class,
276
+ which is "Project" in this case.
277
+
278
+ But sometimes, flash messages are not that simple. Sometimes you want to say
279
+ the title of the project while updating a project. Well, that's easy also:
280
+
281
+ flash:
282
+ projects:
283
+ update:
284
+ notice: "Hooray! The project "{{project_title}}" was updated!"
285
+
286
+ Since :project_title is not available for interpolation by default, you have
287
+ to overwrite interpolation_options.
288
+
289
+ def interpolation_options
290
+ { :project_title => @project.title }
291
+ end
292
+
293
+ Then you will finally have:
294
+
295
+ "Hooray! The project "Plataforma" was updated!"
296
+
297
+ By default, resource name is capitalized. If you want to make it lower case, you
298
+ can add to your application controller:
299
+
300
+ def interpolation_options
301
+ { :resource_name => resource_class.human_name.downcase }
302
+ end
303
+
304
+ Finally, if your controller is namespaced, for example Admin::ProjectsController,
305
+ the messages will be checked in the following order:
306
+
307
+ flash.admin.projects.create.notice
308
+ flash.admin.actions.create.notice
309
+ flash.projects.create.notice
310
+ flash.actions.create.notice
311
+
312
+ == Has Scope
313
+
314
+ InheritedResources tries to integrate nicely with your model. In order to do so,
315
+ it also is named_scope fluent. Let's suppose our Project model with the scopes:
316
+
317
+ class Project < ActiveRecord::Base
318
+ named_scope :featured, :conditions => { :featured => true }
319
+ named_scope :by_methodology, proc {|methodology| { :conditions => { :methodology => methodology } } }
320
+ named_scope :limit, proc{|limit| :limit => limit.to_i }
321
+ end
322
+
323
+ Your controller:
324
+
325
+ class ProjectsController < InheritedResources::Base
326
+ has_scope :featured, :boolean => true, :only => :index
327
+ has_scope :by_methodology
328
+ has_scope :limit, :default => 10
329
+ end
330
+
331
+ Then for each request:
332
+
333
+ /projects
334
+ #=> acts like a normal request, but returning 10 projects
335
+
336
+ /projects?featured=true
337
+ #=> calls the featured named scope and bring 10 featured projects
338
+
339
+ /projects?featured=true&by_methodology=agile&limit=20
340
+ #=> brings 20 featured projects with methodology agile
341
+
342
+ You can retrieve the current scopes in use with :current_scopes method.
343
+ In the last case, it would return:
344
+
345
+ { :featured => "true", :by_methodology => "agile", :limit => "20" }
346
+
347
+ Finally, let's suppose you store on the session how many projects the user sees
348
+ per page. In such cases, you can give a proc as default value:
349
+
350
+ has_scope :limit, :default => proc{|c| c.session[:limit] || 10 }
351
+
352
+ == Belongs to
353
+
354
+ Finally, our Projects are going to get some Tasks. Then you create a
355
+ TasksController and do:
356
+
357
+ class TasksController < InheritedResources::Base
358
+ belongs_to :project
359
+ end
360
+
361
+ belongs_to accepts several options to be able to configure the association.
362
+ For example, if you want urls like /projects/:project_title/tasks, you can
363
+ customize how InheritedResources find your projects:
364
+
365
+ class TasksController < InheritedResources::Base
366
+ belongs_to :project, :finder => :find_by_title!, :param => :project_title
367
+ end
368
+
369
+ It also accepts :route_name, :parent_class and :instance_name as options.
370
+ Check the lib/inherited_resources/class_methods.rb for more.
371
+
372
+ == Nested belongs to
373
+
374
+ Now, our Tasks get some Comments and you need to nest even deeper. Good
375
+ practices says that you should never nest more than two resources, but sometimes
376
+ you have to for security reasons. So this is an example of how you can do it:
377
+
378
+ class CommentsController < InheritedResources::Base
379
+ nested_belongs_to :project, :task
380
+ end
381
+
382
+ If you need to configure any of these belongs to, you can nest them using blocks:
383
+
384
+ class CommentsController < InheritedResources::Base
385
+ belongs_to :project, :finder => :find_by_title!, :param => :project_title do
386
+ belongs_to :task
387
+ end
388
+ end
389
+
390
+ Warning: calling several belongs_to is the same as nesting them:
391
+
392
+ class CommentsConroller < InheritedResources::Base
393
+ belongs_to :project
394
+ belongs_to :task
395
+ end
396
+
397
+ In other words, the code above is the same as calling nested_belongs_to.
398
+
399
+ == Polymorphic belongs to
400
+
401
+ We can go even further. Let's suppose our Projects can now have Files, Messages
402
+ and Tasks, and they are all commentable. In this case, the best solution is to
403
+ use polymorphism:
404
+
405
+ class CommentsController < InheritedResources::Base
406
+ belongs_to :task, :file, :message, :polymorphic => true
407
+ # polymorphic_belongs_to :task, :file, :message
408
+ end
409
+
410
+ You can even use it with nested resources:
411
+
412
+ class CommentsController < InheritedResources::Base
413
+ belongs_to :project do
414
+ belongs_to :task, :file, :message, :polymorphic => true
415
+ end
416
+ end
417
+
418
+ The url in such cases can be:
419
+
420
+ /project/1/task/13/comments
421
+ /project/1/file/11/comments
422
+ /project/1/message/9/comments
423
+
424
+ When using polymorphic associations, you get some free helpers:
425
+
426
+ parent? #=> true
427
+ parent_type #=> :task
428
+ parent_class #=> Task
429
+ parent #=> @task
430
+
431
+ Right now, Inherited Resources is limited and does not allow you
432
+ to have two polymorphic associations nested.
433
+
434
+ == Optional belongs to
435
+
436
+ Later you decide to create a view to show all comments, independent if they belong
437
+ to a task, file or message. You can reuse your polymorphic controller just doing:
438
+
439
+ class ProjectsController < InheritedResources::Base
440
+ belongs_to :task, :file, :message, :optional => true
441
+ # optional_belongs_to :task, :file, :message
442
+ end
443
+
444
+ This will handle all those urls properly:
445
+
446
+ /comment/1
447
+ /tasks/2/comment/5
448
+ /files/10/comment/3
449
+ /messages/13/comment/11
450
+
451
+ This is treated as a special type of polymorphic associations, thus all helpers
452
+ are available. As you expect, when no parent is found, the helpers return:
453
+
454
+ parent? #=> false
455
+ parent_type #=> nil
456
+ parent_class #=> nil
457
+ parent #=> nil
458
+
459
+ == Singletons
460
+
461
+ Now we are going to add manager to projects. We say that Manager is a singleton
462
+ resource because a Project has just one manager. You should declare it as
463
+ has_one (or resource) in your routes.
464
+
465
+ To declare an association as singleton, you just have to give the :singleton
466
+ option.
467
+
468
+ class ManagersController < InheritedResources::Base
469
+ belongs_to :project, :singleton => true
470
+ # singleton_belongs_to :project
471
+ end
472
+
473
+ It will deal with everything again and hide the action :index from you.
474
+
475
+ == URL Helpers
476
+
477
+ When you use InheritedResources it creates some URL helpers.
478
+ And they handle everything for you. :)
479
+
480
+ # /posts/1/comments
481
+ resource_url # => /posts/1/comments/#{@comment.to_param}
482
+ resource_url(comment) # => /posts/1/comments/#{comment.to_param}
483
+ new_resource_url # => /posts/1/comments/new
484
+ edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit
485
+ edit_resource_url(comment) #=> /posts/1/comments/#{comment.to_param}/edit
486
+ collection_url # => /posts/1/comments
487
+ parent_url # => /posts/1
488
+
489
+ # /projects/1/tasks
490
+ resource_url # => /projects/1/tasks/#{@task.to_param}
491
+ resource_url(task) # => /projects/1/tasks/#{task.to_param}
492
+ new_resource_url # => /projects/1/tasks/new
493
+ edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit
494
+ edit_resource_url(task) # => /projects/1/tasks/#{task.to_param}/edit
495
+ collection_url # => /projects/1/tasks
496
+ parent_url # => /projects/1
497
+
498
+ # /users
499
+ resource_url # => /users/#{@user.to_param}
500
+ resource_url(user) # => /users/#{user.to_param}
501
+ new_resource_url # => /users/new
502
+ edit_resource_url # => /users/#{@user.to_param}/edit
503
+ edit_resource_url(user) # => /users/#{user.to_param}/edit
504
+ collection_url # => /users
505
+ parent_url # => /
506
+
507
+ Those urls helpers also accepts a hash as options, just as in named routes.
508
+
509
+ # /projects/1/tasks
510
+ collection_url(:page => 1, :limit => 10) #=> /projects/1/tasks?page=1&limit=10
511
+
512
+ In polymorphic cases, you can also give the parent as parameter to collection_url.
513
+
514
+ Another nice thing is that those urls are not guessed during runtime. They are
515
+ all created when your application is loaded (except for polymorphic
516
+ associations, that relies on Rails polymorphic_url).
517
+
518
+ == Bugs and Feedback
519
+
520
+ If you discover any bugs or want to drop a line, join us in the mailing list:
521
+
522
+ http://groups.google.com/group/inherited_resources
523
+
524
+ Copyright (c) 2009 José Valim http://blog.plataformatec.com.br