Table of Contents
For this project, we will have high-level project instructions in the first section of this readme. If you find yourself confused about how to implement a specific step, there are more detailed instructions/hints in the second section of the readme that you can reference, however try to tackle each step yourselves first before referencing the hints.
If you're having bundle install issues, please refer to Piazza for help. You can try bundle install --without production
if it's a pg gem issue.
Additionally, please make sure you consistently keep your repo up to date. In order to sync your repository with ours:
# Do this line below once
git remote add upstream git@github.com:rails-decal/sp18-proj1.git
# The line below is not needed if you are already on master branch
git checkout master
git pull upstream master
If you are seeing permission denied errors, try replacing the first line with:
git remote add upstream https://github.com/rails-decal/sp18-proj1.git
Note: The skeleton project we have created for you already implements sign up and sign in. Though this course will not cover the details of sign up and sign in, we know many of you will want to have sign up and sign in for your final projects, so here is the link to a really simple and quick way to setup an entire Rails app with user authentication (and frontend framework) already implemented. This is what we used to create the foundation of this project!
Throughout this project you will be creating a PokePortal, a mysterious realm where you will be able to:
- Capture Pokemon
- View your Pokemon
- View other trainers' Pokemon
- Damage and destroy other trainers' Pokemon
- Create your own new Pokemon
Important: You will be answering questions in ANSWERS.md along the way.
Fork this repo and clone it in your terminal. cd
into the directory, run bundle install --without production
and migrate your database, then start your server. (If you have trouble running the bundle install, try running rvm use 2.4.1
(or whatever your version of Ruby you downloaded is) in your terminal first). In localhost, you should see an error that says: "uninitialized constant HomeController::Pokemon". This is expected; let's fix it.
In ANSWERS.md, answer Question 0.
- Run the
generate
method you've learned to generate the Pokemon model. The model should have the following attributesname
:string
level
:integer
trainer_id
:integer
ndex
:integer
(this is the pokedex number!)
- Note: Try to use the
references
column type in order to associate thepokemon
with the appropriatetrainer
. This will affect how you generate the column withtrainer_id
. It is ok to simply create thetrainer_id
column of typeinteger
, but with thereferences
type we also build an index on thetrainer_id
foreign key which makes lookups more efficient. - After you've generated the model, migrate it into the database.
- Edit your
pokemon.rb
andtrainer.rb
file so that a Pokemon optionally belongs to a Trainer and a Trainer can have many Pokemon. In order to have the optional of wild, trainerless Pokemon, we will need the line:belongs_to :trainer, optional: true
. - Generate a controller for your Pokemon model. This should be an empty controller for now, just make the file. We've already created a
pokemons.scss
file for you. DO NOT OVERWRITE THIS when it asks you for it in the generation prompt. - Seed your database with starter Pokemon with the seed file we've provided. This can be achieved with the command
rails db:seed
.
Go to localhost - you should be able to see the home page and sign up now. Once you've logged in and go back to the home page, some wild Pokemon should appear with every refresh, however you can't capture them!
In ANSWERS.md
, answer Question 1.
- In
views/home/index.html.erb
, replace the div button with the following code:<%= button_to "Throw a Pokeball!", capture_path(id: @pokemon), :class => "button medium", :method => :patch %>
- In your Pokemon controller, add a function called
capture
. This function should:- Grab the id of the Pokemon from the parameters and set that Pokemon's trainer to be the current trainer logged in.
- What's great about Devise (the user authentication gem we already have set up) is that it predefines a method to give us the current user logged in - or in this case, current trainer. To grab the current trainer, use
current_trainer
. You can use this in controllers and views.
- What's great about Devise (the user authentication gem we already have set up) is that it predefines a method to give us the current user logged in - or in this case, current trainer. To grab the current trainer, use
- Don't forget to save the changes to the Pokemon!!!
- Redirect to the home page
- Grab the id of the Pokemon from the parameters and set that Pokemon's trainer to be the current trainer logged in.
- Create a new route in your routes file that will call the function you just wrote. Name the path
capture
as its prefix. Set the URI pattern to be "capture".
On your localhost, you should now be able to capture Pokemon! Double check in your console that a captured Pokemon now belongs to you.
In ANSWERS.md
, answer Question 2.
- Figure out where in the app you can see a trainer's profile. In that view, add a list of the trainer's Pokemon. Each Pokemon should show its name and level.
- Additionally, the Pokemon's sprite should be rendered above its name/level. Take a look at lines 5-7 of
app/views/home/index.html.erb
, and try to pattern match those lines of code.
On your localhost, you should now be able to view all your Pokemon in your profile!
In ANSWERS.md
, answer Question 3.
- Make the Pokemon model have a health column as well.
- Go into your
db/seeds.rb
file and make all seed Pokemon start out with 100 health. - After you've changed the seeds, run
rails db:reset
thenrails db:seed
. This command drops your database, creates a new one, runs all migrations, and seeds the database. Now you should have seeded Pokemon with health as well. - Show health for each Pokemon in the list on a Trainer's profile.
- Go into your
- Based on Part 2, you should be able to mimic the capture method to implement a damage method.
- Each damage should subtract 10 health from the Pokemon.
- You should redirect back to the trainer's profile page at the end of the damage method. Hint: run
rails routes
to see what path you need. - There should be a button that says "Damage!" next to each Pokemon in the list of Pokemon on each trainer's page. You can follow the same syntax you used for the button in part 2 to implement this button, except changing two things.
- If a Pokemon reaches <= 0 health after being damaged, destroy it. It should no longer exist in the database. It is dead.
On your profile page, try damaging your own Pokemon. Try destroying one.
In ANSWERS.md
, answer Question 4.
Now that it's so easy to destroy Pokemon, we need a way to create new Pokemon.
In this part, we will allow the current trainer logged in to create his or her own Pokemon that will automatically belong to himself/herself.
- Create a folder
pokemons
inviews
. Make a new file in that folder callednew.html.erb
.- Use
simple_form_for
to make a form for creating a new Pokemon. You should refer to the documentation on simple_form. The only fields in your form should be the Pokemon'sname
and the Pokemon'sndex
.- In order to capture the Pokemon's
ndex
, or Pokedex number, we want to include a radio selector over all Pokemon options available to choose from. Add a field forndex
using the code below. As a challenge, try to understand what it's doing!
<%= f.collection_radio_buttons( :ndex, (1..649).map {|ndex| [ndex, ndex]}, :first, :last ) do |b| %> <div class="pokemon-choice-container"> <%= b.label { image_tag("pokemon/#{b.text}.png") + b.radio_button } %> </div> <% end %>
- Don't forget to add a submit button! Use this code to make it nice and big (it applies the CSS we defined in
pokemons.scss
)
<%= f.button :submit, class: "create-pokemon-btn" %>
- In order to capture the Pokemon's
- Create the necessary methods in the Pokemons controller that are needed to show the form and to handle the form's data after submit.
- Since we only had the Pokemon's name in the form, we want to set every other attribute to a default. Default health to 100 and level to 1.
- It is highly recommended that you use strong parameters in order to retrieve data from
params
. While doing this, make sure youpermit
BOTH thename
and thendex
fields, since these are the data fields that we are receiving from the create pokemon form. - Set the new Pokemon's trainer to the current logged-in trainer.
- Redirect to the current logged-in trainer's profile.
- Route the methods accordingly.
- Use
- Create a button that only shows up in the current logged-in trainer's profile and links to the form you just created.
Now if you go into your localhost, you should be able to create new Pokemon for yourself. But we want to make sure you can never create Pokemon with the same name, or even worse, no name! What do we need? A validation.
- In the Pokemon model, validate a name is present and that it is also unique.
- In the method that you created to handle the form data in your Pokemons controller, give the following logic at the end:
- If you successfully save the new Pokemon instance, then redirect to the current logged-in trainer's profile, just like before.
- Else, redirect to the form and flash the appropriate error.
Now you shouldn't be able to create new Pokemon with no name or a duplicate name.
In ANSWERS.md
, answer Question 5.
[+1% of final course grade] Let friends join PokePortal.
- Deploy this app on Heroku. Link the Heroku in the Google Form.
[+1% of final course grade] Implement Pokemon healing.
- Increment health by 10.
- Your Pokemon should now be hidden from other trainers when health is <= 0, instead of being destroyed.
- You should be able to heal only your own Pokemon.
[+5% of final course grade] Implement Pokemon battling.
- Right now, damaging is lame. Your Pokemon, not yourself, should damage other Pokemon. Make it so that when you click damage, you have to select one of your own Pokemon to gain experience from the attack, and level up!
- You should choose your Pokemon from a dropdown menu.
- At github.com, make a new empty repo called proj1.
- Repoint the remote of your local repo to the new repo you just created.
- In your terminal, run
git remote set-url origin git://new.url.here
using the url of your new repo (this can be found in the bottom right of your empty repo on github.com, in the box above Clone in Desktop).
- In your terminal, run
- Run
git add --all
. - Run
git commit -m "I am a Pokemon master."
. - Run
git push origin master
.
Link your repo in the last question of ANSWERS.md, and submit!
Congratulations. You are a Pokemon master.
If you ever have to reset your database (for instance you destroyed all the Pokemon in the PokePortal or you messed up your migrations), run rails db:reset
to drop, recreate, migrate, and reseed your database.
Reference Lecture 5 for a recap of how to make a Pokemon belong to a Trainer. To set up the seed Pokemon, use rails db:seed
.
To redirect to a certain page, use redirect_to PREFIX_PATH
.
rails routes
will be very helpful in debugging. Since we are updating a Pokemon, your route should be a PATCH. If you need to jog your memory on routing, reference how routes were done in Lecture 2
Also, if you don't know what a URL pattern in a route is, look back at Lecture 2 or Jon's demo again.
To learn more about what button_to
actually does, read up on its documentation here and maybe this Stack Overflow post as well.
Refer to the Lecture 5. Also recall what you did for Lab 2.
If you want to designate a path that simple_form should go to after a submit, use this syntax:
simple_form_for @object, :url => prefix_path
For help with validations, you should read the Rails documentation on validation, specifically the sections for "presence" and "uniqueness". You can also Google and there should be many Stack Overflow posts to help you out.
To flash the appropriate error, use the line flash[:error] = @pokemon.errors.full_messages.to_sentence
. This works because in views/layouts/application.html.erb
, it is rendering something at the very end. Take a look at that file and see what it is doing. If you don't already know what application.html.erb
does, you should Google it and understand its function.
For easy deployment, reference Heroku's deployment docs. You'll need to look at the Local Workstation Setup part and the Deploy your application to Heroku part.