You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Essential Guide 4: Forms & Actions (Create, Update, Delete)
2
+
2
3
Welcome to the forth part of the 10-step-guide of setting up a working Rails CRUD app with `matestack-ui-core`!
3
4
4
5
## Introduction
5
-
In the [previous guide](guides/essential/03_index_show_transition.md), we added index and show pages for the **person** model. In this part, we will add the functionality to add new instances and edit and delete our database records using `matestack` forms.
6
+
7
+
In the [previous guide](guides/essential/03_index_show_transition.md), we added index and show pages for the **person** model. In this part, we will implement the create, update and delete part of our CRUD application. For this we will introduce the matestack `forms`.
6
8
7
9
In this guide, we will
8
-
- add a **New** page and corresponding controller action to create new persons
9
-
- add an **Edit** page and corresponding controller action to modify existing persons
10
-
- add an action with a delete button to the "show" page and corresponding controller action to remove an existing person from the database
11
-
- introduce the concept of `matestack` forms
12
-
- introduce the concept of `matestack` actions
10
+
- add a new page and action action to create new persons
11
+
- add an edit page and action to modify existing persons
12
+
- add an delete action to delete existing persons
13
+
- introduce the concept of matestack forms
14
+
- introduce the concept of matestack actions
15
+
16
+
action with a delete button to the "show" page and corresponding controller action to remove an existing person from the database
13
17
14
18
## Prerequisites
15
-
We expect you to have successfully finished the [previous guide](guides/essential/03_index_show_transition.md) and no uncommited changes in your project.
19
+
We expect you to have successfully finished the [previous guide](guides/essential/03_index_show_transition.md).
16
20
17
21
## Updating the person model
18
-
Let's make sure all the persons in our database actually end up having a name and a a role by adding those lines to `app/models/person.rb`:
22
+
23
+
All persons should have a first name, last name and a role. Therefore we add validations to our person model for these three attributes in `person.rb`.
19
24
20
25
```ruby
21
26
validates :first_name, presence:true
22
27
validates :last_name, presence:true
23
28
validates :role, presence:true
24
29
```
25
30
26
-
This might not seem like a big change, but will help with validating form input later on!
31
+
We only check for presence of this three attributes.
27
32
28
33
## Preparing routes & controller
34
+
29
35
In your `config/routes.rb`, change
30
36
31
37
```ruby
@@ -38,19 +44,15 @@ to
38
44
resources :persons
39
45
```
40
46
41
-
to allow further actions for the ressource.
47
+
in order to let rails generate all CRUD routes for persons.
42
48
43
49
Then, in the `persons_controller.rb`, update the contents like this:
@@ -111,23 +112,20 @@ class PersonsController < ApplicationController
111
112
end
112
113
```
113
114
114
-
What's going on there? We've added `render`-methods for two new `matestack` pages (**New** and **Edit**) and controller endpoints for **create**, **update** and **destroy** actions. Since we're interacting with the database directly now, we also need to sanitize the params and, to keep the code clean, have extracted some functionality into a `before_action`.
115
+
What's going on there? We've added `render`-calls for two new matestack pages (new, edit) and controller actions for create, update and destroy. To keep the code clean, we have extracted some functionality into a `before_action`and added the `person_params` method to extract person relevant params from all params in rails safe params manner.
115
116
116
117
Nothing extraordinary, but definitely stepping things up a bit!
117
118
118
-
## Adding the **New** and **Edit** pages
119
+
## Adding the new and edit pages with forms
120
+
119
121
Create a new page in `app/matestack/demo/pages/persons/new.rb` and add the following content:
@@ -146,9 +144,9 @@ class Demo::Pages::Persons::New < Matestack::Ui::Page
146
144
147
145
defnew_person_form_config
148
146
{
149
-
for:@person,
147
+
for:Person.new,
150
148
method::post,
151
-
path::persons_path,
149
+
path: persons_path,
152
150
success: {
153
151
transition: {
154
152
follow_response:true
@@ -161,11 +159,21 @@ end
161
159
```
162
160
163
161
What's going on here? Let's break it down:
164
-
- in the `prepare` method, an empty person record is created so we can fill it later
165
-
- within the `response` method, there's a link back to the **Show** page, a heading and the first `matestack` form, featuring two text input fields, radio select fields and a submit button
166
-
- the `new_person_form_config` tells the form which data to use (the empty person, in this case), where to send the inputs upon submission and how to handle successful (and, potentially, unsuccessful) response messages from the controller!
167
162
168
-
Take a moment to familiarize yourself with everything going on in the file, and then go ahead and create another page in `app/matestack/demo/pages/persons/edit.rb`, featuring similar content:
163
+
Within our response method we have at first a transition to the person index page. After that comes _h2_ tag as a headline stating 'Create a new person'. Nothing new so long. Afterwards comes an unfamiliar call of `form`.
164
+
165
+
Let's take a closer look. Like in Rails with `form_for` you can create a form in matestack with `form`. It takes a hash as first argument for configuration. In this case we defined `new_person_form_config` to return the config hash for our form. In the config hash you can set the http request method, a path, success and failure configs and a for key, which will be explained soon. This form gets submitted as a POST request to the `persons_path`.
166
+
167
+
The `for` key let's us define for what this form is. In this case we pass a empty model to the form component, which will therefore submitt the form inputs wrapped by the model name following the Rails behavior and conventions.
168
+
169
+
The 'success' key let's us define a behavior when the form was submitted successful, which means the server returned a status code of 2XX. In this case we tell the form that if successful it should follow the transition path we return in our controller action. So a page transition will happen to the detail page of our newly created model. We could also configure a failure behavior by specifying the `failure` key.
170
+
171
+
Inside our form component we have calls to normal html components like `label, br, button` which render the corresponding html tag and we have calls for form inputs and a form submit. Let's take a closer look at the `form_input` call. A form input at least requires a key and a type. The type can be any html input type possible. The key defines the input name as which it will get submitted. If the model specified by the `for` key in the form config responds to the key the input will be prefilled with the value the model returns. `form_radio, form_select, form_checkbox` helpers can take an array or hash in the `options` key. They render for example a radio button for each option in the array or hash. In case of an array the label and value are the same for each radio button, in case of a hash the keys are used as labels and the values as values.
172
+
To enable the user to submit the form, we added a button to click. This button needs to be wrapped inside a `form_submit` call, which will take care of triggering the form submit if the contents inside the given block is clicked.
173
+
174
+
To learn more, check out the [complete API documentation](docs/components/form.md) for the `form` component.
175
+
176
+
Take a moment to familiarize yourself with everything going on and then go ahead and create another page in `app/matestack/demo/pages/persons/edit.rb`, featuring similar content:
@@ -208,19 +216,39 @@ class Demo::Pages::Persons::Edit < Matestack::Ui::Page
208
216
end
209
217
```
210
218
211
-
Again, we're using a form within the `response` method and define its behaviour in the `person_edit_form_config`. Since this time, an existing person is looked up in the database, the form gets initialized with his/her data.
219
+
Again, we're using a form within the `response` method and define its behaviour in the `person_edit_form_config`. Since this time, an existing person is looked up in the database, the form gets initialized with his/her data as described above.
220
+
221
+
## Updating the index page
212
222
213
-
## Updating the **Index** page
214
223
Within the `response` block on the **Index** page (`app/matestack/demo/pages/persons/index.rb`), add the following line:
215
224
216
225
```ruby
217
226
transition path::new_person_path, text:'Create new person'
218
227
```
219
228
220
-
As you might have guessed, this takes us to the **New** page and you can add a new person to the database there!
229
+
As you might have guessed, this takes us to the **New** page and you can create a new person there.
230
+
231
+
## Further introduction: Forms
232
+
233
+
During this article, you've got a general idea of how matestack forms handle data input. But since this is only an introductory guide, we can't cover all the possible use cases and functionality in here.
221
234
222
-
## Adding the **delete** button to the **Show** page
223
-
Update your **Show** page in `app/matestack/demo/pages/persons/show.rb` to look like this:
235
+
Let's do a quick recap: The `form` component can be used like other components we have seen before, but requires a hash as parameter for configuration. Within the hash, various configurations like HTTP method, submission path, payload and handling of success/failure responses can be set.
236
+
237
+
Beyond that, here's some suggestions of what you could try to add in the future:
238
+
- uploading files
239
+
- handling failure
240
+
- different input types like email, password, textfield, range or dropdown
241
+
- re-rendering parts of a page instead of doing a page transition
242
+
- using other Ruby objects than ActiveRecord collections
243
+
- fetching data from and sending data to third party APIs
244
+
245
+
To learn more, check out the [complete API documentation](docs/components/form.md) for the `form` component.
246
+
247
+
## Adding a delete button for persons
248
+
249
+
We want to add the ability to delete persons. For that we add a delete button to the persons show page, which will destroy the person model when it was clicked. To achieve this we will use matestacks `action` component.
250
+
251
+
Update your show page in `app/matestack/demo/pages/persons/show.rb` to look like this:
@@ -236,12 +264,9 @@ class Demo::Pages::Persons::Show < Matestack::Ui::Page
236
264
end
237
265
238
266
defdelete_person_config
239
-
return{
267
+
{
240
268
method::delete,
241
-
path::person_path,
242
-
params: {
243
-
id:@person.id
244
-
},
269
+
path: person_path(@person),
245
270
success: {
246
271
transition: {
247
272
follow_response:true
@@ -256,63 +281,37 @@ class Demo::Pages::Persons::Show < Matestack::Ui::Page
256
281
end
257
282
```
258
283
259
-
This is the first time we encounter another powerful `matestack` component: The `action` component! In the example above, the delete button gets wrapped into an `action` that receives a `*_config*` parameter. The configuration then is specified below, sending the currently displayed person's `id` to the **delete** action in the `person controller`. Upon a positive response from our controller, we configure our `action` component to follow the redirect specified in the **delete** action.
260
-
261
-
## Further introduction: Forms
262
-
During this article, you've got a general idea of how `matestack` forms handle data input. But since this is only an introductory guide, we can't cover all the possible use cases and functionality in here.
263
-
264
-
Let's do a quick recap: The `form` component can be used like the other components we have seen before, but requires a `*_config` parameter. Within the `*_config`, various parameters like HTTP method, submission path, payload and handling of success/error responses can be set.
265
-
266
-
Beyond that, here's some suggestions of what you could try to add in the future:
267
-
- uploading files
268
-
- handling failure
269
-
- different input types like email, password, textfield, range or dropdown
270
-
- re-rendering parts of a page instead of doing a page transition
271
-
- using other Ruby objects than ActiveRecord collections
272
-
- fetching data from and sending data to third party APIs instead of interacting with your database
273
-
274
-
To learn more, check out the [complete API documentation](docs/components/form.md) for the `form` component.
284
+
As you see we wrap our delete button inside an `action` component. Like the `form` component, an `action` component also takes a hash as first parameter for configuration. An action component triggers a asynchronous request when someone clicks on the wrapped content. The request target and http method are again configured in the hash. In this case when the action component is clicked it will send an DELETE request to `/persons/:id`. For a successful request we configured our `action` component to follow the redirect specified by the delete action. With the `confirm` keyword we can configure that when the button is clicked a confirm dialog pops up and needs to be confirmed before the request is send.
275
285
276
286
## Further introduction: Actions
277
287
As we've seen with the delete button, `matestack` actions are a convenient way to trigger HTTP requests without having to write a lot of code.
278
288
279
-
Let's do a quick recap: Similar to the `form`, an `action` component requires a `*_config`parameter and wraps other content, for example a button. This content is then clickable and triggers whatever HTTP request is specified in the configuration.
289
+
Let's do a quick recap: Similar to the `form`, an `action` component requires a hash as parameter for configuration and wraps other content, for example a button. This content is then clickable and triggers whatever HTTP request is specified in the configuration.
280
290
281
291
Beyond that, here's some suggestions of what you could try to add in the future:
282
292
- sending an advanced payload with the HTTP request
283
-
- adding a confirmation window
284
293
- re-rendering parts of a page on successful request
285
294
286
295
To learn more, check out the [complete API documentation](docs/components/action.md) for the `action` component.
287
296
288
297
## Local testing
298
+
289
299
Run `rails s` and head over to [localhost:3000](http://localhost:3000/) to test the changes! You should be able to create new persons as well as edit and delete existing ones!
290
300
291
301
## Saving the status quo
302
+
292
303
As usual, we want to commit the progress to Git. In the repo root, run
293
304
294
305
```sh
295
306
git add .&& git commit -m "Add edit/new matestack pages for person model (incl. create/update controller, routes), add delete button (incl. controller action & route) to person show page"
296
307
```
297
308
298
-
## Deployment
299
-
After you've finished all your changes and commited them to Git, run
300
-
301
-
```sh
302
-
git push heroku master
303
-
```
304
-
305
-
to deploy your latest changes (again, no migrations are needed as the database schema is still unchanged). Check the results via
306
-
307
-
```sh
308
-
heroku open
309
-
```
310
-
311
-
and celebrate your progress by creating some new persons, modifying existing ones and delete one or two!
312
-
313
309
## Recap & outlook
310
+
314
311
By now, we have already implemented the complete **CRUD** (**C**reate-**R**ead-**U**pdate-**D**elete) functionality around the person model. Neat!
315
312
316
-
But there's still six out of ten guides open - so what's left? In the upcoming chapters, we will dive deeper into some `matestack` concepts to further enhance both user experience and developer happiness!
313
+
We got a brief introduction of the `form` and `action` components and know how to use them.
314
+
315
+
But there's still more guides coming - so what's left? In the upcoming chapters, we will dive deeper into some `matestack` concepts to further enhance both user experience and developer happiness!
317
316
318
317
Take a well deserved rest and make sure to come back to the next part of this series, introducing the powerful [`async` and `collection` components](/guides/essential/04_form_create_update_delete.md).
0 commit comments