August 11, 2019
We had to:
Render at least 1 index page via JS and an Active Model Serialization (AMS) JSON backend.
Render at least 1 show page via JS and an AMS JSON backend.
Dynamically render on the page at least one serialized ‘has_many’ relationship through JSON using JS.
Render a form for creating a resource that is submitted dynamically and displayed through JS and JSON without a page refresh.
I started this project a little early - unlike the last several - and having the full 2+ weeks made a big difference. Several of the requirements were straightforward and required only a couple of lines of code, but I struggled with numbers 1 and 5, and needed help with 5 and 4.
I was able to take advantage of the office hours this time around - working full time while going through the Flatiron program has caused scheduling issues in the past - and it was a huge help being able to talk through what I was looking at and trying to do.
JSON and AMS
For this project I chose to work only with my “places” table since I was struggling with the concepts initially and wanted to keep everything as simple as possible.
For the Index, Show, and Create pages, I need to add a block of code which let the pages respond to html requests or requests for JSON. This only required 4 lines of code in each action, and now if you go to /page.json, you’ll see the JSON in lieu of the html. JSON is a way of organizing information in a way that is easy for humans to read and write but keeps the data size small enough for it to be easily transferable and able to be parsed.
Adding AMS was also simple - it required adding the gem ‘active_model_serializers’ too the Gemfile and running “rails g [model name] serializer”. This creates a “serializers” folder within the “app” folder and the files look very similar to the model files - they have a class, attributes, relationships, and end. You can specify exactly what attributes you want to be available to be turned into JSON, and you can connect your models together via “has_many” and “belongs_to.” In my app, I specified all of the attributes available for a place and that it has many reviews. I also created a “review” serializer, and specified that it belongs to “place.”
The real meat of the project is inside the places.js file. At the beginning of the file, I use a jQuery function which waits until the document object model (DOM) is ready before firing the rest of the code in the file. This waits until the html has been loaded and parsed before manipulating it with JS, which keeps the JS from slowing down the response time by trying to manipulate HTML which hasn’t been loaded yet, as HTML loads top to bottom. (jQuery is a library which simplifies the syntax needed for the navigation and manipulation of the DOM.)
Inside the initialization function, two functions are referenced: one to handle when the review link is clicked on the places#show page, and one to listen for one a place is created and handle things from there.
The following several functions exist to allow a separation of concerns - each function handles one primary task, allowing for easier debugging by making it easier to target where an error might be coming from and to require less editing when an error is found.
Using “#review_link” and “.click”, we wait for the user to click on the link with the id of “review_link” and following this, it executes the getReviews function.
The getReviews function takes in the event (the click) and prevents the default action and then tells the page what to do instead. In this case, we ask for the reviews belonging to the place in JSON format, and then display them on the page. The displayReviews function iterates through each review and formats them for the page by putting them in HTML list item tags. All of this together allows us to show the user the existing review content without requiring the page to refresh or requiring them to navigate to a new page.
Similarly, when a place is created, we have an event listener to prevent the default action when the form is submitted, take the information that is created as JSON, then inserting it into the DOM after formatting it with HTML. For this we utilize a class for “Place” which contains a constructor function and a function which inserts the data into HTML.
The result of running the code isn’t particularly visually attractive - I didn’t add any CSS or do much other than render the straight HTML. In the past, this would have driven me insane because I want to do all the things. My boyfriend - a career software engineer - has repeatedly reminded me not to let the perfect be the enemy of the good. Fulfill the requirements, get it working, and then worry about making additions. In this instance, doing what I could after work and on the weekends, I’m still happy with what I’ve done because I was able to meet the requirements without being stressed at the last minute and I learned a lot more than I knew when I started.
One of the things I like about being a developer is that you are basically committing to be a lifetime student. When I was younger, my endless curiosity led my mom to tell me more than once that I couldn’t “be a professional student” but it turns out, I can. I don’t know everything right now, but I’m learning and in the future I’ll be at a point where I can fulfill the basic requirements and make the result pretty. Just keep swimming.