Setting up a Basic CRUD Rails API
Tags: rails, ruby, beginners
Published: 2020-09-26 15:24:56

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.
```ruby
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
      t.timestamps
    end
  end
end
```
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.
```ruby
Rails.application.routes.draw do
  resources :dogs, only: [:create, :index, :update, :destroy]
end
```
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.
```ruby
class DogsController < ApplicationController
  def index
    render json: Dog.all
  end
end
```
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!
```ruby
def create
  dog = Dog.create(dog_params)
  render json: dog
end

private 

def dog_params
  params.require(:dog).permit(:name, :age)
end
```
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.
```ruby
def update
  dog = Dog.find(params[:id])
  dog.update_attributes(dog_params)
  render json: dog
end
```
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.
```ruby
def destroy
  Dog.destroy(params[:id])
end
```
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.
```ruby
class ApplicationController < ActionController::Base
  protect_from_forgery
end
```
`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.