Custom REST Actions in Rails 5

Steps

Step 1

There are 7 standard actions provided by resources declaration in the routes.rb.

resources :tasks

Step 2

The index page displays all the tasks. For completed tasks, define a completed method:

def completed
  @tasks = Task.where(complete: false)  
end

This finds all the completed tasks.

Step 3

Go to complete view in the browser http://localhost:3000/completed. It will not work. Delete this:

before_action :set_task, only: [:show, :edit, :update, :destroy]

Try again. The error is:

ActiveRecord::RecordNotFound in TasksController#show
Couldn't find Task with 'id'=completed

Step 4

Change the routes.rb to allow complete action for task resource.

get 'completed', to: 'tasks#completed', as: :completed_tasks

Step 5

$ rake routes | grep tasks

The installed routes are:

          tasks GET    /tasks(.:format)             tasks#index
                POST   /tasks(.:format)             tasks#create
       new_task GET    /tasks/new(.:format)         tasks#new
      edit_task GET    /tasks/:id/edit(.:format)    tasks#edit
           task GET    /tasks/:id(.:format)         tasks#show
                PATCH  /tasks/:id(.:format)         tasks#update
                PUT    /tasks/:id(.:format)         tasks#update
                DELETE /tasks/:id(.:format)         tasks#destroy
completed_tasks GET    /completed(.:format)         tasks#completed

Step 6

Go to completed view in the browser by browsing to http://localhost:3000/completed. In the log file, you can see that nothing was rendered.

Started GET "/completed" for ::1 at 2016-03-23 17:47:54 -0700
Processing by TasksController#completed as HTML
No template found for TasksController#completed, rendering head :no_content
  Task Load (0.1ms)  SELECT "tasks".* FROM "tasks" WHERE "tasks"."complete" = ?  [["complete", true]]
Completed 204 No Content in 20ms (ActiveRecord: 0.1ms)

Step 7

Define completed.html.erb:

<h1>Completed Tasks</h1>

<table>
  <thead>
    <tr>
      <th></th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <% for task in @tasks %>
        <div class='task'>
            <strong> <%= task.name %> </strong>
        </div>
        <%= link_to 'Edit', edit_task_path(task) %>
      <% end %>
     </tr>       
  </tbody>
</table>

Step 8

Add a link to completed tasks in the index page.

<%= link_to "Completed Tasks", completed_tasks_path %>

Step 9

Implement the complete action:

def complete
  @task = Task.find(params[:id])  
  @task.update_attribute(:complete, true)
  flash[:notice] = 'marked task as complete'

  redirect_to completed_tasks_path
end

Step 10

Define the routes for marking a task as complete.

put 'complete/:id', to: 'tasks#complete', as: :complete_task

Step 11

Add the link to mark a task as complete in index page:

<%= link_to 'Mark as Complete', complete_task_path(task), method: :put %>

Step 12

Browse to http://localhost:3000/tasks. Click on 'Mark as Complete' to mark a task as complete. It shows up in completed tasks page

Summary

In this article, you learned how to use custom REST actions in Rails 5.


Related Articles


Software Compatibility Best Practices

I spoke to some of the most talented and experienced software developers. I have created a guide that is filled with valuable insights and actionable ideas to boost developer productivity.

You will gain a better understanding of what's working well for other developers and how they address the software compatibility problems.

Get the Guide Now