Accessing a Ruby Hash with a Variable as the Key

How to access a symbol hash key using a variable in Ruby

You want to convert your string to a symbol first:

another_family[somevar.to_sym]

If you want to not have to worry about if your hash is symbol or string, simply convert it to symbolized keys

see: How do I convert a Ruby hash so that all of its keys are symbols?

Accessing a Ruby hash with a variable as the key

It looks like you want to exec that last line, as it's obviously a shell command rather than Ruby code. You don't need to interpolate twice; once will do:

exec("rsync -ar root@#{environments['testing']}:/htdocs/")

Or, using the variable:

exec("rsync -ar root@#{environments[current_environment]}:/htdocs/")

Note that the more Ruby way is to use Symbols rather than Strings as the keys:

environments = {
:testing => '11.22.33.44',
:production => '55.66.77.88'
}

current_environment = :testing
exec("rsync -ar root@#{environments[current_environment]}:/htdocs/")

Accessing hash value with variable

Try this:

print "Enter number "
num = gets.chomp().to_i
puts "Value: #{DHASH[num]}"

Accessing hash values with a variable in Ruby is wonderfully easy! You just make sure the variable has the proper key, and then use the variable instead of the key. In your case, the number that you are getting will be a string, and you need it to be an integer, so you need to turn it into an integer. And you need to correct the string interpolation.

How do I set a variable as a key when I call my hash value?

The easiest is just to update

puts "point #{card_value[:card]}"

To

puts "point #{card_value[random_card.to_sym]}"

The reason is card_value[:card] is trying to get from the card_value hash they card key, which doesn't exist.

Your random_card function returns a "random" string value from the cards array defined in its body, being a string, you'll get the same error, as the keys in the card_value are symbols, so you need to convert that result to a symbol.



Answering to the dx7 nice addition.

You can just declare a CARD_VALUES hash, containing card names and points, which you can then pick up with Array#sample, so you avoid adding a useless instance variable for the card, and having to pass it as a method argument when calling random_card:

CARD_VALUES = { two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7, eight: 8, nine: 9, ten: 10,
jack: 10, queen: 10, king: 10, ace: 11 }

def random_card
CARD_VALUES.to_a.sample
end

def move
loop do
puts '"hit" or "stick"'
input = gets.chomp
if input == 'hit'
card, point = random_card
puts "card: #{card}"
puts "point: #{point}"
end
break if input == 'stick'
end
end

move

Access Ruby hash variables

Try request.params["model"]["password"]

A Hash's keys can consist of both symbols and strings. However, a string key is different than a symbol key.

Note the following:

h = {:name => 'Charles', "name" => 'Something else'}
h[:name] #=> 'Charles'
h["name"] #=> 'Something else'

EDIT:

In your particular situation, it appears request.params["model"] returns a string instead of a hash. There is a method String#[] which is a means of getting a substring.

s = "Winter is coming"
s["Winter"] #=> "Winter"
s["Summer"] #=> nil

This would explain your comments.

