Cookies - yumm


Amongst other things, I have been gradually adding features and refactoring my dinner party app. I also finally made it out to the providence geeks dinner last night which featured shape up. It was definitely a worthwhile experience and I met a lot of great people. I will definitely be trying to make it out as often as possible.

Back to the app, in its current form it does what I wanted it to do. However, there were a few quirks that were bothering me. First, I hadn’t let a user edit their RSVP, which you know if they decide not to go well that’s an issue. Anyway, that was a easy fix…However, another problem arose.

When I first started working on this project, I knew I didn’t want to go through creating a user authentication system or using omniauth again…Besides, no one likes logging in anyway, especially on a site that is supposed to be super simple and just does one thing.

What I did instead when building the project was to generate a unique “slug” to use in URL. This way once someone creates a “dinner event” they are provided with a unique link to send to their friends so they can RSVP. This also has the bonus of not exposing the db id’s within the URL.

Great, so you get the link and decide to RSVP. Once RSVP’d you’ll see yourself on the list of “attendees” along with the “dish” your going to bring..Finally, here’s the problem…All your friends who also visit that link to RSVP can edit or delete your RSVP..not cool, well hopefully your friends wouldn’t do that, but still not ideal.

Here’s what I did to “kinda” rectify this situation. We needed a way to “id” the user that is “RSVP-ing”. Typically, this could be handled easily if I were using some kind of login or user authentication system. In my case I decided to use a cookie..Here’s what I did.

# app/controllers/rsvps_controller.rb

class RsvpsController < ApplicationController
  def create
    dinner = Dinner.find_by_slug(params[:dinner_id])
    rsvp = Rsvp.new(rsvp_params)
    if rsvp.save
      cookies[:current_rsvp_id] = rsvp.id
      redirect_to dinner_path(dinner), notice: "RSVP'ed, Thanks!"
    else
      redirect_to root_path, notice: "Sorry, make sure all fields are filled."
    end
  end
  ...

Above, upon creation of a new RSVP we fetch the associated dinner via its unique slug, create and save a new Rsvp object and after a successful save we create a cookie with the rsvp.id. In this case I not dealing with any kind of sensitive information so the cookie isn’t encrypted in any way. So we have a cookie with the key of :current_rsvp_id and value of rsvp.id.

# app/controllers/application_controller.rb

  def current_rsvp_user
    current_rsvp_user ||= cookies[:current_rsvp_id] && Rsvp.find_by(id: cookies[:current_rsvp_id])
  end
...

Here in the application controller is just a simple helper which is then used in the view.

# app/views/dinners/show.html.erb
 ...
<% @dinner.rsvps.each do |rsvp| %>
  <tr>
    <td class="text-center">
      <%= rsvp.name %>
      <% if current_rsvp_user == rsvp %>
        <%= link_to edit_dinner_rsvp_path(rsvp.dinner.slug, rsvp) do %>
          <i class="glyphicon glyphicon-pencil"></i>
        <% end %>
        <%= link_to dinner_rsvp_path(@dinner.slug, rsvp), method: :delete do %>
          <i class="glyphicon glyphicon-remove"></i>
        <% end %>
      <% end %>
    </td>
    <td class="text-center"><%= rsvp.dish %></td>
  </tr>
<% end %>
...

In my view I have a table which shows who’s attending and the dish they are bringing. This code above checks to see if the cookie matches the rsvp.id as the list of RSVP’s is iterated through. If there is a match, it displays the edit and delete icons next to the rsvp.

So, understandably this has its limitations. If someone were to clear their browsing history/cookies then well..they are no longer able to edit their RSVP. I didn’t put an expiration on the cookies themselves. At some point I plan on maybe having a automated cron job that removes any dinner about a week after it occurs.

That said, this was a fun exercise…Trying to find a solution without resorting to a login system. If anyone has any ideas feel free to let me know. I would say this solution given my criteria fits relatively nicely.

comments powered by Disqus