DEV Community

Joshua Shane Doud Jr.
Joshua Shane Doud Jr.

Posted on

Sinatra/Active Record Full CRUD

Welcome and get ready to link your front-end to your back end using Sinatra with Active Record. In this blog I will be showing you how to use Sinatra and Active Record to access your Ruby based models and present this data to your front-end React application. To get started lets take a look at a simple GET request from our front-end server below:

  fetch("http://localhost:9292/animals")
  .then(res => res.json())
  .then(data => {
    setAnimals(data);
  },)
Enter fullscreen mode Exit fullscreen mode

Now this bit of code shows that we are asking our server for data using a GET request. After this data is received we are turning that data which is JSON into data that can be used by our front-end and then updating our state to that data.

How does this look on the back-end? How is this request being processed after it is sent to the server? Lets take a look at the code:

class ApplicationController < Sinatra::Base

  get '/games' do

  end

end
Enter fullscreen mode Exit fullscreen mode

This code above is the beginning of the server's job to receive the GET request. Now we must obtain all of the data needed by the request:

 get '/animals' do 
    animals = Animal.all 

  end
Enter fullscreen mode Exit fullscreen mode

This is where Active Record comes in handy. Using the method .all we can obtain all of the animals from the database. We are not done yet though we need to convert these animals to JSON. Luckily Active Record has a method for this as well .to_json.

 get '/animals' do 
    animals = Animal.all 
    animals.to_json
  end
Enter fullscreen mode Exit fullscreen mode

Yay! Now our React application can make a GET request for the "/animals" database; but wait we also want to set the content type headers for all of the responses. We do this by adding the following line: set :default_content_type, 'application/json'

class ApplicationController < Sinatra::Base
  set :default_content_type, 'application/json'

  get '/animals' do 
    animals = Animal.all 
    animals.to_json(include: :shelter) 
  end
end
Enter fullscreen mode Exit fullscreen mode

Now our ApplicationController inherits from the Sinatra::Base class and can send a response to a GET request with a default json content type for the headers.

We can modify this request using Active Record methods to control the data the server sends back as a response to the request.

We can only send the first 10 entries in our database and we can make sure to include the shelter that the animal has a relationship with:

  get '/animals' do 
    animals = Animal.all.limit(10) 
    animals.to_json(include: :shelter) 
  end
Enter fullscreen mode Exit fullscreen mode

Methods like this help us as developers to use our back-end to control server responses.

So we have successfully made a GET request and set up our server's response, but our application is going to require more than just readable data from our database. We would also like to create, update, and remove from our database. These options are known to developers as CRUD (create, read, update, delete) or our POST, GET, PATCH, and DELETE requests.

Lets start with our POST request using similar looking code. Here is our request from our React application:

fetch("http://localhost:9292/animals", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify(formData)
        })
        .then(res => res.json())
        .then(newAnimal => onAddAnimal(newAnimal))
Enter fullscreen mode Exit fullscreen mode

The beginning of our code is going to start off with similar syntax to our GET response but will be post instead.

class ApplicationController < Sinatra::Base
  set :default_content_type, 'application/json'

 post '/animals' do


  end
end
Enter fullscreen mode Exit fullscreen mode

Unlike our GET response we need to use an Active Record method .create to create an animal using the body of the request sent by the react application and add it to the database sending a response from the server with the added animal and its new id generated by the database. How does this look?

 post '/animals' do
    animal = Animal.create(
      name: params[:name],
      species: params[:species],
      breed: params[:breed],
      sex: params[:sex],
      age: params[:age],
      image: params[:image],
      shelter_id: params[:shelter_id]
    )
    animal.to_json
  end
Enter fullscreen mode Exit fullscreen mode

We added to our database!
This allows our react application to make a request sending over data to the server. The server then takes this data and using Sinatra and the params hash creates a new animal. Our create part of CRUD is complete. Our next two requests are going to be our update or PATCH request and our DELETE request. Here is the final result of all four requests in our controller file.

class ApplicationController < Sinatra::Base
  set :default_content_type, 'application/json'


  # Animal Controllers Full CRUD
  get '/animals' do 
    animals = Animal.all 
    animals.to_json(include: :shelter) 
  end

  get '/animals/:id' do
    animal = Animal.find(params[:id])
    animal.to_json(include: :shelter)
  end

  delete '/animals/:id' do
    animal = Animal.find(params[:id])
    animal.destroy
    animal.to_json
  end

  post '/animals' do
    animal = Animal.create(
      name: params[:name],
      species: params[:species],
      breed: params[:breed],
      sex: params[:sex],
      age: params[:age],
      image: params[:image],
      shelter_id: params[:shelter_id]
    )
    animal.to_json
  end

  patch '/animals/:id' do
    animal = Animal.find(params[:id])
    animal.update(
      name: params[:name],
      species: params[:species],
      breed: params[:breed],
      sex: params[:sex],
      age: params[:age],
      image: params[:image],
      shelter_id: params[:shelter_id]
    )
    animal.to_json
  end
end
Enter fullscreen mode Exit fullscreen mode

Thank you for going on this CRUD journey with me. Tune in next time!

Top comments (0)