For my rails project, I created a web app that allows users to create, share, and rate loglines. If you’re unfamiliar, a logline is a one or two sentence synopsis of a movie or TV show.
I tried to keep the project as simple as possible but it became complex when I added in the rating system. I wanted users to have the ability to rate loglines but only once, and they weren’t allowed to rate their own loglines.
I got tripped up trying to implement the logic for the user to only rate a logline once. At first, I tried searching through the rating model to see if the user already rated the logline. This worked but the rating system could be hacked by rating a logline, then going back in the browser and rating the same logline again. So finally I settled upon this code in ratings table:
add_index :ratings, [:user_id, :logline_id], unique: true
This prevented duplicate records from being created.
The next issue I ran into was averaging all of the ratings for a particular logline. At first I had a model method that looped through all of the logline’s ratings, pulled out the rating integer and averaged them all together. But this became unwieldy and I ended up adding an average_rating attribute to the logline table. I should have done this from the start, but it gave me the ability to use a scope method to pull all of the top rated loglines to display.
Another issue I ran into was using render collection to loop through an associated object. I had trouble getting this to work in one area, so I ended up leaving the loop in the view.
Finally, the other issue I ran into was when a user signed up with invalid credentials, the errors showed up fine but the view got routed to /users instead of back to /users/new. The user could still fill out the page but if they pressed refresh in the browser, it would route to /users and throw an error. I opted to not use @user = User.new in the controller to prevent this issue. I’m sure there is a work around for this, but I couldn’t seem to figure it out.
That being said, I learned a ton from building this project, and surprisingly it actually went much smoother than my Sinatra project.
You can check out the project here.