karsthammer-inherited_resources 1.1.2

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