There are a couple things you can do to remedy your specific situation. I have found the most simplest way to be using JSON. (I'm sure there are others and maybe those will surface through other answers or through comments.)

require 'json'
hash_of_params = JSON.load(request.params["model"]).to_hash
hash_of_params["password"] #=> "36494092d7d5682666ac04f62d624141"

How to set a hash key using a variable in Ruby 1.9?

Let me introduce you two ways to do what you exactly want. If you don't want to continue using 1.8 syntax and hashrockets anymore, ruby-doc.org recommends doing it in this way in Ruby 1.9.3:

my_hash = Hash.new

my_key = "key000"
my_hash[my_key] = "my_value"

Livedemo: http://ideone.com/yqIx2M

Second one (more similar to what you are trying to achieve) is:

my_key = "key0"
my_hash = Hash[my_key, "value00"]

puts my_hash

Livedemo: http://ideone.com/HHLyAi

ruby acces hash with variable as key

After OP's edit, use

my_pc = `hostname`.strip

to avoid newline in your string.

This does work as expected,

> my_pc
=> "TSL-PCM-126"
> puts inventory["all"]["children"]["#{my_pc}"]
{"children"=>{"my_host-TSL-PCM-126"=>{"hosts"=>{"TSF-W01"=>{"ip"=>"192.168.0.201"}}

You do not need string interpolation though:

> inventory["all"]["children"][my_pc]
=> {"children"=>{"my_host-TSL-PCM-126"=>{"hosts"=>{"TSF-W01"=>{"ip"=>"192.168.0.201"}}}}}

You either have a typo in your variable/hash or you're trying to assign the return value of puts, which is nil.

Ruby access hash value by a variable

Old good recursive Ruby 1.9+ solution:

hash = {:test => {:foo => true}}
path = [[:test],[:foo]]

path.flatten.reduce(hash) { |h, p| h[p] }
#⇒ true

Or, as @Stefan suggested in comments:

path.reduce(hash) { |h, (p)| h[p] }
# or even
path.reduce(hash) { |h, p| h[p.first] }

More defensive:

path.flatten.reduce(hash) { |h, p| h.nil? ? nil : h[p] }

Confused about the million ways to reach inside Ruby Hash with the symbol sign

Rule of thumb

If there's a colon (:) it's a Symbol. If there's a hashrocket (=>), it's whatever is to the left of the hashrocket (which can be anything).

Declaring keys in a Hash literal

When we say "Hash literal" we mean code that declares a Hash with curly braces ({ foo: 1 }) or as method arguments (bar(baz: 2)).

There are two ways to declare a key in a Hash literal.

Keys with hashrockets (=>)

The first way to declare a key is with the hashrocket (=>). When you use the hashrocket, the key is whatever value is to the left of it, and you can put any kind of object (or expression) to the left of it:

hashrocket_hash = {
"I am a String" => 1,
:I_am_a_Symbol => 2,
:"I am also a Symbol" => 4,
/I am a Regexp!/ => 5,
Kernel => 6,
if true then "I am also a String" end => 7,
nil => 8
}

p hashrocket_hash.keys
# => [ "I am a String",
# :I_am_a_Symbol,
# :"I am also a Symbol",
# /I am a Regexp!/,
# Kernel,
# "I am also a String",
# nil
# ]

p hashrocket_keys.map(&:class)
# => [ String,
# Symbol,
# Symbol,
# Regexp,
# Module,
# String,
# NilClass
# ]

Keys with colons (:)

The other way to declare a key is with a colon (:). When you use a colon the resulting key is always a Symbol. The usual Symbol rules apply (read the very thorough answer here: What can a ruby symbol (syntax) contain?) except the colon goes at the end instead of the beginning:

colon_hash = {
I_am_a_Symbol: 9,
"I am also a Symbol": 10
}

p colon_hash.keys
# => [ :I_am_a_Symbol,
# :"I am also a Symbol" ]

p colon_hash.keys.map(&:class)
# => [ Symbol,
# Symbol ]

Accessing a Hash value

There are no special rules for accessing a Hash value. If you want to access a value whose key is a Symbol, you must use a Symbol. If you want to access a value whose key is a String, you must use a String. If the key is something else, you must use that thing.

In the below examples, pay close attention to which keys are followed by colons and which are followed by hashrockets:

hsh1 = { foo: 1 }
p hsh1[:foo] # => 1
p hsh1[:"foo"] # => 1
p hsh1["foo"] # => nil

hsh2 = { "bar": 2 }
p hsh2[:bar] # => 2
p hsh2[:"bar"] # => 2
p hsh2["bar"] # => nil

hsh3 = {
Kernel: 3,
Kernel => 4
}
p hsh3[:Kernel] # => 3
p hsh3[Kernel] # => 4
p hsh3["Kernel"] # => nil

Ruby: Creating a hash key and value from a variable in Ruby

If you want to populate a new hash with certain values, you can pass them to Hash::[]:

Hash["a", 100, "b", 200]             #=> {"a"=>100, "b"=>200}
Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}

So in your case:

Hash[id, 'foo']
Hash[[[id, 'foo']]]
Hash[id => 'foo']

The last syntax id => 'foo' can also be used with {}:

{ id => 'foo' }

Otherwise, if the hash already exists, use Hash#=[]:

h = {}
h[id] = 'foo'


Related Topics



Leave a reply



Submit