The Free Jazz of Computer Languages
Published: 2021-08-05 16:53:03

For Flatiron School's Phase 4 Final Project, we created a project using Javascript to handle the views to a client, without ever refreshing a page. I'll use this blog post to detail some of the challenges I encountered and how I overcame them, in case it resonates with someone else who is learning frontend development. 
I'll make the music analogy, especially in contrast to making a full-stack site entirely on Rails: Javascript is really the free jazz of coding, whereas Ruby on Rails is the hardcore punk. Rails is rigid and has a pretty strict set of conventions that it makes you follow, and if you deviate, you've got to explicitly hard code it to do so- ie in punk, it's a rigid set of rules: predominantly power chords on guitar, root notes on the bass, fast 4/4 time on the drums. If you buck that convention too much in another direction, well, it no longer sounds like punk rock (the Clash notwithstanding- they are often labeled punk but covered so much sonic ground. Anyway...). Not to mention your aggro lead "singer" will start getting annoyed, ie Rails throwing you an error anytime your code falls out of line. In Javascript, there are very few guidelines! Declare your global variables and functions wherever! Invoking a function with an argument, when you didn't declare any parameters? Great! JS will try to run it. Declare a function to a variable name to pass it into another function as a callback to handle the data? Yeah! Anything goes! It's like improvisational jazz- it can be easy for a novice to get lost in the lack of form and inherent organization. What chord was I supposed to improvise over? A Cadd7dim9? So I can use the flatted 5th of the root note is "in scope"? (as a musician I'm not even entirely sure that's a real chord- power chords and root notes for me!).
Well this project was a fusion of both styles- with a Rails API handling my backend, and Javascript taking that data and displaying it client-side. Making a Rails API was nice review of Mod 3, plus it underscored why it is such a useful framework- I created my project in the command line and "scaffolded" my resources with each of their attributes (Team and Player in my case). Player would be a nested resource to Team, as a Player belongs_to a Team- rendering only the data I wanted in the teams_controller was the only major challenge here:
``` 
render json: teams, only: [:name, :logo_img, :players, :id], include: {players: {except: [:created_at, :updated_at]}}
 ``` 
I went on to make an entirely separate repo and file directory my project's frontend, where I would be coding my Javascript. Starting was simple enough- I put an event listener on the document, and when the DOM is loaded, I invoke a yet-to-written function called getTeam() (logical enough, I wanted the browser to display the available teams that I seeded into my backend).
getTeam() makes a fetch request to the API, and once the data is formatted correctly, runs a forEach(), taking in each Team object, and creating a new Team (using the ES6 object-oriented syntactic sugar) to display in the DOM.
```
function getTeam(){
    fetch('http://localhost:3000/api/teams')
    .then(r => r.json())
    .then(resp => {
        resp.forEach(team => {
            const t = new Team(team, modal)
            t.addToDom()
        })
    })
```
This is where getting into Object Orientation made sense. All the concerns of Team could be under one big class, so when 'new Team' is called from the fetch request, each one could be initialized with the constructor method that would correctly set each attribute. The addToDom() method of the Team class posed my next significant challenge: its purpose was actually access the appropriate HTML node and show the application user the data correctly. However I found that the function I was writing was starting to take up 30 lines of code and going supernova! I had it showing each team with it's logo on a div. Then when that logo gets clicked, an event listener would fire, making a fetch request to show the players associated to that particular team. Having an entirely separate fetch request in the same function seemed like it was in dire need of a refactor, since now this one function was responsible for two completely separate concerns. ```
    addToDom() {
        const teamOnDom = document.querySelector('#team-container')
        const teamDiv = document.createElement("div")
        teamDiv.classList.add("team")
        teamDiv.innerHTML += this.renderTeam()
        teamOnDom.appendChild(teamDiv)
        teamDiv.addEventListener('click', () => {
            this.modal.classList.remove("hide")
            this.renderPlayers()
        })
    }
```
I refactored that call to the API into its own function, renderPlayers(), after displaying the modal that would pop up and show the roster. 
Players were a nested resource of Team, should they have their own class handling their concerns? I opted against it, because I could call 'Team.players' in the Team class and have all of the info about each player easily accessible.
In order to hit the project requirements, I needed an additional fetch request to my backend with another CRUD functionality- I already had the 'read', and as my app is for managing player rosters, it made sense to be able to update information about each player. A PATCH request would do the trick. First I needed to figure out my endpoint, which would be each player by their ID in the URL. I had to pass the configuration object as a second argument, which would designate this fetch call as a PATCH request to update information about the targeted resource. 
```
updatePlayer(form, id) {
            fetch(`http://localhost:3000/api/teams/${this.id}/players/${id}`, {
                method: "PATCH",
                headers: {
                    "Content-Type": "application/json",
                    "accept": "application/json"},
                body: JSON.stringify( 
                    {
                        first_name: form[0].value,
                        last_name: form[1].value,
                        jersey_number: form[2].value,
                        primary_position: form[3].value,
                        handedness: form[4].value,
                        injured: form[5].value
                    }
                )
            })
                .then(r => r.json())
                .then(data => this.renderPlayers(data))
    } 
```The existing information about each player was already present in the Edit Form rendered to a user, but any information edited in that form was passed into the body of the configuration object to persist to the database. As an aside, I found that accounting for all the closed parentheses and curly brackets to be a huge headache in this! An object passed as an argument, with it's own embedded objects, and passing an object as the argument to a .stringify() serializer function. It took AT LEAST triple checking to understand why VS Code was still telling me there was a syntax error baked into my code!
Javascript overall is a more free-form language that challenges a developer to plan and structure their code before writing it, as otherwise it can quickly get confusing to keep track of. The key I think is to go into a project with an idea of the functionality in mind, and split those concerns into their own functions, and pass those functions to each other to handle the appropriate data.