karsthammer-inherited_resources 1.1.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 (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.