Ruby Programming – ODIN Project – 2

odinIntermediate Ruby

You’ve got tools in your Ruby tool box and now it’s time to combine them into more meaningful programs. In this section, you’ll learn how to turn your code into properly organized methods and classes. You’ll also learn how to serialize code and save it into files.


Step 1: Object Oriented Programming

Fundamental concepts about object oriented programming that will help you with any programming language you learn.

How do we combine these building blocks in the most efficient and elegant ways to produce the programs we’d like to write?

The concepts you’ll learn here are often less specific to Ruby itself and more widely applicable to any object-oriented language. That’s because the fundamental concepts are just that… fundamental. Don’t repeat yourself. Modularize your code. Have your classes and methods only do one thing. Show as little of your interfaces to the world as you can. Don’t make methods or classes heavily dependent on each other. Be lazy. These will take some time and practice to implement effectively, but you’ll already be taking a big step towards creating high quality code just by finishing up this section.

There’s a lot to do here but stick with it! We’ll start with some refactoring work which should be a quick refresher of some concepts we covered in the last lesson before moving into some of the OOP principles. The Codecademy lessons are interspersed with their projects so you’ll get a chance to apply what you’re learning. The Beginning Ruby book will help you understand the material a bit deeper, which will be important when you are creating your own projects next.

Points to Ponder

Look through these now and then use them to test yourself after doing the tasks

  • Classes and Methods:
    • What is an implicit return?
    • What is a class?
    • When should you use a class?
    • How do you create a class in your script file?
    • What is an instance of a class?
    • What is the difference between the CamelCase and snake_case styles of naming?
    • How do you instantiate a class?
    • How do you set the state of your new instance?
    • What should be done in the #initialize method?
    • What is a class method?
    • How is a class method different from an instance method?
    • How are methods you already know like #count or #sort etc instance methods?
    • What’s the difference between how you declare a class method vs an instance method?
    • What’s the difference between how you call a class method vs an instance method?
    • What is an instance variable?
    • What’s the difference between an instance variable and a ‘regular’ variable?
    • What are “getter” and “setter” methods used for?
    • What is the difference between a “getter” and a “setter” method?
    • How do you make instance variables readable outside your class? Writeable? Both at the same time?
    • Can a class call its own class methods?
    • What’s the difference between when you would use a class variable and when you would use a constant?
    • What’s the difference between a class and a module?
    • When would you use a class but not a module?
    • How does inheritance work?
    • Why is inheritance really useful?
    • How do you extend a class? What does that mean?
    • What does #super do? Why use it?
  • Scope:
    • What is scope?
    • When can you start using a variable?
    • When is a new scope defined?
    • When are methods in scope?
    • What is a private method?
    • What is a protected method?
    • How are private and protected methods different?
    • What does “encapsulation” mean?

 Your Tasks:

