My Sinatra portfolio app is an RPG Character Builder that allows users to save and view details of the video game characters they’ve created and played.
Users can sign up for accounts, login to view their saved character details, create, edit, and delete the characters they saved, and associate them with games.
They can also view a total list of all games that have been created and associated with characters on the site, and the number of characters and users associated with them.
The most important, difficult structural decision I made when developing this app is what sort of associations to have between my Character, Game, and User model class.
Since the main purpose of the app is to allow Users to perform CRUD actions on Characters, it was a simple enough choice to give the User a :has_many relationship with the Character class.
However, it was harder to decide how to associate Users with Games. At first, I wrote a UserGame model class, a join table that would’ve saved both user_ids and game_ids, but realized shortly into coding my app that a UserGame model was redundant. If I gave the Character model a :belongs_to relationship with both the User and Game models, then I could give the User and Game models :has_many :through associations with each other, through the Character class. Removing the UserGame model made my code more DRY.
Key takeaways from developing this app:
-
Avoid unnecessarily complex associations. There is no need to create redundant model classes if the two models can be associated with an existing
:has_many :throughrelationship. -
Avoid calling
Class.allin your views for security reasons. It makes it easier for hackers to access all the data in your table through your browser. It is better to set assignClass.allto an instance variable in your controller routes, and invoke the variable in your view. -
When using the
rack-flash3Ruby gem,use Rack::Flashmust be invoked in the application_controller after enabling sessions, not in theconfig.rufile. I believe the reason for this is because Rack::Flash depends on having sessions enabled, so if Rack::Flash is loaded byconfig.rubefore sessions is enabled, your app will throw an error. -
Calling
.uniqon an instance associated with other instances through a:has_manyrelationship avoids redundant lists and inflated totals.