JavaBurger - Using Rails as an API
Published: 2021-02-21 21:21:11

###Rails as an API
  To start my JavaBurger app I needed to get an API going.  This was a bit new and familiar at the same time as I had used an API for a previous project, but never created my own.  Rails lets you start the process by using the --api command when creating a new rails app `rails new [app_name] --api`.  Once created and after setting up the models, relationships, and some seed data I wanted I was basically half way there.  Considering the power of an API it's pretty cool to think now I'm building my own.

###First FETCH of the App
  To begin the app needed to get the data from my API using `fetch`.  It first makes the request to the URL provided in this case it's a localhost.  And *then* you have to tell it what to do with the response or *promise*.  The response comes back as a JavaScript object and then gets converted back to json format, and with our new json data we can now pass that info to the JavaScript and use it to create new objects.
```static fetchBurgers(){      fetch('http://[::1]:3000/burgers')
        .then(resp => resp.json())
        .then(Burger.makeBurgers)
    }```
###Classes in JavaScript
  As mentioned we are creating objects in JavaScript.  This is similar to a Ruby object ever since ES2015 was added we can use labels like `class [ClassName] {...bunch of code}`, to create a JavaScript class and write object oriented code.  To create new objects you have to setup what's called the *constructor*, just like an *initializer* in Ruby.  You assign the values that you want each object to have.
```constructor(id, name) {
        this.name = name
        this.id = id
        this.tag = document.createElement('p')
        Burger.all.push(this)
    }```
By setting up a constant equal to an empty array, `static all = []`, you can push all your new objects to it and call it anytime you need to *filter* to get specific ones back, `Burger.all.filter(...filterCode)`.  Your constant is going to be called on the class you made so the reference is not *const* it changes to *static*.  Any functions that you will call outside the class will have the same setup, and you will not have to say *function* in front of your code anymore.  But, as mentioned those without static will not be accessible outside of the class.

###Changing Database Info
In order to send info the database to update it the *fetch* is going to be slightly different. First the thing being sent has to be configured.
```const configObj = {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json'
            },
            body: JSON.stringify(ing)
        }```
Using this code inside of the function called to update will setup the object data so that it is readable for the API and turn it into the same type that you receive form the API.  Next you send the data, 
```fetch(`http://[::1]:3000/ingredients/${ing.id}`, configObj)
        .then(r => r.json())
        .then(json => {
            if(json.error){
                alert(json.error)
                }else{
                    burgerForm.innerHTML = ""
                }
            })```
The *fetch* is sent to the API with the configured object.  In the code above I setup to check if the data was saved by looking for error.  On the backend the code was:
```def update
        ing = Ingredient.find(params[:id])
        if ing.update(ing_params)
            render json: IngredientSerializer.new(ing)
        else
            render json: {error: 'could not save'}
        end
    end```
If the new ingredient was saved the render the JSON back if not then the JSON would be an error hash.  And on the frontend if there was a key of error then the alert would pop up saying "could not be saved", else it would just put the new data on the DOM.

###Conclusion
With a Ruby on Rails backend setup as an API you can create a fully JavaScript frontend that talks to you stored data.  Not only retrieve or *fetch* that data but also create new data.  All of the above was done on a single page app, no new routes were used to make changes only JavaScript.