1. Complete Codecademy’s Ruby tutorial (https://www.codecademy.com/learn/ruby). Sections 7, 9 and 10.

2. Read Beginning Ruby (http://peterc.org/beginningruby/index.html) Chapter 5: The Ruby Ecosystem and Community

3. Read Beginning Ruby (http://peterc.org/beginningruby/index.html) Chapter 6: Classes, Objects, and Modules

4. Read Beginning Ruby (http://peterc.org/beginningruby/index.html) Chapter 7: Projects and Libraries

5. Read Beginning Ruby (http://peterc.org/beginningruby/index.html) Chapter 8: Documentation, Error Handling, Debugging, and Testing.  You should skip pages 190-196 on testing.

6. For a deeper look at certain sections of the above material, check out these posts from Erik Trautman:

7. Read The Bastards Book of Ruby’s Exception and Error Handling (http://ruby.bastardsbook.com/chapters/exception-handling/) to reinforce your understanding of dealing with errors.

8. Read the Ruby Style Guide (https://github.com/bbatsov/ruby-style-guide) so you have an idea of how to make your code look more professional.


Test Yourself

Make sure you can do the following quizzes from Code Quizzes (http://www.codequizzes.com/). They are quite short and should give you an idea of what you still need to brush up on.


Additional Resources

  • View Kevin Berridge’s video presentation OOP: You’re Doing It Completely Wrong (Stir Trek Edition) (https://vimeo.com/91672848).  This covers major themes of practical object-oriented design, with many references to the Metz book in about 40 minutes.

 Project: OOP

Project 1: Tic Tac Toe

Remember Tic Tac Toe? See Wikipedia’s Tic-tac-toe (https://en.wikipedia.org/wiki/Tic-tac-toe) if you haven’t. It involves a couple of players, a simple board, checking for victory in a game loop… all the conditions that make it a fun little problem to solve.

Your Task:

Build a tic-tac-toe game on the command line where two human players can play against each other and the board is displayed in between turns.

1. Think about how you would set up the different elements within the game. What should be a class? Instance variable? Method? A few minutes of thought can save you from wasting an hour of coding.

2. Build your game, taking care to not share information between classes any more than you have to.



Example Solution

Afshinator’s solution (https://github.com/afshinator/playground/tree/master/ticTacToe)


Project 2: Mastermind

If you’ve never played Mastermind, a game where you have to guess your opponent’s secret code within a certain number of turns (like hangman with colored pegs), check it out on Wikipedia’s Mastermind (board game) (https://en.wikipedia.org/wiki/Mastermind_%28board_game%29). Each turn you get some feedback about how good your guess was – whether it was exactly correct or just the correct color but in the wrong space.


Your Task:

Build a Mastermind game from the command line where you have 12 turns to guess the secret code, starting with you guessing the computer’s random code.

Think about how you would set this problem up!

1. Build the game assuming the computer randomly selects the secret colors and the human player must guess them. Remember that you need to give the proper feedback on how good the guess was each turn!

2. Now refactor your code to allow the human player to choose whether she wants to be the creator of the secret code or the guesser.

3. Build it out so that the computer will guess if you decide to choose your own secret colors. Start by having the computer guess randomly (but keeping the ones that match exactly).

4. Next, add a little bit more intelligence to the computer player so that, if the computer has guessed the right color but the wrong position, its next guess will need to include that color somewhere. Feel free to make the AI even smarter.


Step 2: Files and Serialization

What if you want to save the state of your program? How about loading in a file? Some basic operations like these will be covered here.

Until now you’ve mostly been working with self-contained command line programs. It’s time to start branching out and interacting with files. Files are basically just collections of bits and bytes that you’ll somehow need to open, read into your program, modify, and save. Even though many files (like images) look like a giant jumble of data when you open them up in a text editor, it can be helpful to think of all files as one really long string, or stream, of bytes. Your script will read them in from top to bottom, performing whatever operations you specify along the way.

Lucky for you, Ruby makes your life pretty easy with regards to dealing with files. It has the tools necessary to read those long streams of bytes into your program and then allow you to work with them using the objects you’re familiar with. As long as you remember that the files are just a long stream of words/characters/bytes being read in from top to bottom, it should be fairly intuitive. If you want to do more detailed stuff like write to a specific point in a file, you’ll need to work out what position you’re at first, since you may be in the middle of it somewhere.

Working with files gets you into the idea of serialization, which basically just means converting your data into a storable format like a string. That’s very useful whether you’re thinking of saving your objects and classes (say, when you’re in the middle of a game) to a file or when you’re transmitting those same types of objects to the web browser (since the only way for information to travel via HTTP is as a string).

Luckily, Ruby again makes things pretty easy for you. There are some generally accepted formats for serializing data and Ruby gives you the tools you’ll need to work with all of them. The two you’ll run into again and again are YAML and JSON. You often see YAML used to save configuration files in Ruby on Rails because it’s very lightweight and straightforward. You can read it easily in a text editor. JSON is ubiquitous across the web, and is the format of choice to deliver complex or deeply nested data (like objects) from some website to your program via an API (like if you want to interface with Google Maps).

Finally, files and serialization overlaps in a lot of ways with the idea and purpose of databases. They facilitate the ability to maintain state and permanence for your data. We’ll briefly look into some basic database connections that Ruby provides as well.

Points to Ponder

Look through these now and then use them to test yourself after doing the tasks

  • What are two ways to store a file from your hard drive into a string or array in your Ruby script?
  • What are three things made possible or much easier by serialization?
  • What is JSON?
  • What is YAML?
  • How do you turn a Ruby object into JSON?
  • How do you turn JSON into a Ruby object?

Your Tasks

1. Read Ruby Monk’s 9.2 Using the `File` Class (http://rubymonk.com/learning/books/1/chapters/42-introduction-to-i-o/lessons/90-using-the-io-class)

2. Read Ruby Monk’s 2.4 Serializing (http://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/45-more-classes/lessons/104-serializing)

3. Read Beginning Ruby (http://peterc.org/beginningruby/) Chapter 4: Developing Your First Ruby Application and follow along with the tutorial.

4. Read Beginning Ruby (http://peterc.org/beginningruby/) Chapter 9: Files and Databases. At first you won’t often use the connection methods yourself (often an ORM like ActiveRecord for Rails will have that code already written for you), so feel free to skim over it but do try to see what Ruby is capable of.

5. Read The Bastard’s Book of Ruby File input/output (http://ruby.bastardsbook.com/chapters/io/)


 Additional Resources


Project: File I/O and Serialization

Event Manager

You’ll inevitably run into times when you’ll be working with CSV files and imperfect data. There is no such thing as a perfect dataset. Any time you find what looks like the perfect batch of data on something interesting, whether you’re trying to plot airline flight delays on a map, tease out the nuggets from a master list of nonprofits, or scrape 10,000 emails to mercilessly SPAM with your latest get-rich-quick scheme, it will be full of mistakes, omissions, and misspellings. Working with and cleaning up data go hand in hand.


Your Task


Project: Hangman

Files are a great way to save and reload a game.

Your Task

You will be building a simple command line Hangman game where one player plays against the computer, but a bit more advanced. If you’re unfamiliar with how Hangman works, see Wikipedia’s Hangman (game) (https://en.wikipedia.org/wiki/Hangman_%28game%29)

1. Download the 5desk.txt dictionary file from Scrapmaker.com (http://scrapmaker.com/view/twelve-dicts/5desk.txt).

2. When a new game is started, your script should load in the dictionary and randomly select a word between 5 and 12 characters long for the secret word.

3. You don’t need to draw an actual stick figure (though you can if you want to!), but do display some sort of count so the player knows how many more incorrect guesses he has before the game ends. You should also display which correct letters have already been chosen (and their position in the word, ie. _ r o g r a _ _ i n g) and which incorrect letters have already been chosen.

4. Every turn, allow the player to make a guess of a letter. It should be case insensitive. Update the display to reflect whether the letter was correct or incorrect. If out of guesses, the player should lose.

5. Now implement the functionality where, at the start of any turn, instead of making a guess the player should also have the option to save the game. Remember what you learned about serializing objects that you can serialize your game class too!

6. When the program first loads, add in an option that allows you to open one of your saved games, which should jump you exactly back to where you were when you saved. Play on!


Example Solution