From b8ee5732dbc228958260753ffc4be6d188aadf15 Mon Sep 17 00:00:00 2001 From: Alex Ghiculescu Date: Mon, 22 Mar 2021 11:05:14 -0500 Subject: [PATCH] Simplify singular resource example This: ```ruby resource :geocoder ``` and this: ```ruby resource :geocoder resolve('Geocoder') { [:geocoder] } ``` create exactly the same routes. Thus, it's better to show the simpler example rather than imply that both method calls are needed. `resolve` is used for [polymorphic routes](https://guides.rubyonrails.org/routing.html#using-resolve) but isn't necessary in this example. --- actionpack/lib/action_dispatch/routing/mapper.rb | 10 ++++++++++ guides/source/form_helpers.md | 9 ++++++++- guides/source/routing.md | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index b09c9c92ee..1960e1f57a 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1306,6 +1306,16 @@ module ActionDispatch # DELETE /profile # POST /profile # + # If you want instances of a model to work with this resource via + # record identification (eg. in +form_with+ or +redirect_to+), you + # will need to call resolve[rdoc-ref:CustomUrls#resolve]: + # + # resource :profile + # resolve('Profile') { [:profile] } + # + # # Enables this to work with singular routes: + # form_with(model: @profile) {} + # # === Options # Takes same options as resources[rdoc-ref:#resources] def resource(*resources, &block) diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md index 85bd1acdc9..f1abd8525f 100644 --- a/guides/source/form_helpers.md +++ b/guides/source/form_helpers.md @@ -271,7 +271,7 @@ resources :articles TIP: Declaring a resource has a number of side effects. See [Rails Routing from the Outside In](routing.html#resource-routing-the-rails-default) guide for more information on setting up and using resources. -When dealing with RESTful resources, calls to `form_with` can get significantly easier if you rely on **record identification**. In short, you can just pass the model instance and have Rails figure out model name and the rest: +When dealing with RESTful resources, calls to `form_with` can get significantly easier if you rely on **record identification**. In short, you can just pass the model instance and have Rails figure out model name and the rest. In both of these examples, the long and short style have the same outcome: ```ruby ## Creating a new article @@ -289,6 +289,13 @@ form_with(model: @article) Notice how the short-style `form_with` invocation is conveniently the same, regardless of the record being new or existing. Record identification is smart enough to figure out if the record is new by asking `record.persisted?`. It also selects the correct path to submit to, and the name based on the class of the object. +If you have a [singular resource](routing.html#singular-resources), you will need to call `resource` and `resolve` for it to work with `form_with`: + +```ruby +resource :geocoder +resolve('Geocoder') { [:geocoder] } +``` + WARNING: When you're using STI (single-table inheritance) with your models, you can't rely on record identification on a subclass if only their parent class is declared a resource. You will have to specify `:url`, and `:scope` (the model name) explicitly. #### Dealing with Namespaces diff --git a/guides/source/routing.md b/guides/source/routing.md index 34e84c0cbc..3eb0fda2fe 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -198,6 +198,8 @@ A singular resourceful route generates these helpers: * `edit_geocoder_path` returns `/geocoder/edit` * `geocoder_path` returns `/geocoder` +NOTE: The call to `resolve` is necessary for converting instances of the `Geocoder` to routes through [record identification](form_helpers.html#relying-on-record-identification). + As with plural resources, the same helpers ending in `_url` will also include the host, port, and path prefix. ### Controller Namespaces and Routing