AltBrian
AltBrian

Reputation: 2562

How to get a default value with hashes in ruby

I am trying to get a default value whilst using hashes in ruby. Looking up the documentation you use a fetch method. So if a hash is not entered then it defaults to a value. This is my code.

def input_students
  puts "Please enter the names and hobbies of the students plus country of    birth"
  puts "To finish, just hit return three times"

  #create the empty array
  students = []
  hobbies = []
  country = []
  cohort = []

  # Get the first name
  name = gets.chomp
  hobbies = gets.chomp
  country = gets.chomp
  cohort = gets.chomp

  while !name.empty? && !hobbies.empty? && !country.empty? && cohort.fetch(:cohort, january) do #This is to do with entering twice
    students << {name: name, hobbies: hobbies, country: country, cohort: cohort} #import part of the code.
    puts "Now we have #{students.count} students"

    # get another name from the user
    name = gets.chomp
    hobbies = gets.chomp
    country = gets.chomp
    cohort = gets.chomp
  end
  students
end

Upvotes: 17

Views: 27374

Answers (2)

dinjas
dinjas

Reputation: 2125

You just need to give fetch a default it can handle. It doesn't know what to do with january as you haven't declared any variable with that name. If you want to set the default value to the string "january", then you just need to quote it like this:

cohort.fetch(:cohort, "january") 

There are some decent examples in the documentation for fetch.

Also, cohort isn't a Hash, it's a String since gets.chomp returns a String. fetch is for "fetching" values from a Hash. The way you're using it should be throwing an error similar to: undefined method 'fetch' for "whatever text you entered":String.

Finally, since you're using it in a conditional, the result of your call to fetch is being evaluated for its truthiness. If you're setting a default, it will always be evaluated as true.

If you just want to set a default for cohort if it's empty, you can just do something like this:

cohort = gets.chomp
cohort = "january" if cohort.empty?
while !name.empty? && !hobbies.empty? && !country.empty?
  students << {
    name: name,
    hobbies: hobbies,
    country: country,
    cohort: cohort
  }
  ... # do more stuff

Hope that's helpful.

Upvotes: 29

Cary Swoveland
Cary Swoveland

Reputation: 110685

You have several options. @dinjas mentions one, likely the one you want to use. Suppose your hash is

h = { :a=>1 }

Then

h[:a] #=> 1
h[:b] #=> nil

Let's say the default is 4. Then as dinjas suggests, you can write

h.fetch(:a, 4) #=> 1
h.fetch(:b, 4) #=> 4

But other options are

h.fetch(:a) rescue 4 #=> 1
h.fetch(:b) rescue 4 #=> 4

or

h[:a] || 4 #=> 1
h[:b] || 4 #=> 4

You could also build the default into the hash itself, by using Hash#default=:

h.default = 4
h[:a] #=> 1
h[:b] #=> 4

or by defining the hash like so:

g = Hash.new(4).merge(h)
g[:a] #=> 1
g[:b] #=> 4

See Hash::new.

Upvotes: 24

Related Questions