inherited_resources 1.4.0 → 1.4.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df31765cf3b996812936adaeb26f33e4e387b55a
4
+ data.tar.gz: b4da9990905f738c3d77c277e3581b2e8d0d142e
5
+ SHA512:
6
+ metadata.gz: 6a67fcd38ac5d44035110616ef92a76b5c96eff5c0ed70c218ccba2198d95490c2f4ec89635424edbbd3b53057e0bffc6e0b3a47a4997fd9d3ac079182bcaed0
7
+ data.tar.gz: 571dff6d8493a3a5596d9eb5020a8da9e3e303d903ac4a5de2763e876e4816e7c97144ec241ace3b3c90ca48f27863b17d5b2b479836cb77292e2051dbec6139
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ # Version 1.4.1
2
+
3
+ * Supports Rails 4
4
+ * Improved compatability with strong params.
5
+
1
6
  # Version 1.4.0
2
7
 
3
8
  * Supports Ruby 2.0.0
data/Gemfile CHANGED
@@ -2,6 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 3.2'
5
+ gem 'rails', '>= 3.2', '< 5'
6
6
  gem 'mocha'
7
7
  gem 'turn'
@@ -1,94 +1,90 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- inherited_resources (1.3.1)
5
- has_scope (~> 0.5.0)
6
- responders (~> 0.9)
4
+ inherited_resources (1.4.0)
5
+ has_scope (~> 0.6.0.rc)
6
+ responders (~> 1.0.0.rc)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionmailer (3.2.13)
12
- actionpack (= 3.2.13)
11
+ actionmailer (4.0.0)
12
+ actionpack (= 4.0.0)
13
13
  mail (~> 2.5.3)
14
- actionpack (3.2.13)
15
- activemodel (= 3.2.13)
16
- activesupport (= 3.2.13)
17
- builder (~> 3.0.0)
14
+ actionpack (4.0.0)
15
+ activesupport (= 4.0.0)
16
+ builder (~> 3.1.0)
18
17
  erubis (~> 2.7.0)
19
- journey (~> 1.0.4)
20
- rack (~> 1.4.5)
21
- rack-cache (~> 1.2)
22
- rack-test (~> 0.6.1)
23
- sprockets (~> 2.2.1)
24
- activemodel (3.2.13)
25
- activesupport (= 3.2.13)
26
- builder (~> 3.0.0)
27
- activerecord (3.2.13)
28
- activemodel (= 3.2.13)
29
- activesupport (= 3.2.13)
30
- arel (~> 3.0.2)
31
- tzinfo (~> 0.3.29)
32
- activeresource (3.2.13)
33
- activemodel (= 3.2.13)
34
- activesupport (= 3.2.13)
35
- activesupport (3.2.13)
36
- i18n (= 0.6.1)
37
- multi_json (~> 1.0)
18
+ rack (~> 1.5.2)
19
+ rack-test (~> 0.6.2)
20
+ activemodel (4.0.0)
21
+ activesupport (= 4.0.0)
22
+ builder (~> 3.1.0)
23
+ activerecord (4.0.0)
24
+ activemodel (= 4.0.0)
25
+ activerecord-deprecated_finders (~> 1.0.2)
26
+ activesupport (= 4.0.0)
27
+ arel (~> 4.0.0)
28
+ activerecord-deprecated_finders (1.0.3)
29
+ activesupport (4.0.0)
30
+ i18n (~> 0.6, >= 0.6.4)
31
+ minitest (~> 4.2)
32
+ multi_json (~> 1.3)
33
+ thread_safe (~> 0.1)
34
+ tzinfo (~> 0.3.37)
38
35
  ansi (1.4.3)
39
- arel (3.0.2)
40
- builder (3.0.4)
36
+ arel (4.0.0)
37
+ atomic (1.1.10)
38
+ builder (3.1.4)
41
39
  erubis (2.7.0)
