DEV Community

Cover image for Setting up a Basic CRUD Rails API
Daniel Troyano
Daniel Troyano

Posted on


Setting up a Basic CRUD Rails API

So you've run rails new and you've got a brand new blank Rails application waiting for you. Let's turn it into a CRUD API that interacts with a list of dogs.

First things first, let's get our dogs table set up in the database. Rails uses Active Record, an ORM, to abstract your calls to the database. To interact with our schemas we're going to need to create a migration.

Migrations are great because you can just write Ruby code to interact with the database and don't have to worry about specific database commands. But they are also great for version control and making sure that your database is set up the same way in every environment.

So let's run rails generate model Dog, which can be shortened to rails g model Dog. Models should be named in Pascal case and also be singular. This is going to generate a dog model and a create_dogs migration, which will have a date time code attached to it as well. It's very important for Rails to know the order to run the migrations in, so it always prepends a timestamp.

Open up your brand new migration and let's give our dogs some characteristics.

class CreateDogs < ActiveRecord::Migration[6.0]
  def change
    create_table :dogs do |t|
      t.string :name, not_null: false
      t.integer :age, not_null: false
      t.boolean :good, default: true

When we run this migration it will run its change method. Which will create the dogs table and then fill it with the columns you tell it. In this case we want a name, which is a string and can't be null, an age, which is an integer and also can't be null, and a column to track if the dog is good, which is a boolean that of course defaults to true.

I have also left in the timestamps so that Rails will automatically create created_at and updated_at columns and keep them updated.

Now run rails db:migrate and you should see a create_table command is run. Hooray! You have created a table to track your dogs.

Let's pop over and open up our app/models/dog.rb that our generator created for us. Notice that it's empty. That's fine. This is where we would put in any validations, associations with other pieces of data, or any computed logic that has to do with this model.

We don't need to make any changes to it though, but it's good to know about.

Now let's make a controller.

Run rails g controller Dogs, controllers should also be in Pascal case but they should be plural. So now you have a app/views/dogs folder and you have a app/controllers/dogs_controller.rb. Before we set up your controller, let's set up our routes to handle our intended actions.

Open up your config/routes.rb, it should have basically nothing in it. And we want to be able to create a dog, see all the dogs, see a specific dog, update a dog, and delete a dog. So let's add a line that lets us do that.

Rails.application.routes.draw do
  resources :dogs, only: [:create, :index, :update, :destroy]

Resources tells Rails that we want to be able to interact with the given resource, so it should make some standard RESTful routes for us. If you leave it at that Rails will set up a couple extra routes that would handle forms for adding a new dog or updating a dog and a route for showing a single dog, but since our front end is going to handle that, we specify we only want the routes listed here.

Now if you run rails routes you'll see all the routes that Rails creates for you. There's probably a bunch about mailboxes, don't worry about them, these are ones we're going to focus on.

Prefix Verb    URI Pattern              Controller#Action
dogs  GET      /dogs(.:format)          dogs#index
      POST     /dogs(.:format)          dogs#create
dog   PATCH    /dogs/:id(.:format)      dogs#update
      PUT      /dogs/:id(.:format)      dogs#update
      DELETE   /dogs/:id(.:format)      dogs#destroy

You should be able to recognize those prefix verbs as HTTP Verbs. They map to a URI, which is the actual route that you are going to be hitting, notice how plenty of them also get an id. And then we have controller actions, these are the methods that Rails will use to dictate the logic when you hit one of those routes.

So let's open up our app/controllers/dogs_controller.rb and start adding methods.

Let's start with our index method, which will show all our dogs.

class DogsController < ApplicationController
  def index
    render json: Dog.all

The index method is going to find all the dogs, and we want to specify that it returns json. The Dog we're referring to here is the model which inherits from ApplicationRecord, so we can use Active Record to interact with our database.

Currently, there's no dogs in our database, so let's create a method that allows us to add some!

def create
  dog = Dog.create(dog_params)
  render json: dog


def dog_params
  params.require(:dog).permit(:name, :age)

In the create method we create a new Dog with the params we were given. Notice we do that by calling a second, private, method though. Rails protects you against malicious users by making sure you use Strong Parameters. This prevents users from passing unintended things into your database. But it also means you have to tell Rails what you're expecting to get. Which we do in the method dog_params.

Now, let's add our update method.

def update
  dog = Dog.find(params[:id])
  render json: dog

Here we find the current dog by id and the update its attributes with the passed in parameters. Even if you aren't super familiar with Ruby, part of what I love about it is how readable that code is.

And finally to fill out our CRUD application let's add a destroy method.

def destroy

Once again, I imagine this is very clear. We destroy a dog based on the given id.

Now before you run rails s and check out your API we need to add one line to our app/controllers/application_controller.rb that our dogs controller inherits from. See, Rails is once again protecting us by expecting us to provide an authenticity token along with any request that alters the data. But since we're just building this for fun, we don't need to worry about that.

So open up the application controller and add one line, so that it looks like this.

class ApplicationController < ActionController::Base

protect_from_forgery is the same as writing protect_from_forgery with: :null_session, which just allows the request through, but removes the session. This isn't secure at all so don't do this in the real world unless you have a really good reason, but it's fine for this.

Now you can run rails s and hit the routes you set up. Although you'll probably need something like Postman to get to most of them. But don't worry, we'll be hitting them in a sec with our React.js front end.

Top comments (0)