inherited_resources 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.