Tarot reading is the practice of utilizing tarot cards to gain an understanding of the past, present, and/or future. Typically, a question is asked, cards are drawn, then an interpretation of the cards is provided. Tarot card reading has been around since the late 1700’s and now, over 200 years later, has gained popularity.
connecTarot is a web application built with Rails. It is designed to connect like-minded people together in the world of tarot. Users are able to track their own tarot readings, receive readings, and conduct readings for others. This application was built with inspiration from my wife (who is deep in the world of tarot) as a portfolio project for Flatiron School.
There are five primary features of the application. The first is integrated user accounts with a standard sign-up method as well as the ability to sign-up with Facebook or Github. In order to implement this functionality, the following omniauth gems were utilized:
gem 'omniauth-github', and
gem 'omniauth-facebook'. A dynamic route was implemented in the
routes.rb file in order to have an efficient route for receiving information back from the provider:
match '/auth/:provider/callback', to: 'sessions#create', via: [:get, :post]
The User model has a class method that gets invoked when a user attempts to sign-up or login with the provided Facebook/Github links. This method utilizes the
find_or_create_by method that ActiveRecord provides in order to cover scenarios in which the user is signing up or logging in.
The main feature of the app is the ability to create tarot readings for yourself with computer generated “shuffling” of a deck of tarot cards. Users have the option of selecting an existing spread of questions, or they can create their own spread by providing three questions they are seeking guidance on. The user will then be prompted to pull a card three times.
There are 78 cards in a tarot deck and they are all seeded in the database. The
.sample method is called on
Card.all as a class method in order to randomly generate three cards (excluding duplicates) out of the computer generated “deck” of cards. After pulling three cards, the reading is then displayed. The reading includes images of the three cards pulled, along with the meanings of the cards displayed in the context of the questions that were asked (or part of the pre-made spreads).
A unique feature is the ability to add thoughts to a finished reading. Reflecting on the cards drawn is an essential part of a tarot practice, so users can add thoughts and see them displayed below the reading.
The fourth major feature is the ability to track your readings over the course of a month. This feature is useful because it allows the user to gain insight into patterns that develop throughout each month. The monthly summary table shows your total readings, total cards pulled, major cards pulled, minor cards pulled, court cards pulled, and the number of cards pulled for each suit. It also displays specific cards if they were pulled more than two times in a month. Users can also filter all of their readings by a specific card or spread.
The final feature is the ability for users to request and respond to readings. Integrating a card’s meaning in the context of a specific reading is a major component of tarot. So in addition to the card meanings being displayed, other users will be able to write out an interpretation for the requestor based on what the requestor is seeking insight on. All users are able to view the requests index page. This is where all of the requests are shown, in order of the status of the request (open, pending, or fulfilled) and by descending date of creation.
Once another user responds to a request, they are provided a form on the request show page.
Once the form is successfully submitted, the requestor will have a new entry on their “My Readings” page. This entry will still display the meanings of the cards, but will also display the custom interpretation from the responder of the request.
One issue I ran into when building this app was how to efficiently display the attributes of a reading in the
show.html.erb view. When a custom reading is complete, the interpretations are displayed on the reading’s show page. Each reading (named
entry in the app), has three optional attributes for interpretations. These attributes are named
In this view, I implement an iteration to display information about the cards pulled, including the interpretations (if any exists):
The last line of code in this iteration invokes the helper method
#display_interpretation_if_request_exists. This method (and iteration in general) was crucial for thinning out the lines of code needed to carry out this functionality. This method uses concatenation to execute and display multiple lines of generated HTML if
entry.request exists (is true). This method calls another method,
In this method I utilize the
#send method. Since we are still in the iteration, I created this method so that I could call reader methods dynamically. For example, I wanted to display the
#interpretation_2 attribute of this entry. So you could code it as
@entry.interpretation_2, but I instead utilized these methods within the iteration to dynamically call the correct methods based on the index of the
cards array. The
#send method allows us to ‘send’ a block of code as a method. So I am sending the local variable
inter as the argument for
inter is a string that utilizes string interpolation to dynamically set the variable name for each cycle of the iteration.
Another issue I had was when I implemented functionality for a responder to create a reading for the requestor. The form for this request is shown in the
requests/show.html.erb view file. This form sends a
POST request to the
user_entries_path. In order to make this function properly, I implemented an if statement in the
entries#create action in which it looks for the existence of the value for
The somewhat challenging part was authorization. I created a method called
#require_authorization that gets executed as a
before_action for all actions in the
EntriesController except for the
create action. This method checks if the current user who is logged in is the same as the
@user instance variable throughout each action in the controller. The reason I have the except clause for the
create action is because this action requires special authorization. When a responder is creating a reading for a requestor, that responder needs authorization to write to another user’s page. This is done by the
unless || statement below in the
#require_custom_authorization method. In this method, a user is considered authorized if the
user_id in the url is the same as the
current_user OR if the
responder_id that is passed as a hidden input field in the form is found in the database and matches
The Github repository for this application can be found at the link below. Feel free to clone the repo and run the app in your browser to play around with it. Even though the app is not live on the web, you can still conduct readings and track them locally. Any comments or questions are greatly appreciated!