- Build a model of a solar system to practice working with classes
- Individual, stage 1 project
- Due before class, DATE
- Create a class to tie together data and methods
- Create a class which manages a collection of other objects
- Write code that interacts with classes
This project is broken up into three waves, each of which consists of a number of steps. You should git commit
after you've completed each step!
The learning goal for this wave is to practice working with individual instances of a single class.
-
In a file called
planet.rb
, create a class calledPlanet
. Each instance of this class will keep track of information about a single planet.Pay attention to the details of the class name
Planet
:- Class names always start with a capital letter
- Class names are usually a noun or noun-phrase
- Because each instance is only one planet, we use a singular noun (
Planet
instead ofPlanets
)
-
Add a constructor to your
Planet
class. Your constructor should take at least these 5 parameters:name
color
mass_kg
distance_from_sun_km
fun_fact
Each parameter should be saved in an instance variable with the same name (e.g.
@color
forcolor
). These instance variables should be readable from outside the class, but not writable.Once you're done, you should be able to write code like this:
# Load Planet into pry: # $ pry -r ./planet.rb earth = Planet.new('Earth', 'blue-green', 5.972e24, 1.496e8, 'Only planet known to support life') puts earth.name # => Earth puts earth.fun_fact # => Only planet known to support life earth.color = 'pink' # => NoMethodError: undefined method `color=' for #<Planet:0x00007fcfba04c130> # => Did you mean? color
-
Add another file,
main.rb
. This file shouldrequire_relative
planet.rb
, and contain one method calledmain
that will exercise your code. This method should create two different instances ofPlanet
and print out some of their attributes.main.rb
should have this structure:# main.rb require_relative 'planet' def main # ... do stuff with planets ... end main
Note that we invoke
main
as the last line of your program. -
Add an instance method to
Planet
calledsummary
. This method should return (notputs
) a string containing a nicely-formatted description of the planet. Exercise yoursummary
method in themain
method.Question: Why do we
puts
inmain
but not inPlanet#summary
? -
OPTIONAL: Add error checking to your constructor.
- Both
mass_kg
anddistance_from_sun_km
must be numbers that are greater than zero. - What should your program do if they aren't?
- How will you make sure this behavior works?
- Both
-
OPTIONAL: Add minitest tests for
Planet
.
In this wave you will build a second class, SolarSystem
, which is responsible for keeping track of a collection of instances of Planet
.
-
In a new file called
solar_system.rb
, create a new class calledSolarSystem
.- The constructor should take one parameter,
star_name
, and save it in an instance variable. - Each
SolarSystem
should have an instance variable called@planets
, which will store an array of planets. When theSolarSystem
is created,@planets
should be set to an empty array. - Both
@star_name
and@planets
should be readable but not writable.
- The constructor should take one parameter,
-
Create a method
SolarSystem#add_planet
, which will take an instance ofPlanet
as a parameter and add it to the list of planets. -
Create a method
SolarSystem#list_planets
, which will return (notputs
) a string containing a list of all the planets in the system. The string should be formatted in this style:Planets orbiting <star name> 1. Mercury 2. Venus 3. Earth 4. Mars 5. Jupiter
-
Update your driver code in
main.rb
to create an instance ofSolarSystem
, add all yourPlanet
s to it, and then print the list. Here is an example with onePlanet
:solar_system = SolarSystem.new('Sol') earth = Planet.new('Earth', ...) solar_system.add_planet(earth) list = solar_system.list_planets puts list # => Planets orbiting Sol # => 1. Earth
NOTE: When you first run your driver code, you may get an error like this:
NameError: uninitialized constant SolarSystem
What does this error mean? What do you need to do to fix it?
-
Create a method
SolarSystem#find_planet_by_name
, that takes the name of a planet as a string, and returns the corresponding instance ofPlanet
. The lookup should be case-insensitive, so thatEarth
,earth
andeArTh
all return the same planet.Update your driver code to exercise this method:
found_planet = solar_system.find_planet_by_name('Earth') # found_planet is an instance of class Planet puts found_planet # => #<Planet:0x00007fe7c2868ee8> puts found_planet.summary # => Earth is a blue-green planet ...
Questions for you to consider as you write this method:
- What should your method do if there is no planet with the given name?
- What should your method do if there are multiple planets with the given name?
- Is there a built-in Ruby enumerable method that could help you here?
-
OPTIONAL: Create a method,
SolarSystem#distance_between
, that takes two planet names as parameters and returns the distance between them.You can assume that all the planets are lined up in a straight line.
-
OPTIONAL: Add minitest tests for
SolarSystem
.
In this wave, you will build a command line interface (CLI) to allow a user to interact with your classes. This will replace the driver code currently in the main
method of main.rb
.
-
Restructure
main
to do the following:- Create a
SolarSystem
and add somePlanet
s - Enter a control loop that repeatedly asks the user what to do next. The two options at this point are
list planets
andexit
.
Remember that you've already implemented listing planets - you should be able to call that method rather than recreating the logic here.
- Create a
-
Add a
planet details
option to the control loop. When the user picks this option, the program should should call a separate method that will:- Ask them for the name of the planet they wish to learn about
- Display details for that planet
Again, you should reuse a method you've already built to handle formatting the planet information.
-
Add an
add planet
option to the control loop. When the user picks this option, the program should call a separate method that will:- Ask the user for details about the planet
- Create a new instance of
Planet
with that info - Add it to the
SolarSystem
The new planet should now appear in the list of planets, and the user should be able to see its details.
-
OPTIONAL: Add error handling to the control loop. What happens if the user enters a bad command, asks for details on a planet that doesn't exist, or enters an bad value for a new planet's mass?
-
OPTIONAL: Implement the optional
distance_between
method from wave 2, then add an option to the control loop to expose it to the user.
Checkout the feedback template for how instructors will evaluate your project.