We'll store a little more information about our games than just the name. Optional arguments are important for a flexible interface. Let's change our new_game
method so it can be called without passing in year
or system
.less
def new_game(name, year, system) { name: name, year: year, system: system } end game = new_game("Street Figher II", nil, nil)
Answer:ide
def new_game(name, year=nil, system=nil) { name: name, year: year, system: system } end game = new_game("Street Figher II")
Defaulting two arguments to nil
isn't ideal. Update the method signature and implementation to take an optional options
hash with keys for :year
and :system
.flex
def new_game(name, year=nil, system=nil) { name: name, year: year, system: system } end game = new_game("Street Figher II", "SNES", 1992)
Answer:this
def new_game(name, options={}) { name: name, year: options[:year], system: options[:system] } end game = new_game("Street Figher II", year: 1992, system: "SNES")
We want to make sure that each game is a valid game object - in this case a simple hash of values. Even still, we wouldn't want to return a hash with a nil
name. Raise an InvalidGameError
error in the new_game
method if name is nil.idea
class InvalidGameError < StandardError; end def new_game(name, options={}) { name: name, year: options[:year], system: options[:system] } end begin game = new_game(nil) rescue InvalidGameError => e puts "There was a problem creating your new game: #{e.message}" end
Answer:spa
class InvalidGameError < StandardError; end def new_game(name, options={}) raise InvalidGameError, "You must provide a name for the game" unless name { name: name, year: options[:year], system: options[:system] } end begin game = new_game(nil) rescue InvalidGameError => e puts "There was a problem creating your new game: #{e.message}" end
When passing in an array of arguments to a method, sometimes it'll make sense to use Ruby's "splat" operator rather than explicitly requesting an array. Update the describe_favorites
method and the call to it to instead use the splat operator.code
def describe_favorites(*games) for game in games puts "Favorite Game: #{game}" end end describe_favorites(['Mario', 'Contra', 'Metroid'])
Answer:orm
def describe_favorites(*games) for game in games puts "Favorite Game: #{game}" end end describe_favorites('Mario', 'Contra', 'Metroid')
Passing around hashes is getting troublesome, let's use a class to hold our data. We've started the Game class for you, now please implement the initialize method to store name, system and year in instance variables.blog
class Game def initialize(name, options={}) end end
Answer:ci
class Game def initialize(name, options={}) @name = name @year = options[:year] @system = options[:system] end end
Whoever created the game object will want to be able to access the name
, year
and system
for the game, but that doesn't mean we need to make getter
methods for them. Refactor the code below to make these variables available using the Ruby way with attr_accessor
.
class Game def initialize(name, options={}) @name = name @year = options[:year] @system = options[:system] end def name @name end def year @year end def system @system end end
Answer:
class Game attr_accessor :year, :system, :name def initialize(name, options={}) @name = name @year = options[:year] @system = options[:system] end end
When a game is initialized, store another variable called created_at
which is set to Time.now
in the initialize method. Make sure it can be accessed, but that it cannot be set from outside the object.
class Game attr_accessor :name, :year, :system def initialize(name, options={}) @name = name @year = options[:year] @system = options[:system] end end
Answer:
class Game attr_accessor :name, :year, :system attr_reader :created_at def initialize(name, options={}) @name = name @year = options[:year] @system = options[:system] @created_at = Time.now end end