Ensuring Users Can Only See What Belongs_To Them
For my second coding project with the Flatiron School, I was tasked with creating an MVC, CRUD app using Sinatra.
No, not that Sinatra!
Lately, I have been using my favorite to-do/shopping list app, Wunderlist, to store books, films, and tv shows I want to read and watch in a centralized location. So, for my project, I decided to make a tv show/film watchlist called CouchPotato.
Getting started on this project was a lot easier than the last because, on some level, I knew what to expect from the process — errors/frustration/excitement!
Error number one took the most refactoring. Although TV shows and movies were editable, every user that logged in was able to see other users’ list items. They all merged together! I wasn’t sure what the problem was, but I knew it violated two of Flatiron’s requirements for this project:
- Once logged in, a user must have the ability to create, read, update and destroy the resource that belongs_to user.
- Ensure that users can edit and delete only their own resources — not resources created by other users.
I also knew it was stemming back to the following areas of code:
- My current_user definition was not correct
- My get & post for ‘/shows’ was not populating the shows that belonged to the user
In reviewing these areas, I noticed that I was defining the current_user with:
User.find(session[:user_id])
I thought about a practice blog we created in one of our study groups and remembered that we assigned a user with a pipes equal:
@user ||= User.find(session[:user_id])
Why? Because double pipes, equal will only assign a user if it is returning as false or nil.
This solved the first bullet point I wrote down for myself. I needed to go back to my get and post routes. My get route was simple enough:
get ‘/shows’ do
@shows = Show.all
if logged_in?
erb:”shows/shows”
else
redirect “/login”
end
Why had I been populating all of the shows!? I, instead, identified the user as the current_user and the shows as the current_user’s shows only. Now we’re talkin’.
if logged_in?
@user = current_user
@shows = current_user.shows
erb:”shows/shows”
else
redirect “/login”
My post route was a little complicated & clunky:
post ‘/shows’ do
if !params[:show_title].empty?
@show = Show.create(show_title: params[:show_title])
else
redirect “/shows/new”
end if logged_in?
@show.user_id = current_user.id
@show.save
end redirect “/shows”
end
I thought back to that study group project again and remembered we used much simpler code to solve this exact problem. I refactored my code and created a variable called @s that was equal to the current_user’s created (built) shows, rather than assigning an instance of a show.user_id and assigning it the current_user.id.
post ‘/shows’ do
@s = current_user.shows.build(params)
if @s.save
redirect “/shows”
end
If this instance variable of @s saves, we’re back at /shows. HOORAY! It worked!
If you want to check out my app, here’s the repository.