[ToDoList] More Front-end CRUD

  1. Updating Entries in the Front-End
  2. index: The King of Views
  3. Links, 1, 2, 3

 


 

Our application can now create new entries into our database and allow users to read them: by the reckoning of the CRUD principles, we have successfully created half of an application! But supposing a user entered a typo in their original submission of a To-Do item, or needed to add something to its description; this is where the update part of CRUD comes in, which we can achieve by adding functionality to edit to our app in similar fashion to how we've developed the existing functions.

The routes for this are already set up via our magic line in the routes configuration. Consulting the routes table we can see that the two actions we need to create are todos#edit and todos#update, which will present a form to edit a Todo object and write this change to the DB table respectively.

Let's begin by adding these to the TodosController (/app/controllers/todos_controller.rb) - make sure this goes above the private block at the bottom:

  def edit
    @todo = Todo.find(params[:id])         ## find Todo to edit from the ID in browser path
  end

  def update
    @todo = Todo.find(params[:id])         ## find the item
    if @todo.update(todo_params)           ## update DB entry
      flash[:notice] = 'Your To-Do item was successfully updated!'
      redirect_to todo_path(@todo)         ## redirect to show view if successful
    else
      render 'edit'                        ## show same form w/ errs if update unsuccessful
    end  
  end
Now you may notice that these two methods are extremely similar to the #show and #create methods respectively - in fact the code for #show and #edit are identical! There is a bit more of a difference between the if blocks in #update and #create, but we are still retrieving the Todo object in exactly the same way.
Bravo to you if you have questioned this and wondered if there is a way we can not just repeat code like this - we most certainly can, and we will do so when we refactor our code in a later section.

With our controller equipped with instructions on what to do, we can now create our edit view. As we've already realised, this will essentially be exactly the same interface as creating a new Todo entry, so we can save ourselves some work and simply copy the new view file into a separate edit view file:

$ cp app/views/todos/new.html.erb app/views/todos/edit.html.erb
And now all we need to do is change the heading at the top of the page to reflect this new functionality:
  <h3> Edit To-Do item: <%= @todo.id.to_s %> </h3>
Again, having identical code in two different files isn't the most optimal/efficient way of achieving this, but we will cover this as well when we refactor later on. For now, we can navigate to our edit page in the browser with a Todo id in the URL, and can see our new functionality in action!
(i.e. http://host/todos/1/edit).

ToDoList Edit view

 


 

By now I'd imagine there are quite a few To-Do items sitting in your database table, and quite frankly it's a pain having to guess their ID to reach them in the browser. Looking in our routes table we can see that our magic line in the config has allowed Rails has preempt this, and it has set up a /todos route for us that points to todos#index.

Not wanting to waste all of the hard effort Rails has gone to to make this easy for us, let's therefore add this action into our TodosController (again, above the private section at the bottom):

  def index
    @todos = Todo.all                           ## simply grab all of the Todo items
  end
This will simply pass the array of all of our Todo objects to a view using the variable we have cited (@todos), so let's create an index view to present this list to our users in a nice table.

Because we are nice app developers who want a happy experience for our users, let's also utilise Rails' handy link_to helper to provide links to the show and edit views for each of the To-Do items that we list. We will need to reference the prefix values from our routes to do so (not forgetting the _path suffix) and then pass the Todo object so that the helper can extract the id.

This sounds tricky I know, but Rails won't let us down. Let's create /app/views/todos/index.html.erb and fill it with:

<div align="center">
  <h3> Your To-Do items: </h3>

  <table border=1>                                       <!-- create table with a border -->
    <tr>
      <th> ID </th>                              <!-- give the table appropriate headers -->
      <th> Name </th>
      <th> Description </th>
    </tr>
    <% @todos.each do |todo| %>                          <!-- array passed by controller -->
      <tr>                                                  <!-- new row per Todo object --> 
        <td> <%= todo.id.to_s %> </td>                      <!-- insert values of object -->
        <td> <%= link_to todo.name, todo_path(todo) %> </td>     <!-- link name to #show -->
        <td> <%= trunacate(todo.description, length: 100) %> </td>
        <td> <%= link_to 'Show', todo_path(todo) %> </td>      <!-- pass todo var as arg -->
        <td> <%= link_to 'Edit', edit_todo_path(todo) %> </td>      <!-- #edit view link -->
      </tr>
    <% end %>                                                    <!-- end the each block -->
  </table>                                                      <!-- close off the table -->
</div>
Notice that we used the truncate helper on the description and passed it the number of characters we want to limit the visible field to, so that it won't completely take over our page if there is a large description.

If we now navigate to http://host/todos this will display a lovely table of all the valid Todo entries in the database (a To-Do list, if you will), with links to show them in full or edit them via a form. We have also been extra helpful and got the To-Do item's name to link to the show view!

ToDoList index view

 


 

While we are on the subject of making the site a bit more user-friendly, you might notice that we are missing a few links that would really make site navigation a lot easier. Let's get this done now, starting with an link in our main nav bar to view our To-Do list in /app/views/layouts/application.html.erb:

        | <%= link_to 'My To-Do List', todos_path %>  <!-- use route prefix and _path -->
From the index view, let's also have a link below the table to quickly create a new To-Do item. However let's make this a bit more fancy and put it in a button! The only complication here is that, by default, Rails will make button actions use POST instead of GET, but that's easily circumvented with a :method flag. Some would argue that buttons shouldn't be used this way, but I say no beauty without pain.
So, below the table but still within the div, let's add our button in /app/views/todos/index.html.erb:
  <p> <%= button_to 'Create new To-Do item', new_todo_path, method: :get %> <p>

ToDoList index view with nav and create button

It's looking a lot better already, right? Let's also deal with the views linked to from within in our table, and add options on the show view that can edit the displayed Todo as well as go back to the list - in /app/views/todos/show.html.erb (below the name and description):

  <p>
    <%= link_to 'Edit this item', edit_todo_path(@todo) %> <!-- pass obj from controller -->
    |  <%= link_to 'Back to To-Do list', todos_path %>       <!-- don't need to pass obj -->
  </p>
Now let's do the equivalent on the edit view, substituting the Edit link for a Show link - /app/views/todos/edit.html.erb:
  <p>
    <%= link_to 'Back to To-Do item', todo_path(@todo) %>                <!-- #show link -->
    |  <%= link_to 'Back to To-Do list', todos_path %>                  <!-- #index link -->
  </p>
And, to round it off, we'll also add an option to go back (or Cancel) on the new view - /app/views/todos/new.html.erb:
  <p> <%= link_to 'Cancel', todos_path %> </p>
Go back to your browser to test all of your lovely new links (if you haven't already), and feel free to take the opportunity to commit and push your changes to GitHub.

ToDoList Show view with links ToDoList Edit view with links ToDoList New view with links

 
 

Comments

Popular posts from this blog

New Rails Apps with Docker Compose

[ToDoList] Basic Pages

[ToDoList] Docker Compose