Creating Associated Objects in Single Page Applications

A few months ago, I had the idea to build a simple game that functions something like this.

An early, rough concept for a flash card/quick match game

The game mechanics changed in the early stages of building it in Ruby on Rails (Rails) and Javascript. One feature, I knew I wanted, was to be able to add a player’s name and their score to the leaderboard at the end of a game.

Since a User has_many Games I wanted to be able to create a new Game instance at the same time as a User instance. If a User with the given name already exists, create the Game and associate it with that User.

Oh and this had to happen without reloading the page.

Was it possible?


At first, I was overthinking how it might work on the frontend. Then, a classmate pointed out, that the creation of the User and Game could be handled on the backend, since the two were associated.

For this to happen, I need two pieces of data

  • The player’s name from the form input
  • And their score

I could query the DOM for the input field with this.nameInput = document.querySelector("#name") and access it’s value with .value. The score was being rendered on the frontend so I could access it in a similar fashion.

const body = {
      score: this.score.innerText,
      name: this.nameInput.value,

Formatted as an object, I could pass it into the createGame() fetch request in GamesAdapters.js.

  createGame(body) {
    return fetch(this.baseURL, {
      method: 'POST',
      headers: {
         'content-type': 'application/json'
      body: JSON.stringify(body)
    .then(res => res.json())

Did I mention the page shouldn’t reload either?

Luckily, that could be solved by including e.preventDefault() within the createGame() function that is triggered by the form submission button.

createGame(e) {
    console.log("Saving the game...")

    const body = {
      score: this.score.innerText,
      name: this.nameInput.value,



Rendering the New Score

The POST fetch() request created a new record and returns the record object, which looks something like this.

#<Game id: 85, user_id: 1, score: 37, created_at: "2020-02-24 00:25:42", updated_at: "2020-02-24 00:25:42">

Oh no.

I see a user_id. Within Rails, it’s possible to get a Users name from their ID, but is there a way to access it on the front end without a page reload? There is! Since we were already asking a player to input their name into a field, on the frontend, we could use that, instead of querying the database.

There is, but it would require a page reload, which we want to avoid for this project. But, we can fake it on the UI by pulling the name from the input field and displaying that. Let’s add a .then statement to the end of createGame(e) to handle this.

createGame(e) {
    console.log("Saving the game...")


    const body = {
      score: this.score.innerText,
      name: this.nameInput.value,


    .then(game => {
      let gameObject = `<li>${game.score} - ${this.nameInput.value}</li>`
      this.leaderboard.innerHTML += gameObject
      this.nameInput.value = ""


Our leaderboard, now looks something like this

A 3rd player and their score has been added to the leaderboard

If we were to refresh/reload the page, visually, we would not see anything different. This is an example of an optimistic user interface. We’re anticipating that the data is successfully written to the server and are responding right away by displaying the data. We’ll also clear out the input field when we’re done, to mimic what would happen if there were a page refresh.

Singular or Plural? A Cheatsheet for Ruby on Rails Generators

Ruby on Rails (Rails) is good at doing the manual work for you. With one line, Rails can create the model, controller and view files associated with your application. The downside of using rails generate or its shortcut rails g is that small mistakes like typos are amplified. If Rails is expecting user, and you mistakenly typed users it could cause functionality errors. 

This cheat sheet will help to avoid those conflicts.

If you are comfortable working with Rails, Model–view–controller (MVC) architecture rails generate, this post is for you.

RoutesNoYesresources :users, :products
Migrations / Table NameNoYes001_create_users.rb
Seed DataNoYesseeds.rb


unsplash-logoKumiko SHIMIZU

Using .inject to Find the Most Popular Item in a Has_Many, Through Relationship

While building my mock, Central Perk, point of sale (POS) application, I had an idea. Is there a way to highlight the most popular menu item?

On a small scale, it would work like this:

  • Get each order
  • List the menu items from each order
  • Count how many times each menu item is ordered

In the real world, manually counting items makes sense.

What about when model associations are involved?

Model associations can add complexity, but they also do a lot of the work for us. This post will outline how to work has many through relationships to find the most common item in your database.

Model Associations

Before we dive into making our most_popular method, let’s take a look at how our models are structured. In the Central Perk scenario, an order has_many menu items through order items. 

This means that given a specific order, we can call and return the menu item objects (a collection) associated with that order.

For example:


This would return the following collection:

#<ActiveRecord::Associations::CollectionProxy [#<MenuItem id: 2, name: "Caffè mocha", description: "Espresso, chocolate and steamed milk topped with c...", price: 2.5, created_at: "2019-12-15 04:09:49", updated_at: "2019-12-15 04:09:49">, #<MenuItem id: 4, name: "Matcha Green Tea Latte", description: "Matcha tea steeped in steamed milk and lightly swe...", price: 3.5, created_at: "2019-12-15 04:09:49", updated_at: "2019-12-23 02:29:01">]>

There’s a lot of information in my menu item model, so let’s simplify the data we will be working with.

Menu Items



IDMenu Items
1“coffee”, “scone”
2“mocha”, “puppuchino”
3“espresso”, “scone”, “puppuchino”
4“mocha”, “puppuchino”
5“coffee”, “puppuccino”

Getting the Most Popular Menu Item

Get all menu items from all orders

The first thing we need to do is to collect all the menu items from all orders. Knowing that calling .menu_item on one order returns the menu items for that order, we can iterate over all orders and add the menu items to an array.

all_items = []
Order.all.each do |order|
all_items << order.menu_items

Flatten the array and return it

Each time .menu_items is called on an order, it returns an array. Those arrays are pushed into the all_items array, which ends up looking like this:

all_items = [["coffee","scone"],["mocha","puppuccino"],["espresso","scone","puppuccino"],["mocha","puppuccino"],["coffee","puppuccino"]]

To make the following steps easier, let’s flatten the array so that each item is in its own place within the array.

// ["coffee","scone","mocha","puppuccino","espresso","scone","puppuccino","mocha","puppuccino","coffee","puppuccino"]

Count the items

This is where a lot of the wow behind Ruby on Rails happens. At the end of this step, we’ll have a hash that looks something like this. 

hash = {

The hash has a key for each menu item. The value for each key is the number of times that menu item appears in the all_items array. 

Let’s break down how we get there. 

First, we’ll call the .inject method on the all_items array. The .inject method is a powerful, if not mysterious method. It accepts a block statement and two variables. The first variable is the memo, which is what holds all the items that will eventually pass through the block. The second is an element from the object that .inject is called on. 

Here’s what it looks like.

all_items.inject( { 
|memo, item| 
memo[item] += 1; 


In our case, the memo is, an empty hash where the default value for each key is 0. And an item is a menu item from the all_items array. As each item comes into the block, it is set as a key within the hash. Remember, adding a new key to a hash can be done like this:

hash[key] = value

And calling a value, by its key looks like this:

// value

If a menu item (a key) does not already exist within the hash, it is created and 1 is added to the default value of 0. The next time that item/key is passed into the block, it value is reassigned to its current value plus 1. When all items have been injected in the block, the hash is returned. It’s tallying!

Let’s look at how the hash changes given the following list of items: 

all_items = "coffee","puppuccino","puppuccino"
hash =

// When "coffee" is passed into the block
// { “coffee”=>1 }

// When "puppuccino" is first passed into the block 
// { “coffee”=>1, “puppuccino”=>1, }

// When "puppuccino" is passed into the block a second time
// { “coffee”=>1, “puppuccino”=>2, }

Sort the hash

Since I am trying to find the most popular item on the menu, I want to put the hash values in order from highest to lowest. We can do that by calling the .sort_by method on our hash.

hash.sort_by{|key,value| value}

Our hash, that originally looked like this:

{“coffee”=>2, “scone”=>2, “mocha”=>2, “puppuccino”=>4, “espresso”=>1} 

Now looks like this. 

[["espresso", 1], ["coffee", 2], ["scone", 2], ["mocha", 2], ["puppuccino", 4]]

Wait. Now it’s an array! And the values are in order from smallest to largest. How can we fix that?

To change the order, we can use the .reserve method or change value from within the .sort_by block to -value

hash.sort_by{|key,value| -value}
// [["puppuccino", 4], ["coffee", 2], ["scone", 2], ["mocha", 2], ["espresso", 1]]

We’re getting close! The most popular item is right there in the nested array. A hash is a better format for data like this, so let’s add .to_h to convert this array back into a hash. Our method now looks like this. 

hash.sort_by{|key,value| -value}.to_h

Which gives us our sorted hash:


Getting the most popular item

We’re so close!

Within our sorted hash, the first key/value pair has the information we need. Let’s access it with the .first method.

most_popular_item = sorted_hash.first
// ["puppuccino", 4]

Cool! Puppuccino, appears four times, making it the most popular menu item in our sample of orders.

Putting it together

If we take everything we worked with and put it together, it looks like this within our Order model.

Now that we have the most popular item, there is a lot we can do with it. For example, we can:

puppuccino = MenuItem.find_by(name: most_popular_item[0])
// <MenuItem id: 5, name: "puppuccino", description: "Whipped cream in a small cup for your favorite pooch.">

Print out a statement:

puts "#{}, is the most popular item at Central Perk!"

Or, tagging it in our interface to bring attention to it.

Puppuccino & “Popular Item!” tag

We can even update our most_popular method to return the top three most popular items. The possibilities are endless.

Debugging Has Many, Through Relationships in Ruby on Rails

Working with associations was the most difficult part of building Central Perk, my Ruby on Rails application. has_many and belongs_to relationships made sense, but the addition to many-to-many—has_many through—relationships are where it got weird. I ran into several issues while building my app and here’s how I solved them.

For my app, I planned on three models. Users (baristas), orders and menu items (products). The relationship would like this:

Sketch outlining the User <–| Order |–> Item relationship

With those models, programmatically, that I wanted to be able to do the following:

  • Create a new order and automatically associate it with a user. shannon.orders.create
  • Be able to see all orders that belong to a user. shannon.orders
  • See all menu_items (products) in a specific order. order.menu_items

Everything with setting up my models seemed to be working fine up until the last part. Currently, an Order with an attribute of :menu_items could only have one value. Meaning, just one MenuItem per Order. Can you imagine if you had to get back in line and start a new order for each item you wanted to buy at a coffee shop? This is where a has_many through relationship came in.

has_many through

I knew that order.menu_items needed to be an array. To solve for this, I needed a fourth model, OrderItem.

OrderItem would be a join table, with foreign keys to the Order and MenuItems models. I thought of each OrderItem record has a transaction instance, representing one Order and one MenuItem at a time. An Order would essentially be a collection of all OrderItem records with the same :order_id. I was a step closer to figuring out what I needed.


At first, an OrderItem model made sense. Until, it didn’t.

Would I need to call order.order_items.menu_items to see all the products in that order? My app had a User model too. How do you build a has_many through a relationship when there are more than three models?

In reality, has_many through only works with three models. But, through other associations, it extends the functionality of those models. If I wanted to know how many MenuItems were in the first order, created by a specific user I could call something like this: user.orders.first.menu_items.count.

Visually, I thought of the relationships between the four models as looking like this:

Visualization of the has_many through relationship of User, Order (which containers OrderItems) and Menu Items.

This was making sense! I would not need to reference OrderItems directly. Active Record does that work for me. Since an Order has many OrderItems, referencing just the Order would give me access to MenuItems. My updated models now looked like this:


With the associations complete, I needed a form to create the Order object. At first, everything seemed to be working. But after looking closer at the console, I realized the transaction was getting rolled back and Order was not saving to the database.

I noticed the :menu_items_id key was listed in my strong params, but I was getting a :menu_items_ids is not permitted error.

To try and resolve this, I worked in the console, testing things out, bit by bit until I could pinpoint where I was getting stuck. In the console, I could successfully do the following.

  • Create an order. order = Order.create(user_id: 1, name_for_pickup: "Rachel", menu_item_ids: [1,2,3])
  • View the value of menu_items. order.menu_items # [1,2,3]
  • Add an item to an order. order.menu_items << item
  • Save the order.

Then it hit me.

Ruby was right in not permitting the menu_item_ids param. I thought I just needed to create an order. Instead, I needed to create an order, find the menu items by id (menu_items_id, which was the unpermitted params) and shovel them into the array. I updated my create order method.

And it worked!

In summary, if you are running into issues with objects relationships, try the following:

  • Verify that the params are correct. Typos can instantly cause object creation to fail. Pluralization like menu_item_id vs menu_item_ids are also something to look out for. All params are strings, which may cause downstream effects if you are expecting an integer or boolean.
  • All model attributes are listed in strong params. Strong params help to prevent users from injecting harmful data into your database via the form. If strong params lists only :name, :email and :password can be submitted in a :user hash, the transaction will fail (and not write to your database, yay!) if an attribute of :not_a_hacker was within your params.
  • Use .create! instead of .create when testing. create! will give more information into what validations may be causing errors. For example, in my app, an Order must have as User (barista) id associated with it. Running Order.create() in the console would not tell me much, but running Order.create!() would print out an error like A User must exist.
  • Append .valid? to objects. A object may be updating. But, is it saving properly to the database? For example, if order referenced Order.create() (an empty object, which will not validate because there is no :user_id), adding .valid? will return false.

All in all, building Central Perk was the most difficult and frustrating project to date. However, I learned a lot about associations, forms, params and creating and overall DRY application. I am more confident in my debugging skills and look forward to improving what I have built so far.

Building a Wine Journal Application with Sinatra

I feel good going into project mode for the Sinatra application.

With my Burger Finder app under my belt, I know what worked, what to expect and what did not work for me last time. I wanted to approach this project with a plan so that I could work efficiently.

I keep a running list of ideas. One that I had been wanting to build for years was a digital wine journal. I have a bad habit of not writing down or taking pictures of wines that I tried and liked. The Sinatra app requires a MVC model, with CRUD commands, so it sounded like a good fit.


I went into detail on planning with my CLI application and followed the same principals in building Wine Journal. Project week was actually two weeks, so I took the first to plan and the second to code. During the first week, I finished any existing labs and revisited new concepts until I was comfortable with them.

I wrote user stories to help me think about the user and how I wanted them to navigate the app. These two were the most important to me:

As a user, I want to see a list of wine bottles that I have tried and added to my collection

As a project maintainer, I want user information to be secure

Writing user stories helped me to think about which RESTful routes I would need, how to structure the /views folder and what methods I would need to achieve what I envisioned for the app.

Sketch of the proposed flow, view and routes for a logged it or logged out user
Sketch of the proposed flow, view and routes for a user.

For Wine Journal, I wrote out the bulk of my application in pseudocode. Pseudocode for Pros explains that by putting time upfront to pseudocode, it saves time later when it comes to writing the code.

# Pseudocode for creating a new bottle object

  • if not logged in
    • redirect to /index
  • else (if they are logged in)
    • require name only
    • check for blank fields
    • create new wine bottle object
    • save to the database
    • associate user with the wine bottle they created
    • wine bottle shows in their collection
    • redirect to /bottles/id
  • end

Looking back, although my pseudocode did not account for everything, it covered at least 80% of what I needed to build.

Building the MVP

The main goals of the Wine Journal were the following:

  1. Have at least 2 models, 1 has_many and 1 belongs_to relationship
  2. Have user accounts where a user can perform CRUD operations only on objects that belongs_to them
  3. Use RESTful routing
  4. Enable user sessions

I met the first requirement by having a User and a Bottle model. A User could have many (wine) bottles in their collection. And a Bottle, a specific entry of a wine bottle, belongs to a User.

For the second requirement, I set up a /signup route. The view included a form with inputs for a name, email address and password. On submission, if none of the inputs are blank, a new User is created, they are logged in and directed to the welcome page.

Wine Journal Signup Form
Signup form for the wine journal app

Signup method checks for duplication accounts and empty input fields

Once logged in, a user would only be able to view, edit or delete bottles in their collection. I handled this in two ways. First, when navigating, a method would check to see if someone was logged in. If they were, then it would check to see if they had permission to view the page.

Get /bottles route checked to see if there is a logged in user. If they are logged in, bottles from their collection are show in the erb view.

Second, as a fail-safe, when a bottle was being edited or deleted, the method would double check that the id of the current user matched the foreign key (user_id column) of the bottle. If everything was truthy, the patch or delete request would go through. If there was a failure, they are redirected to the /login page.

Patch method checked that the current user has permission to edit the current bottle

Enabling sessions allowed me to check if a user was logged in by assigning their user id to session[:user_id]. When navigating to the /logout route, the session has is cleared and the user is directed to the / route.

Using RESTful routes, get  post requests and forms was difficult. I kept getting the routes wrong—did I need patch or post if I was using form inputs to create an object. But, I took it slow and got comfortable with the concepts. I started with basic routes, get routes like  /signup and /bottles before creating the patch and delete routes. I almost forgot to include use Rack::MethodOverride in which allows the Sinatra Middleware to send patch request. Oddly, post was working in place of patch but there may have been long-term effects.

I avoided working on sessions. Even though this app did not have real user data or API keys, I wanted to keep it as secure as possible. I had the idea to use environmental variables to reference the session secret word, but did not know how to do it. I saw some references to hiding API keys with Javascript or Rails, but not within the context of my Sinatra app.

I learned about the dotenv gem, worked without Rails and seemed to be the solution I was looking for. After installing the gem, creating a .env file and adding it to a .gitignore secret keys could be added to .env and referenced in the application.

For example, instead of set :session_secret, "secret" in the application_controller, it could be set :session_secret, ENV["SESSION_SECRET"] which references the SESSION_SECRET> within the .env file, which contains like this SESSION_SECRET="secret".

Plans for the future

I feel like this project went really well. I gave myself the time and resources I needed to succeed. However, there are improvements I would like to make. For a future update, I want to refine this app so that I can deploy it to a service like Heroku or Netlify so that I can access it on the web. Learning to hide sensitive information was a step in the right direction, but there may be additional layers of security to implement. I will have to think about storage, deploying changes, testing and monitoring the app to ensure any vulnerabilities are taken care of.

Keeping Wine Journal DRY was a large part of the project requirements. Overall, my application was DRY, but I know there is room for improvement. I like to take some time away from a project (and after it has been reviewed) before I refactor it. That way, there is less risk of breaking it ahead of it being reviewed.

I would like to refactor common or similar patterns into new helper methods. At several points in my application_controller I confirm if the current user has permission to modify an object. This can be refactored into a has_permissions? method and referenced within other methods.

The routes and redirects I set up keep the user from getting stuck at a page with no direction. However, error messages to explain why they have been redirected is something that I want to incorporate. The Sinatra Flash gem is one I am looking into.

The scope of this project did not include accessibility, load times or progressive web applications (PWAs), but I would like to incorporate those concepts. I learned about PWAs last year during the Udacity, Mobile Web Specialist Nanodegree and would love to do more! It would be really cool to be able to access the app offline, store any changes locally then push them to a server when the connection is available again. I’ll be able to add wine notes anywhere!

Overall, I am happy with this project and look forward to being able to add to it.

The code for Wine Journal is available for use on Github.

Screeshot of Wine Journal homepage
Screenshot of Wine Journal homepage

Wine bottle icon provided by Font Awesome. No changes were made.