42
- has_scope (0.5.1)
43
- hike (1.2.1)
44
- i18n (0.6.1)
45
- journey (1.0.4)
46
- json (1.7.7)
47
- mail (2.5.3)
48
- i18n (>= 0.4.0)
40
+ has_scope (0.6.0.rc)
41
+ actionpack (>= 3.2, < 5)
42
+ activesupport (>= 3.2, < 5)
43
+ hike (1.2.3)
44
+ i18n (0.6.4)
45
+ mail (2.5.4)
49
46
  mime-types (~> 1.16)
50
47
  treetop (~> 1.4.8)
51
48
  metaclass (0.0.1)
52
- mime-types (1.21)
53
- mocha (0.13.3)
49
+ mime-types (1.23)
50
+ minitest (4.7.5)
51
+ mocha (0.14.0)
54
52
  metaclass (~> 0.0.1)
55
- multi_json (1.7.2)
53
+ multi_json (1.7.7)
56
54
  polyglot (0.3.3)
57
- rack (1.4.5)
58
- rack-cache (1.2)
59
- rack (>= 0.4)
60
- rack-ssl (1.3.3)
61
- rack
55
+ rack (1.5.2)
62
56
  rack-test (0.6.2)
63
57
  rack (>= 1.0)
64
- rails (3.2.13)
65
- actionmailer (= 3.2.13)
66
- actionpack (= 3.2.13)
67
- activerecord (= 3.2.13)
68
- activeresource (= 3.2.13)
69
- activesupport (= 3.2.13)
70
- bundler (~> 1.0)
71
- railties (= 3.2.13)
72
- railties (3.2.13)
73
- actionpack (= 3.2.13)
74
- activesupport (= 3.2.13)
75
- rack-ssl (~> 1.3.2)
58
+ rails (4.0.0)
59
+ actionmailer (= 4.0.0)
60
+ actionpack (= 4.0.0)
61
+ activerecord (= 4.0.0)
62
+ activesupport (= 4.0.0)
63
+ bundler (>= 1.3.0, < 2.0)
64
+ railties (= 4.0.0)
65
+ sprockets-rails (~> 2.0.0)
66
+ railties (4.0.0)
67
+ actionpack (= 4.0.0)
68
+ activesupport (= 4.0.0)
76
69
  rake (>= 0.8.7)
77
- rdoc (~> 3.4)
78
- thor (>= 0.14.6, < 2.0)
79
- rake (10.0.4)
80
- rdoc (3.12.2)
81
- json (~> 1.4)
82
- responders (0.9.3)
83
- railties (~> 3.1)
84
- sprockets (2.2.2)
70
+ thor (>= 0.18.1, < 2.0)
71
+ rake (10.1.0)
72
+ responders (1.0.0.rc)
73
+ railties (>= 3.2, < 5)
74
+ sprockets (2.10.0)
85
75
  hike (~> 1.2)
86
76
  multi_json (~> 1.0)
87
77
  rack (~> 1.0)
88
78
  tilt (~> 1.1, != 1.3.0)
89
- thor (0.17.0)
90
- tilt (1.3.6)
91
- treetop (1.4.12)
79
+ sprockets-rails (2.0.0)
80
+ actionpack (>= 3.0)
81
+ activesupport (>= 3.0)
82
+ sprockets (~> 2.8)
83
+ thor (0.18.1)
84
+ thread_safe (0.1.2)
85
+ atomic
86
+ tilt (1.4.1)
87
+ treetop (1.4.14)
92
88
  polyglot
93
89
  polyglot (>= 0.3.1)
94
90
  turn (0.9.6)
@@ -101,5 +97,5 @@ PLATFORMS
101
97
  DEPENDENCIES
102
98
  inherited_resources!
103
99
  mocha
104
- rails (~> 3.2)
100
+ rails (>= 3.2, < 5)
105
101
  turn
