DEV Community

Aldo Portillo
Aldo Portillo

Posted on • Updated on

Cookie Limit

Intro

I've been working on a mini project using Sinatra. I'm attempting to use everything I've learned in Ruby.

I'm constantly trying to find new things to add to make sure I cover all the bases I have learned so far. Currently I am working on creating an advanced search section in which users can add whatever ingredients they have and they will receive an array of cocktails they can make with those ingredients.

In order to keep data upon each render. I am storing the data as cookies. As a React Developer, I would've just used state, so I am finding this problem very helpful.

Attempt

Upon calling the API with a query of a certain ingredient the API returns all the cocktails that contain those ingredients in JSON. My initial idea was to have the current drinks array and modify it after a new ingredient is added:

new_ingredient = params.fetch("new_ingredient")

ingredient_list = JSON.parse(cookies["ingredient_list"])
ingredient_list.push("new_ingredient")

new_cocktails_req = HTTP.get("API including #{new_ingredient} param")

new_cocktails_res = JSON.parse(new_cocktails_req).dig("drinks",0)

current_cocktails = JSON.parse(cookies["current_cocktails"]) #The cookie is initialized in the get route

filtered_array = []
if current_cocktails != []
  current_cocktails.each{|cocktail|
    if new_cocktails_res.include?(cocktail)
      filtered_array.push(cocktail)
    end
  }
else
  filtered_array = new_cocktails_res
end

cookies["ingredient_list"] = JSON.generate(ingredient_list)

cookies["current_cocktails"] = JSON.generate(filtered_array)
Enter fullscreen mode Exit fullscreen mode

Problem with this code

I was noticing that the ingredient_list was being stored in local storage; however, the filtered_array was not. I was able to display the filtered_array using irb to see if it was working as it should and it was. So I figured that it had to do with cookie storing. I modified my code and nothing changed, so I figured there must be a limit. There is a limit. The limit is 4096 bytes. Each character counts as a byte, so str.length returns the number of bytes the string contains.

I converted my filtered_array to JSON and checked the length. It was 14,036 bytes exceeding the limit. If the cookie that is being stored is greater that 4096 bytes. The cookie is not modified.

Solution

I could easily store the filtered_array in local storage but there are two problems with that:

  1. Storing a string in local storage is an synchronous process so the main thread will be blocked. Compared to cookie storing which is async.
  2. Although I'm familiar with local storage, it is something I haven't covered in Ruby yet.

My current solution revolves around storing the cocktail IDs as opposed to the entire cocktail hash and at the point of render fetch each cocktail in the list. At first, the list will be very long but as more ingredients are added the list should decrease following an exponential decay graph to 1 or 0.

Issue with my solution

Let's say my array of ids is of length 1000 and each id is of length 5. That will exceed the local storage size. Luckily, that shouldn't happen since the cocktail database I am using isn't that large.

The next issue will be if I have the array of ids of length 50 which is very plausible. I will have to make 50 calls to the API in the get route using a for loop. Can the API even handle that in time to render the page? If it can't are promises even a concept available in Ruby?

Update: August 5, 2023

I attempted to declare a global variable to store the array of cocktails in my app.rb file. Unfortunately, the blocks within my routes do not have access to global variables.

After further consideration, I realized since storing in local storage is a synchronous process. The webpage will wait til the process is complete to render. This should allow the page to:

  1. Store a larger array
  2. If I kept an array of IDs, I would be able to create and resolve a request for every single ID.

Luckily, the second option is not necessary since local storage can store a larger array than cookies.

I will incorporate this update when I cover local storage in Sinatra.

Final Update: August 22, 2023

When reviewing Ruby Classes and Objects. I went deep into a variable rabbit hole. Luckily this lead me to figure out how to declare a global variable in Ruby within a method block. Even though this was a solution I had in mind since my last update. I am glad I got it running.

Top comments (4)

Collapse
 
samuellubliner profile image
Samuel Lubliner

Really interesting post! I am curious how you feel about the developer experience with React vs Sinatra?

Collapse
 
aldoportillo profile image
Aldo Portillo

They're both great frameworks. React being a front end framework that is very simple and easy to learn, but you can do more as you learn more. In my old React projects, I used Express.js which is another backend framework just like Sinatra.

When it comes to Express.js vs. Sinatra, they are both very similar. Sinatra does seem a bit limiting as to what I can do with it. I think that is because it's a language designed to learn HTTP basics and routing. That is exactly what Sinatra did for me. I thought I had a decent grasp on HTTP and routing from previous express projects, but I wasn't sure how to start a request from scratch.

Learning Sinatra helped me better understand my old code, and I am extremely grateful for getting the opportunity to learn it. I'm looking forward to moving on to Ruby on Rails since it's a framework better suited to learning how to use a database, store in a database, and learning the concept of a β€œresource”.

Collapse
 
samuellubliner profile image
Samuel Lubliner

Thanks for the reply! I'm interested in building a project with React but I get a bit overwhelmed by all the options for JS ecosystem. It seems like React and Express are popular technologies. I feel like I've just scratched the surface with Sinatra but I am also looking forward to learning Rails!

Thread Thread
 
aldoportillo profile image
Aldo Portillo

It is always a good skill to have. After my interview, I spoke with previous alums who now work for John Deere and one of them told me that he is a React Developer. They plan to fully switch to React in 3 months.

If you do have some free time. Look at the documentation. It is easy to follow and learn from.