Skip to content

Commit 847bd59

Browse files
committed
[skip ci] Add composite primary key examples to Rails guides
- Action Controller Overview: Add example of how a cpk record can be found using a show action. - Action View Form Helpers: Add example of what a form updating a cpk record looks like. - Action View Helpers: Add examples for url_for and link_to cpk record urls.
1 parent 9fd3d03 commit 847bd59

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

guides/source/action_controller_overview.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,34 @@ In this case, when a user opens the URL `/clients/active`, `params[:status]` wil
186186
[`controller_name`]: https://api.rubyonrails.org/classes/ActionController/Metal.html#method-i-controller_name
187187
[`action_name`]: https://api.rubyonrails.org/classes/AbstractController/Base.html#method-i-action_name
188188

189+
### Composite Key Parameters
190+
191+
Composite key parameters contain multiple values in one parameter. For this reason, we need to be able to extract each value and pass them to Active Record. We can leverage the `extract_value` method for this use-case.
192+
193+
Given the following controller:
194+
195+
```ruby
196+
class BooksController < ApplicationController
197+
def show
198+
# Extract the composite ID value from URL parameters.
199+
id = params.extract_value(:id)
200+
# Find the book using the composite ID.
201+
@book = Book.find(id)
202+
# use the default rendering behaviour to render the show view.
203+
end
204+
end
205+
```
206+
207+
And the following route:
208+
209+
```ruby
210+
get '/books/:id', to: 'books#show'
211+
```
212+
213+
When a user opens the URL `/books/4_2`, the controller will extract the composite
214+
key value `["4", "2"]` and pass it to `Book.find` to render the right record in the view.
215+
The `extract_value` method may be used to extract arrays out of any delimited parameters.
216+
189217
### `default_url_options`
190218

191219
You can set global default parameters for URL generation by defining a method called `default_url_options` in your controller. Such a method must return a hash with the desired defaults, whose keys must be symbols:

guides/source/action_view_helpers.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,9 @@ url_for @profile
468468

469469
url_for [ @hotel, @booking, page: 2, line: 3 ]
470470
# => /hotels/1/bookings/1?line=3&page=2
471+
472+
url_for @post # given a composite primary key [:blog_id, :id]
473+
# => /posts/1_2
471474
```
472475

473476
#### link_to
@@ -481,6 +484,9 @@ when passing models to `link_to`.
481484
```ruby
482485
link_to "Profile", @profile
483486
# => <a href="/profiles/1">Profile</a>
487+
488+
link_to "Book", @book # given a composite primary key [:author_id, :id]
489+
# => <a href="/books/2_1">Book</a>
484490
```
485491

486492
You can use a block as well if your link target can't fit in the name parameter. ERB example:

guides/source/form_helpers.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,43 @@ There are several things to notice here:
236236

237237
TIP: Conventionally your inputs will mirror model attributes. However, they don't have to! If there is other information you need you can include it in your form just as with attributes and access it via `params[:article][:my_nifty_non_attribute_input]`.
238238

239+
#### Composite primary key forms
240+
241+
Forms may also be built with composite primary key models. In this case, the form
242+
building syntax is the same with slightly different output.
243+
244+
Given a `@book` model object with a composite key `[:author_id, :id]`:
245+
246+
```ruby
247+
@book = Book.find([2, 25])
248+
# => #<Book id: 25, title: "Some book", author_id: 2>
249+
```
250+
251+
The following form:
252+
253+
```erb
254+
<%= form_with model: @book do |form| %>
255+
<%= form.text_field :title %>
256+
<%= form.submit %>
257+
<% end %>
258+
```
259+
260+
Outputs:
261+
262+
```html
263+
<form action="/books/2_25" method="post" accept-charset="UTF-8" >
264+
<input name="authenticity_token" type="hidden" value="..." />
265+
<input type="text" name="book[title]" id="book_title" value="My book" />
266+
<input type="submit" name="commit" value="Update Book" data-disable-with="Update Book">
267+
</form>
268+
```
269+
270+
Note the generated URL contains the `author_id` and `id` delimited by an underscore.
271+
Once submitted, the controller can [extract each primary key value][] from parameters
272+
and update the record as it would with a singular primary key.
273+
274+
[extract each primary key value]: action_controller_overview.html#composite-key-parameters
275+
239276
#### The `fields_for` Helper
240277

241278
The [`fields_for`][] helper creates a similar binding but without rendering a

0 commit comments

Comments
 (0)