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())
}
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()
})
}
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
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
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.
Top comments (0)