inherited_resources 0.9.2

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.
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