Flatiron Project #2, MTGDeckBuilder

For this project I designed a prototype MTG deck builder. I thought it would be fun to make since I play Magic, and I’m somewhat dissatisfied with other solutions. This is a prototype, so it’s not amazing, but I’m somewhat happy with it. It definitely gives me motivation for a future project where I revisit this idea when we make a project with a frontend framework.


The project is a fairly standard Sinatra web app. It is split into 4 controllers, 4 models, and several views. I decided to have a user/ route which relates to a user, their settings, and their decks, a users/ route which lets others view information about a specific user, and a decks/ route which lets users view all decks and their cards. I chose this because it made sense to me. It allows for route guarding in a simple and intuitive way, either you’re logged in and you can access your user route, or you’re not and you can’t. This allows logged out users to still view info on users and decks. It also has a side effect of simplifying locking editing down to only the user who created the deck/owns the account. This approach has a “downside” of increasing routes, and somewhat obfuscating the difference between users/ and user/, but since this is designed to be used as a web app/site, and the browser handles navigation and understanding of the routes, I think this is fine. Once we move to rails and begin using a frontend framework for navigating the app, I think the backend should change to only using users/ and decks/ since it will primarily be used as an API at that point.

A struggle I had during development was the difference between the sqlite db I am using in development vs the Postgresql database I am using in production. Postgres doesn’t like the group command without using the primary key it seems, I still don’t 100% understand the issue, but the solution I came up with was to do the grouping external to ActiveRecord.

get '/user/decks/:id/add', auth: ['user'] do
    ungrouped_cards = []
    ungrouped_cards = Card.where('name ilike ?', "%#{params[:card_name]}%") if settings.environment == :production
    ungrouped_cards = Card.where('name like ?', "%#{params[:card_name]}%") if settings.environment == :development
    @cards = []
    ungrouped_cards.each do |card|
        @cards << card unless @cards.find { |c| c.name == card.name }

    erb :'/user/decks/add'

Another fix can be seen from this snippet. Postgres is case sensitive when it comes to using the like command, while sqlite is insensitive. Postgres has an insensitive ilike command, but sqlite doesn’t support this so I had to use different commands depending on the environment. Since I only use this search functionality in one place, I didn’t feel the need to extract this logic from the function, but if I were to need this code elsewhere it would be a good idea to extract this functionality.

The source can be found on Github.

Posted on July 6, 2020, 9:52 a.m.

Tagged with: Ruby Sinatra Education MTG