DEV Community

Swislok-Dev
Swislok-Dev

Posted on

Rails and JavaScript

Guitar Picks

I wrote a simple single page application (SPA) that utilizes HTML, CSS, and JavaScript for the front-end and a Ruby on Rails acting as an API server. For this project I went with the concept of a photo sharing site for guitarists which I aptly named Guitar Picks.

The app works quite simply by requesting a username to get started. Once a valid username has been accepted, the main content of the page is written using JavaScript to show the current list of guitars through a series of function calls, one of which is a request to the server to grab the Guitars table and which is render to JSON.

Rendering JSON data

The following snippet is a get request from the front-end to the back-end and is targeting this.api followed by the route to populate data for the Guitar class constructor.

getGuitars = () => {
    return fetch(this.api + "/guitars")
    .then(response => response.json())
  }
Enter fullscreen mode Exit fullscreen mode

This function is called when a valid username is accepted and processes the api call, setting an empty array for Guitar.all, then finishing by sending that infomation one-by-one to a render method to produce the output on screen, all without a page refresh.

static getGuitars = () => {
    api.getGuitars().then(guitars => {
      Guitar.all = []
      guitars.forEach(guitar => new Guitar(guitar))
      this.renderGuitars()
    })
  }
Enter fullscreen mode Exit fullscreen mode

Front-end troubles

A few issues that I faced with this concept was how to render updated information such as when a user deletes a post of a guitar. The guitar is stored in the array Guitar.all, but without updating this array, would produce the guitar until the page was refreshed or what I have done (per requirement of this project) since this is a SPA and page refreshes are not allowed. By calling Guitar.getGuitars() keeps the JSON data from the back-end in sync with the front-end without the need for a page refresh.

I learned quickly that any script that is written needs to be referenced in the HTML using a <script> tag in order to be read. I faced some headaches not grasping this concept at the start as with Rails was not an issues as all the files where being read as they were needed. That's the first place to look to trouble-shoot code not running and verifying the the src is targeting the correct location of said script file.

Rails back-end setup

Setting up a rails server in this manner was fairly straight forward. Starting with rails new server_name --api. With the --api flag this tells Rails to only generate files which are dependent to serving data rather than taking advantage of views and erb files that would normally do the rendering of on-screen information. Controllers are similar to writing Ruby code with the change-off of instead of using a redirect, one would write render json:. A view would grab the instance variable from the controller and do something with it while the render json: would do just that. By going to the route in a browser, with the Rails server running, http://localhost:3000/guitars will only produce a JSON object with the data stored in the current database.

def show
    guitar = Guitar.find_by(id: params[:id])
    if guitar
      render json: guitar
    else
      render json: { message: "No guitars found" }
    end
  end
Enter fullscreen mode Exit fullscreen mode

Add in an if else block and if a guitar id does not exist will produce a message to state that there is no information stored at the location.

Rails Models

As for models using the --api flag, work just the same as one would expect if any validations or associations are given.

Serializers

Using a serializer for this type of project seems almost necessary in order to keep the app DRY (Do not Repeat Yourself). The serializer is used to keep the information that is produced in the JSON object formalized and shows reduced information if required. It can also be used to add custom serialized information to bring information in from an associated object from another Class.

class GuitarSerializer < ActiveModel::Serializer
  attributes :id, :style, :brand, :model, :image_url, :username, :created_at

  def username 
    self.object.user.username
  end

  def created_at
    self.object.created_at.strftime("%b-%d-%Y")
  end
end
Enter fullscreen mode Exit fullscreen mode

The Guitar class had a belongs_to relationship to User, but did not have an attribute of username. By creating a custom method to tell the serializer to find the username of the user object associated with it. Another thing learned from this project was date formatting in the serializer worked better if formatted for the data here rather than the whole object. This allows the front-end code to grab the date as-is and be printed directly to the DOM.

The serialized data can then be used in functions where applicable and destructured for ease of use in render functions.

Discussion (0)