@@ -0,0 +1,709 @@
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
+ In addition to making your controllers follow a pattern, it helps you to write better
8
+ code by following fat models and skinny controllers convention. There are
9
+ two screencasts available besides this README:
10
+
11
+ * http://railscasts.com/episodes/230-inherited-resources
12
+ * http://akitaonrails.com/2009/09/01/screencast-real-thin-restful-controllers-with-inherited-resources
13
+
14
+ ## Installation
15
+
16
+ ### Rails 3
17
+
18
+ You can let bundler install Inherited Resources by adding this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'inherited_resources'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ ```sh
27
+ $ bundle install
28
+ ```
29
+
30
+ Or install it yourself with:
31
+
32
+ ```sh
33
+ $ gem install inherited_resources
34
+ ```
35
+
36
+ ### Rails 2.3.x
37
+
38
+ If you want to use the Rails 2.3.x version, you should install:
39
+
40
+ ```sh
41
+ $ gem install inherited_resources --version=1.0.6
42
+ ```
43
+
44
+ Or checkout from the v1.0 branch:
45
+
46
+ ```
47
+ http://github.com/josevalim/inherited_resources/tree/v1.0
48
+ ```
49
+
50
+ ## HasScope
51
+
52
+ Since Inherited Resources 1.0, has_scope is not part of its core anymore but
53
+ a gem dependency. Be sure to check the documentation to see how you can use it:
54
+
55
+ ```
56
+ http://github.com/plataformatec/has_scope
57
+ ```
58
+
59
+ And it can be installed as:
60
+
61
+ ```sh
62
+ $ gem install has_scope
63
+ ```
64
+
65
+ ## Responders
66
+
67
+ Since Inherited Resources 1.0, responders are not part of its core anymore,
68
+ but is set as Inherited Resources dependency and it's used by default by
69
+ InheritedResources controllers. Be sure to check the documentation to see
70
+ how it will change your application:
71
+
72
+ ```
73
+ http://github.com/plataformatec/responders
74
+ ```
75
+
76
+ And it can be installed with:
77
+
78
+ ```sh
79
+ $ gem install responders
80
+ ```
81
+
82
+ Using responders will set the flash message to :notice and :alert. You can change
83
+ that through the following configuration value:
84
+
85
+ ```ruby
86
+ InheritedResources.flash_keys = [ :success, :failure ]
87
+ ```
88
+
89
+ Notice the CollectionResponder won't work with InheritedResources, as
90
+ InheritedResources hardcodes the redirect path based on the current scope (like
91
+ belongs to, polymorphic associations, etc).
92
+
93
+ ## Basic Usage
94
+
95
+ To use Inherited Resources you just have to inherit (duh) it:
96
+
97
+ ```ruby
98
+ class ProjectsController < InheritedResources::Base
99
+ end
100
+ ```
101
+
102
+ And all actions are defined and working, check it! Your projects collection
103
+ (in the index action) is still available in the instance variable `@projects`
104
+ and your project resource (all other actions) is available as `@project`.
105
+
106
+ The next step is to define which mime types this controller provides:
107
+
108
+ ```ruby
109
+ class ProjectsController < InheritedResources::Base
110
+ respond_to :html, :xml, :json
111
+ end
112
+ ```
113
+
114
+ You can also specify them per action:
115
+
116
+ ```ruby
117
+ class ProjectsController < InheritedResources::Base
118
+ respond_to :html, :xml, :json
119
+ respond_to :js, :only => :create
120
+ respond_to :iphone, :except => [ :edit, :update ]
121
+ end
122
+ ```
123
+
124
+ For each request, it first checks if the "controller/action.format" file is
125
+ available (for example "projects/create.xml") and if it's not, it checks if
126
+ the resource respond to :to_format (in this case, `:to_xml`). Otherwise returns 404.
127
+
128
+ Another option is to specify which actions the controller will inherit from
129
+ the `InheritedResources::Base`:
130
+
131
+ ```ruby
132
+ class ProjectsController < InheritedResources::Base
133
+ actions :index, :show, :new, :create
134
+ end
135
+ ```
136
+
137
+ Or:
138
+
139
+ ```ruby
140
+ class ProjectsController < InheritedResources::Base
141
+ actions :all, :except => [ :edit, :update, :destroy ]
142
+ end
143
+ ```
144
+
145
+ In your views, you will get the following helpers:
146
+
147
+ ```ruby
148
+ resource #=> @project
149
+ collection #=> @projects
150
+ resource_class #=> Project
151
+ ```
152
+
153
+ As you might expect, collection (`@projects` instance variable) is only available
154
+ on index actions.
155
+
156
+ If for some reason you cannot inherit from `InheritedResources::Base`, you can
157
+ call inherit_resources in your controller class scope:
158
+
159
+ ```ruby
160
+ class AccountsController < ApplicationController
161
+ inherit_resources
162
+ end
163
+ ```
164
+
165
+ One reason to use the `inherit_resources` macro would be to ensure that your controller
166
+ never responds with the html mime-type. `InheritedResources::Base` already
167
+ responds to `:html`, and the `respond_to` macro is strictly additive.
168
+ Therefore, if you want to create a controller that, for example, responds ONLY via `:js`,
169
+ you will have write it this way:
170
+
171
+ ```ruby
172
+ class AccountsController < ApplicationController
173
+ respond_to :js
174
+ inherit_resources
175
+ end
176
+ ```
177
+
178
+ ## Overwriting defaults
179
+
180
+ Whenever you inherit from InheritedResources, several defaults are assumed.
181
+ For example you can have an `AccountsController` for account management while the
182
+ resource is a `User`:
183
+
184
+ ```ruby
185
+ class AccountsController < InheritedResources::Base
186
+ defaults :resource_class => User, :collection_name => 'users', :instance_name => 'user'
187
+ end
188
+ ```
189
+
190
+ In the case above, in your views you will have `@users` and `@user` variables, but
191
+ the routes used will still be `accounts_url` and `account_url`. If you plan also to
192
+ change the routes, you can use `:route_collection_name` and `:route_instance_name`.
193
+
194
+ Namespaced controllers work out of the box, but if you need to specify a
195
+ different route prefix you can do the following:
196
+
197
+ ```ruby
198
+ class Administrators::PeopleController < InheritedResources::Base
199
+ defaults :route_prefix => 'admin'
200
+ end
201
+ ```
202
+
203
+ Then your named routes will be: `admin_people_url`, `admin_person_url` instead
204
+ of `administrators_people_url` and `administrators_person_url`.
205
+
206
+ If you want to customize how resources are retrieved you can overwrite
207
+ collection and resource methods. The first is called on index action and the
208
+ second on all other actions. Let's suppose you want to add pagination to your
209
+ projects collection:
210
+
211
+ ```ruby
212
+ class ProjectsController < InheritedResources::Base
213
+ protected
214
+ def collection
215
+ @projects ||= end_of_association_chain.paginate(:page => params[:page])
216
+ end
217
+ end
218
+ ```
219
+
220
+ The `end_of_association_chain` returns your resource after nesting all associations
221
+ and scopes (more about this below).
222
+
223
+ InheritedResources also introduces another method called `begin_of_association_chain`.
224
+ It's mostly used when you want to create resources based on the `@current_user` and
225
+ you have urls like "account/projects". In such cases you have to do
226
+ `@current_user.projects.find` or `@current_user.projects.build` in your actions.
227
+
228
+ You can deal with it just by doing:
229
+
230
+ ```ruby
231
+ class ProjectsController < InheritedResources::Base
232
+ protected
233
+ def begin_of_association_chain
234
+ @current_user
235
+ end
236
+ end
237
+ ```
238
+
239
+ ## Overwriting actions
240
+
241
+ Let's suppose that after destroying a project you want to redirect to your
242
+ root url instead of redirecting to projects url. You just have to do:
243
+
244
+ ```ruby
245
+ class ProjectsController < InheritedResources::Base
246
+ def destroy
247
+ super do |format|
248
+ format.html { redirect_to root_url }
249
+ end
250
+ end
251
+ end
252
+ ```
253
+
254
+ You are opening your action and giving the parent action a new behavior. On
255
+ the other hand, I have to agree that calling super is not very readable. That's
256
+ why all methods have aliases. So this is equivalent:
257
+
258
+ ```ruby
259
+ class ProjectsController < InheritedResources::Base
260
+ def destroy
261
+ destroy! do |format|
262
+ format.html { redirect_to root_url }
263
+ end
264
+ end
265
+ end
266
+ ```
267
+
268
+ Since most of the time when you change a create, update or destroy
269
+ action you do so because you want to to change its redirect url, a shortcut is
270
+ provided. So you can do:
271
+
272
+ ```ruby
273
+ class ProjectsController < InheritedResources::Base
274
+ def destroy
275
+ destroy! { root_url }
276
+ end
277
+ end
278
+ ```
279
+
280
+ If you simply want to change the flash message for a particular action, you can
281
+ pass the message to the parent action using the keys `:notice` and `:alert` (as you
282
+ would with flash):
283
+
284
+ ```ruby
285
+ class ProjectsController < InheritedResources::Base
286
+ def create
287
+ create!(:notice => "Dude! Nice job creating that project.")
288
+ end
289
+ end
290
+ ```
291
+
292
+ You can still pass the block to change the redirect, as mentioned above:
293
+
294
+ ```ruby
295
+ class ProjectsController < InheritedResources::Base
296
+ def create
297
+ create!(:notice => "Dude! Nice job creating that project.") { root_url }
298
+ end
299
+ end
300
+ ```
301
+
302
+ Now let's suppose that before create a project you have to do something special
303
+ but you don't want to create a before filter for it:
304
+
305
+ ```ruby
306
+ class ProjectsController < InheritedResources::Base
307
+ def create
308
+ @project = Project.new(params[:project])
309
+ @project.something_special!
310
+ create!
311
+ end
312
+ end
313
+ ```
314
+
315
+ Yes, it's that simple! The nice part is since you already set the instance variable
316
+ `@project`, it will not build a project again.
317
+
318
+ Before we finish this topic, we should talk about one more thing: "success/failure
319
+ blocks". Let's suppose that when we update our project, in case of failure, we
320
+ want to redirect to the project url instead of re-rendering the edit template.
321
+
322
+ Our first attempt to do this would be:
323
+
324
+ ```ruby
325
+ class ProjectsController < InheritedResources::Base
326
+ def update
327
+ update! do |format|
328
+ unless @project.errors.empty? # failure
329
+ format.html { redirect_to project_url(@project) }
330
+ end
331
+ end
332
+ end
333
+ end
334
+ ```
335
+
336
+ Looks too verbose, right? We can actually do:
337
+
338
+ ```ruby
339
+ class ProjectsController < InheritedResources::Base
340
+ def update
341
+ update! do |success, failure|
342
+ failure.html { redirect_to project_url(@project) }
343
+ end
344
+ end
345
+ end
346
+ ```
347
+
348
+ Much better! So explaining everything: when you give a block which expects one
349
+ argument it will be executed in both scenarios: success and failure. But if you
350
+ give a block that expects two arguments, the first will be executed only in
351
+ success scenarios and the second in failure scenarios. You keep everything
352
+ clean and organized inside the same action.
353
+
354
+ ## Smart redirects
355
+
356
+ Although the syntax above is a nice shortcut, you won't need to do it frequently
357
+ because (since version 1.2) Inherited Resources has smart redirects. Redirects
358
+ in actions calculates depending on the existent controller methods.
359
+
360
+ Redirects in create and update actions calculates in the following order: `resource_url`,
361
+ `collection_url`, `parent_url` (which we are going to see later), and `root_url`. Redirect
362
+ in destroy action calculate in following order `collection_url`, `parent_url`, `root_url`.
363
+
364
+ Example:
365
+
366
+ ```ruby
367
+ class ButtonsController < InheritedResources::Base
368
+ belongs_to :window
369
+ actions :all, :except => [:show, :index]
370
+ end
371
+ ```
372
+
373
+ This controller redirect to parent window after all CUD actions.
374
+
375
+ ## Success and failure scenarios on destroy
376
+
377
+ The destroy action can also fail, this usually happens when you have a
378
+ `before_destroy` callback in your model which returns false. However, in
379
+ order to tell InheritedResources that it really failed, you need to add
380
+ errors to your model. So your `before_destroy` callback on the model should
381
+ be something like this:
382
+
383
+ ```ruby
384
+ def before_destroy
385
+ if cant_be_destroyed?
386
+ errors.add(:base, "not allowed")
387
+ false
388
+ end
389
+ end
390
+ ```
391
+
392
+ ## Belongs to
393
+
394
+ Finally, our Projects are going to get some Tasks. Then you create a
395
+ `TasksController` and do:
396
+
397
+ ```ruby
398
+ class TasksController < InheritedResources::Base
399
+ belongs_to :project
400
+ end
401
+ ```
402
+
403
+ `belongs_to` accepts several options to be able to configure the association.
404
+ For example, if you want urls like "/projects/:project_title/tasks", you can
405
+ customize how InheritedResources find your projects:
406
+
407
+ ```ruby
408
+ class TasksController < InheritedResources::Base
409
+ belongs_to :project, :finder => :find_by_title!, :param => :project_title
410
+ end
411
+ ```
412
+
413
+ It also accepts `:route_name`, `:parent_class` and `:instance_name` as options.
414
+ Check the [lib/inherited_resources/class_methods.rb](https://github.com/josevalim/inherited_resources/blob/master/lib/inherited_resources/class_methods.rb)
415
+ for more.
416
+
417
+ ## Nested belongs to
418
+
419
+ Now, our Tasks get some Comments and you need to nest even deeper. Good
420
+ practices says that you should never nest more than two resources, but sometimes
421
+ you have to for security reasons. So this is an example of how you can do it:
422
+
423
+ ```ruby
424
+ class CommentsController < InheritedResources::Base
425
+ nested_belongs_to :project, :task
426
+ end
427
+ ```
428
+
429
+ If you need to configure any of these belongs to, you can nest them using blocks:
430
+
431
+ ```ruby
432
+ class CommentsController < InheritedResources::Base
433
+ belongs_to :project, :finder => :find_by_title!, :param => :project_title do
434
+ belongs_to :task
435
+ end
436
+ end
437
+ ```
438
+
439
+ Warning: calling several `belongs_to` is the same as nesting them:
440
+
441
+ ```ruby
442
+ class CommentsController < InheritedResources::Base
443
+ belongs_to :project
444
+ belongs_to :task
445
+ end
446
+ ```
447
+
448
+ In other words, the code above is the same as calling `nested_belongs_to`.
449
+
450
+ ## Polymorphic belongs to
451
+
452
+ We can go even further. Let's suppose our Projects can now have Files, Messages
453
+ and Tasks, and they are all commentable. In this case, the best solution is to
454
+ use polymorphism:
455
+
456
+ ```ruby
457
+ class CommentsController < InheritedResources::Base
458
+ belongs_to :task, :file, :message, :polymorphic => true
459
+ # polymorphic_belongs_to :task, :file, :message
460
+ end
461
+ ```
462
+
463
+ You can even use it with nested resources:
464
+
465
+ ```ruby
466
+ class CommentsController < InheritedResources::Base
467
+ belongs_to :project do
468
+ belongs_to :task, :file, :message, :polymorphic => true
469
+ end
470
+ end
471
+ ```
472
+
473
+ The url in such cases can be:
474
+
475
+ ```
476
+ /project/1/task/13/comments
477
+ /project/1/file/11/comments
478
+ /project/1/message/9/comments
479
+ ```
480
+
481
+ When using polymorphic associations, you get some free helpers:
482
+
483
+ ```ruby
484
+ parent? #=> true
485
+ parent_type #=> :task
486
+ parent_class #=> Task
487
+ parent #=> @task
488
+ ```
489
+
490
+ Right now, Inherited Resources is limited and does not allow you
491
+ to have two polymorphic associations nested.
492
+
493
+ ## Optional belongs to
494
+
495
+ Later you decide to create a view to show all comments, independent if they belong
496
+ to a task, file or message. You can reuse your polymorphic controller just doing:
497
+
498
+ ```ruby
499
+ class CommentsController < InheritedResources::Base
500
+ belongs_to :task, :file, :message, :optional => true
501
+ # optional_belongs_to :task, :file, :message
502
+ end
503
+ ```
504
+
505
+ This will handle all those urls properly:
506
+
507
+ ```
508
+ /comment/1
509
+ /tasks/2/comment/5
510
+ /files/10/comment/3
511
+ /messages/13/comment/11
512
+ ```
513
+
514
+ This is treated as a special type of polymorphic associations, thus all helpers
515
+ are available. As you expect, when no parent is found, the helpers return:
516
+
517
+ ```ruby
518
+ parent? #=> false
519
+ parent_type #=> nil
520
+ parent_class #=> nil
521
+ parent #=> nil
522
+ ```
523
+
524
+ ## Singletons
525
+
526
+ Now we are going to add manager to projects. We say that `Manager` is a singleton
527
+ resource because a `Project` has just one manager. You should declare it as
528
+ `has_one` (or resource) in your routes.
529
+
530
+ To declare an resource of current controller as singleton, you just have to give the
531
+ `:singleton` option in defaults.
532
+
533
+ ```ruby
534
+ class ManagersController < InheritedResources::Base
535
+ defaults :singleton => true
536
+ belongs_to :project
537
+ # singleton_belongs_to :project
538
+ end
539
+ ```
540
+
541
+ So now you can use urls like "/projects/1/manager".
542
+
543
+ In the case of nested resources (when some of the can be singletons) you can declare it separately
544
+
545
+ ```ruby
546
+ class WorkersController < InheritedResources::Base
547
+ #defaults :singleton => true #if you have only single worker
548
+ belongs_to :project
549
+ belongs_to :manager, :singleton => true
550
+ end
551
+ ```
552
+
553
+ This is correspond urls like "/projects/1/manager/workers/1".
554
+
555
+ It will deal with everything again and hide the action :index from you.
556
+
557
+ ## Namespaced Controllers
558
+
559
+ Namespaced controllers works out the box.
560
+
561
+ ```ruby
562
+ class Forum::PostsController < InheritedResources::Base
563
+ end
564
+ ```
565
+
566
+ Inherited Resources prioritizes the default resource class for the namespaced controller in
567
+ this order:
568
+
569
+ ```
570
+ Forum::Post
571
+ ForumPost
572
+ Post
573
+ ```
574
+
575
+ ## URL Helpers
576
+
577
+ When you use InheritedResources it creates some URL helpers.
578
+ And they handle everything for you. :)
579
+
580
+ ```ruby
581
+ # /posts/1/comments
582
+ resource_url # => /posts/1/comments/#{@comment.to_param}
583
+ resource_url(comment) # => /posts/1/comments/#{comment.to_param}
584
+ new_resource_url # => /posts/1/comments/new
585
+ edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit
586
+ edit_resource_url(comment) # => /posts/1/comments/#{comment.to_param}/edit
587
+ collection_url # => /posts/1/comments
588
+ parent_url # => /posts/1
589
+
590
+ # /projects/1/tasks
591
+ resource_url # => /projects/1/tasks/#{@task.to_param}
592
+ resource_url(task) # => /projects/1/tasks/#{task.to_param}
593
+ new_resource_url # => /projects/1/tasks/new
594
+ edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit
595
+ edit_resource_url(task) # => /projects/1/tasks/#{task.to_param}/edit
596
+ collection_url # => /projects/1/tasks
597
+ parent_url # => /projects/1
598
+
599
+ # /users
600
+ resource_url # => /users/#{@user.to_param}
601
+ resource_url(user) # => /users/#{user.to_param}
602
+ new_resource_url # => /users/new
603
+ edit_resource_url # => /users/#{@user.to_param}/edit
604
+ edit_resource_url(user) # => /users/#{user.to_param}/edit
605
+ collection_url # => /users
606
+ parent_url # => /
607
+ ```
608
+
609
+ Those urls helpers also accepts a hash as options, just as in named routes.
610
+
611
+ ```ruby
612
+ # /projects/1/tasks
613
+ collection_url(:page => 1, :limit => 10) #=> /projects/1/tasks?page=1&limit=10
614
+ ```
615
+
616
+ In polymorphic cases, you can also give the parent as parameter to `collection_url`.
617
+
618
+ Another nice thing is that those urls are not guessed during runtime. They are
619
+ all created when your application is loaded (except for polymorphic
620
+ associations, that relies on Rails' `polymorphic_url`).
621
+
622
+ ## Custom actions
623
+
624
+ Since version 1.2, Inherited Resources allows you to define custom actions in controller:
625
+
626
+ ```ruby
627
+ class ButtonsController < InheritedResources::Base
628
+ custom_actions :resource => :delete, :collection => :search
629
+ end
630
+ ```
631
+
632
+ This code creates delete and search actions in controller (they behaves like show and
633
+ index actions accordingly). Also, it will produce `delete_resource_{path,url}` and
634
+ `search_resources_{path,url}` url helpers.
635
+
636
+ ## What about views?
637
+
638
+ Sometimes just DRYing up the controllers is not enough. If you need to DRY up your views,
639
+ check this Wiki page:
640
+
641
+ ```
642
+ https://github.com/josevalim/inherited_resources/wiki/Views-Inheritance
643
+ ```
644
+
645
+ Notice that Rails 3.1 ships with view inheritance built-in.
646
+
647
+ ## Some DSL
648
+
649
+ For those DSL lovers, InheritedResources won't leave you alone. You can overwrite
650
+ your success/failure blocks straight from your class binding. For it, you just
651
+ need to add a DSL module to your application controller:
652
+
653
+ ```ruby
654
+ class ApplicationController < ActionController::Base
655
+ include InheritedResources::DSL
656
+ end
657
+ ```
658
+
659
+ And then you can rewrite the last example as:
660
+
661
+ ```ruby
662
+ class ProjectsController < InheritedResources::Base
663
+ update! do |success, failure|
664
+ failure.html { redirect_to project_url(@project) }
665
+ end
666
+ end
667
+ ```
668
+
669
+ ## Strong Parameters
670
+
671
+ If your controller defines a method named `permitted_params`, InheritedResources
672
+ will call it where it would normally call params. This allows for easy
673
+ integration with the strong_parameters gem:
674
+
675
+ ```ruby
676
+ def permitted_params
677
+ params.permit(:widget => [:permitted_field, :other_permitted_field])
678
+ end
679
+ ```
680
+
681
+ Note that this doesn't work if you use strong_parameters' require method
682
+ instead of permit, because whereas permit returns the entire sanitized
683
+ parameter hash, require returns only the sanitized params below the parameter
684
+ you required.
685
+
686
+ If you need `params.require` you can do it like this:
687
+
688
+ ```ruby
689
+ def permitted_params
690
+ {:widget => params.require(:widget => [:permitted_field, :other_permitted_field])}
691
+ end
692
+ ```
693
+
694
+ Or better yet just override `#build_resource_params` directly:
695
+
696
+ ```ruby
697
+ def build_resource_params
698
+ [params.require(:widget => [:permitted_field, :other_permitted_field])]
699
+ end
700
+ ```
701
+
702
+ ## Bugs and Feedback
703
+
704
+ If you discover any bugs, please describe it in the issues tracker, including Rails and InheritedResources versions.
705
+
706
+ Questions are better handled on StackOverflow.
707
+
708
+ Copyright (c) 2009-2012 José Valim http://blog.plataformatec.com.br
709
+ See the attached MIT License.