Phase Two Project - Dragon Hunter
Published: 2021-01-06 17:57:07

Vikram Chatterjee

Intro
The Dragon Hunter is the premier tool for adventurers who seek to document and hunt the dragons they are looking for or have found in the wild. The Dragon Hunter webpage allows a user to document a new dragon, edit a dragon that they have listed, or delete a dragon. Each user has many dragons and each dragon belongs to and can only be accessed by one specific user. 


Layout
The styling of this website is provided by Materialize, a CSS library available at www.materializecss.com. The stylesheet is loaded in the layout page within the head area. A nav bar with options to login or signup, or logout, or to go to the Dragons index, or create a new dragon, based on whether the user is logged in or not, are contained within the nav bar. Also if the user is logged in, the user will be greeted on every page with "Hello, <%=current_user.username%>", so there is no confusion on which user is logged in at any given time. 

Signup 
When a user first visits my website, they will be redirected to the GET route for the sign up page. They will be asked to enter a username and password, at which point a POST request will be made to the signup route. A user will be created with the params of username and password and stored into the database. A password digest parameter in the User object uses bcrypt to take the password param and replace it with an encrypted hex value. A session will then be created with a key of :user_id and a value of the user id (user.id). This logs in the user. Then the user will be redirected to the dragons index page, which will initially show an empty list of dragons. 


Login
A link to the login page is only showed on the navbar if the user is not logged in. Like the signup page, a user that is logged in who attempts to go to the /login route will be redirected to /dragons. When a username and password are entered into the login fields, the post '/login' method in the sessions controller will check to see if a user with the given username exists, and then it will use the user.authenticate method from Bcrypt to check to see if the entered password matches the encrypted hex from the password digest of that user. If the login is successful, a session will be created containing the user id,  and the user will be redirected to the Dragons index at '/dragons'. Otherwise, the user will be redirected back to an empty login page. 

A note on sessions
Sessions have been enabled through the application controller. A randomly generated hex value for session secret has been generated in IRB using the securerandom gem and the SecureRandom.hex saved into the .env file and is accessed in the Application Controller. The .env file is not accessible in the repo as it has been filed under gitignore. This way, sessions can not be artificially created by a user in any other way than through the methods that create sessions within the controllers of this program. 

New Dragon
The user will then have the option to click on the New Dragon button at the top right hand corner of the page. They will see a form that allows them to fill in the dragon's name, select a color using radio buttons, and select the dragon's breed, personality, and treasure using drop down menus. The drop down menus are initialized in the layout page using a jquery script towards the bottom of the "head" area. There are 7 different dragon colors for a user to choose between, as well as 5 different breeds, 5 personality types, and 5 different types of treasure. The user must enter/select a value for every attribute, otherwise the Dragon object will not be saved. When all of the attributes for the Dragon are filled out or selected and the user hits submit, a POST request is made to the /dragons route. A local variable named 'dragon' is assigned to a Dragon object that is built using an Active Record association <current_user.dragons.build(params[:dragon])> and if that dragon is saved successfully, a session will be created with the id of that dragon, which allows the website to remember which dragon was most recently viewed or created. The user will then be redirected to the dragons index page, and the name of the dragon that was just created will show up under recently viewed. If the dragon fails to save, the user will hit submit and be redirected to an empty 'new dragon' form. 

Index
When a user requests or is redirected to the Index page, a check is made to see that a user is logged in, and if not, they will be redirected to the signup page. An instance variable, @dragons, is set to Dragon.all, and @dragons is iterated over to see which dragons belong to the user that is logged in. If a dragon's 'user foreign key' matches the id of the currently logged in user, a link to the show page of that dragon will be displayed as the name of the dragon being listed. Above the list of dragon names belonging to the user, a 'Recently Viewed' string of text appears, and presents whatever dragon object is stored in session[:dragon_id]; ie. the dragon whose show page we have most recently viewed. 

Show
The show page lists the name of the dragon as a header, and all of the dragon's attributes (color, breed, personality, treasure) as paragraph tags underneath it. An image of the dragon, based on its color, is rendered beneath the attributes of the dragon. Below the dragon's picture, an edit button is displayed which takes the user to the dragon's edit page, and a delete button is displayed which will delete the dragon and take the user back to the index page where the other dragons are listed. If the user tries to go to the show page of a dragon that does not exist, the redirect if not found method will check to see if a dragon with the corresponding id exists, and if not, the user will be redirected back to /dragons. A session will be created for a specific dragon when its show page is visited, which allows the Recently Viewed string in the index page to list the name of the last dragon that was viewed. 

Edit
The edit form directs the POST request to the route /dragons/@dragon.id and using the line: 'input type="hidden" name="_method" value="patch"' the POST request is changed into a PATCH request. The edit page for the dragon is similar to the new dragon page, except that all of the values for the name and attributes of the dragon are pre-filled in. For the name attribute, this means that the value @dragon.name is listed within the name input field. For the color, the radio button will be checked if the dragon's color matches the value corresponding with the color that the radio button selects for. The code for this is <%='checked' if @dragon.color == "Red" %> so for example if the dragon color is Red, the radio button for Red will be checked. Similarly, the values of the drop-down menus will be preselected with whichever breed, personality, and treasure the dragon has. For example, the drop-down menu will be prepopulated with "Dragonnet" using the code <%= 'selected' if @dragon.breed == "Dragonnet" %> if the dragon's current breed is Dragonnet. Like with the show page, a dragon can only be edited if the dragon id in question is populated by a dragon that exists. When the submit button is pressed, a patch request will update the dragon's attributes and return the user to the show page for that dragon. 

Dragon and User objects
The Dragon object inherits from ActiveRecord::Base and validates that all of the attributes have been assigned a value in order for the dragon to be saved. The dragon object also has a belongs_to attribute where a dragon belongs to a user. 
The User object inherits from ActiveRecord::Base and validates the presence and uniqueness of the username. It also calls on the has_secure_password method from Bcrypt which validates the presence of a password, and encrypts the password param into a password digest. 

User Dragon Relationships
A user is only able to see and interact with dragons that belong to that specific user. In the index page, as was previously mentioned, embedded ruby commands iterate over Dragons.all to see which dragons have a user_id matching the foreign key of the user. If a user tries to go to the show or edit page of a specific dragon, the program will check if that dragon belongs to the user using the foreign key, and if the dragon does not belong to the user, the user will be redirected to /dragons. The current user method checks to see if the session belongs to the user that is logged in, and the redirect if not owner method checks to see if the dragon's owner or user matches the current user. 

Flash Errors
Flash errors have been added to the program, which tell a user the corrections that they need to make in their requests if they have made an error. If a user is logged in and requests the signup or login page, a flash error will come up saying "You are already logged in". Similarly, if a user tries to go to the index page for dragons, or a show or edit page for a specific dragon, and they are not logged in, a flash error will come up saying "You must be logged in." If a user requests the show or edit page of a dragon that does not exist, the error "Dragon not found" will show. If the user attempts to go to the show or edit page of a dragon that belongs to another user, the error message "That is not your dragon!" will show. If a user attempts to go into the edit page of a dragon and delete the name, the error message "Dragon must have a name" will be shown.