1. Adding Edit and Update Methods

Now that we're able to create our ideas smoothly, let's work on writing code so that users can edit and update the ideas.

First, let's go into ideas_controller.rb. Inside the file, let's add an edit method. In ideas_controller.rb, add the following code right under your create method.

Make sure you don't put it under private. Code written under private will make the code private, meaning that they won't be accessible outside of the class.

# end of create method

def edit
end

Review on Controller and Views Files

By default, once a controller action is triggered, Rails will try to find a file with the name of the controller action in app/views/controller_name.

For example, when the edit method in ideas_controller.rb is triggered, Rails will try to find a file called edit.html.erb inside app/views/ideas. Review this lesson for more information.

Let's create a file called edit.html.erb in the /app/views/ideas folder.

This edit.html.erb is where we want to put our form for editing ideas. Since we want to be able to tell rails which idea we are editing, let's tell rails to find the idea that we are working on and store that in an instance variable. Let's go back to the ideas_controller.rb and add a line of code to the edit method.

def edit
  @idea = Idea.find(params[:id])
end

find

What is this Idea.find(params[:id])?? This is a new concept, but let's try to break it down into little pieces.

First, let's open up our rails console. In the terminal, type in the following command and press enter:

rails console

Once it's open, let's type in the following command to display all of our ideas that are stored in the database.

Idea.all

All of your ideas should be displayed in the terminal now. Notice how each idea has it's own id.

When you create an object in Rails, it will give the object a unique id automatically. These ids can be used to retrieve objects.

For example, let's say we want to get an Idea with an id of 1. We can do this with the following command. In the rails console, type in the following command and press enter:

Idea.find(1)

The code above means: Find an Idea with an id of 1.

The find method can be used to retrieve an object that has the id passed in as a parameter:

Modelname.find(id)

Let's go back to this piece of code:

def edit
  @idea = Idea.find(params[:id])
end

Here we see code that we've never seen before: params[:id]. Let's break down what params are.

params

You will see params used in mainly 3 situations.

  • GET requests
  • POST requests
  • Routing parameters

Let's go through each one.

GET Requests

When a user makes a request to a server such as a GET request (refresher on HTTP methods in this lesson, information gets sent to the browser.

Many times, the params are encoded in the URL, like this:

http://www.example.com/?foo=1&boo=octopus

In this example, we have two pieces of data, foo and boo. foo is assigned a variable of 1 and boo is assigned a variable of octopus.

In Rails, we can get the values for each piece of data like this:

params[:foo] # returns 1
params[:boo] # returns octopus

POST requests

When making a POST request (for example, when you write a Facebook post and hit the submit button), the information will not be encoded in the URL like it did with the GET request example above. For example, in our application, we have the following form:

<!-- Button trigger modal -->
<button data-modal-target="default-modal" data-modal-toggle="default-modal" class="block text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" type="button">
Add New Idea
</button>

<!-- Modal -->
<div id="default-modal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
  <div class="relative p-4 w-full max-w-2xl max-h-full">
    <div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
      <%= simple_form_for Idea.new do |f| %>
        <div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
          <h3 class="text-xl font-semibold text-gray-900 dark:text-white">Add New Idea</h3>
          <button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-hide="default-modal">
            <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
              <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
            </svg>
            <span class="sr-only">Close modal</span>
          </button>
        </div>
        <div class="p-4 md:p-5 space-y-4">
          <%= f.input :description, input_html: { rows: 5, class: 'text-gray-800' } %>
          <%= f.input :author, input_html: { class: 'text-gray-800' } %>
        </div>
        <div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
          <%= f.submit 'Submit', class: 'text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800' %>                <button data-modal-hide="default-modal" type="button" class="text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-none dark:focus:ring-red-800">Cancel</button>
        </div>
      <% end %>
    </div>
  </div>
</div>

Let's say you fill out the form like this:

image.png

When a user clicks "Submit", a bunch of data is sent to the server. In your terminal window that is running the rails server, you will see something like this:

image.png

Notice how the information we filled out in the form is shown here:

"idea"=>{"description"=>"This is the beginning of a beautiful idea.", "author"=>"Mr. Authy"}

These are parameters being sent to the server. We can access these attributes like this:

params[:idea][:description] # returns "This is the beginning of a beautiful idea."
params[:idea][:author] # returns "Mr. Authy"

Routing Parameters

If we go to our terminal and type rails routes, you will see a list of routes (review this lesson{:target="_blank"} for more on routes). If you look at the URI pattern column, you will see that some have /:id(.:format) at the end of its URI. This :id is important. Rails sends this :id to the server as a parameter.

Let's look at an example of the edit action. When we ran rails routes, we see a line like this:

  Prefix Verb   URI Pattern               Controller#Action
edit_idea GET    /ideas/:id/edit(.:format) ideas#edit

Let's take a look at the URI Pattern. Notice the :id portion of /ideas/:id/edit(.:format). This :id represents an id that is passed in as a parameter in the URL.

For example, when a user makes a GET request to a URL like https://techbrain-ideator.herokuapp.com/ideas/1/edit, the edit action of the ideas controller is triggered. id is sent to the server as a parameter as well.

Overview

Let's take a look at the following code again:

def edit
  @idea = Idea.find(params[:id])
end

Now we know what this means. We are telling Rails to find the Idea with the id of params[:id], which is a value that is passed in as a parameter, and store it in @idea.

Now let's hop into edit.html.erb. Here we can actually use similar code that we have used before for creating new ideas. Make the file look like this:

<h1 class="text-3xl mb-5 font-bold">Revise Idea</h1>

<%= simple_form_for @idea, method: :patch do |f| %>
  <%= f.input :description, input_html: { rows: 5, class: 'text-gray-800' } %>
  <%= f.input :author, input_html: { class: 'text-gray-800' } %>
  <%= f.submit 'Submit', class: 'text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800 mt-3' %>
<% end %>

The only difference here is that on the first line of the simple form we are adding method: :patch. This piece of code indicates that we are performing a PATCH request. If we type rails routes in the terminal and look at the VERB column, we can see that it corresponds to a controller action. For PATCH, it corresponds to ideas#update. This means that when we submit this form, it will trigger the update method in the ideas controller.

Right now we don't have an update method, so let's add that in our ideas_controller.rb.

Under our edit method, add the following code:

def update
  @idea = Idea.find(params[:id])
  if @idea.update(idea_params)
    redirect_to root_path
  else
    redirect_to edit_idea_path(params[:id])
  end
end

Let's go through what this code is doing. We're first doing the same thing we did in the edit method: finding the idea we are working on using params[:id], and then storing that in @idea.

Then we are saying if @idea updates successfully, then redirect_to the root_path (the home page). If it doesn't update successfully, then redirect_to the edit page that we were just on so that you can enter the correct information.

Why do we need to check if the idea was updated successfully? In the next lesson, we'll talk about validations and get into why we need to do this.

Lesson list