hellogoodbye hellogoodbye - 6 months ago 10
Ruby Question

Is this possible with hashes in Ruby?

class Card
suit = {"C":"C", "D":"D", "H":"H", "S":"S"}
rank = { :A => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10, :J => 11, :Q => 12, :K => 13}
end

card = Card.new

puts(card.rank["A"])


I have this code and I have a couple of questions.

Firstly, instead of doing
2 => 2
, why cant i just do
:2 : 2
or
2 : 2

Secondly, what is the point of attributes if I cant access them like I have tried to above? Do i need to feed the attribute into a method and then call that method?

Answer

Firstly, instead of doing 2 => 2, why cant i just do :2 : 2 or 2 : 2

key: value is a shortcut for :key => value, i.e. it treats key as a symbol.

2: 2 doesn't work, because :2 is not a valid symbol. You could use '2': 2 instead, but it uses :'2' (a symbol) as the key, not 2 (a number).

However, symbols don't make much sense here, because you want to look up strings:

card.rank["A"] # <= "A" is not :A

Secondly, what is the point of attributes if I cant access them like I have tried to above?

These are not attributes, but local variables. Attributes work like this:

class Card
  attr_reader :suit, :rank

  def initialize
    @suit = { 'C' => 'C', 'D' => 'D', 'H' => 'H', 'S' => 'S' }
    @rank = { 'A' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, '10' => 10, 'J' => 11, 'Q' => 12, 'K' => 13 }
  end
end

card = Card.new

card.rank      #=> {"A"=>1, "2"=>2, "3"=>3, "4"=>4, "5"=>5, "6"=>6, "7"=>7, "8"=>8, "9"=>9, "10"=>10, "J"=>11, "Q"=>12, "K"=>13}
card.rank['A'] #=> 1

It makes probably more sense to use constants:

class Card
  SUITS = { 'C' => 'C', 'D' => 'D', 'H' => 'H', 'S' => 'S' }
  RANKS = { 'A' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, '10' => 10, 'J' => 11, 'Q' => 12, 'K' => 13 }
end

Card::RANKS['A'] #=> 1

And use attributes for the suit and rank of a specific card:

class Card
  SUITS = { 'C' => 'C', 'D' => 'D', 'H' => 'H', 'S' => 'S' }
  RANKS = { 'A' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, '10' => 10, 'J' => 11, 'Q' => 12, 'K' => 13 }

  attr_reader :suit, :rank

  def initialize(suit, rank)
    @suit = suit
    @rank = rank
  end

  def value
    RANKS[rank]
  end
end

card = Card.new('C', 'A')

card.suit    #=> "C"
card.rank    #=> "A"
card.value   #=> 1