Reputation: 323
An exercise says:
Create three hashes called person1, person2, and person3, with first and last names under the keys
:first
and:last
. Then create a params hash so thatparams[:father]
is person1,params[:mother]
is person2, andparams[:child]
is person3. Verify that, for example,params[:father][:first]
has the right value.
I did
person1 = {first: "Thom", last: "Bekker"}
person2 = {first: "Kathy", last: "Bekker"}
person2 = {first: "Anessa", last: "Bekker"}
then the params
hash in Rails
params = {}
params[:father] = person1
params[:mother] = person2
params[:child] = person3
Now I can ask for father, mother or child's first or last name like so
params[:father][:first]
gives me "Thom"
.
What makes params[:father][:first][:last]
return an error? Is there a way to make that return "Thom Bekker"
?
I have no way to check if the way I came up with is correct, is there a better way to do the exercise?
Is there a reason why symbol:
is better than symbol =>
?
Upvotes: 0
Views: 154
Reputation: 727
In Ruby, using square brackets on the Hash or other classes is actually using a method available for an object of that class (this one). When you call these methods in your example, each of these methods will be called and will return its result before the next method is called. So, as you've defined it:
- Calling
[:father]
onparams
returns the hash represented byperson1
[:first]
is then called on{first: "Thom", last: "Bekker"}
, returning the corresponding value in the hash,"Thom"
[:last]
is called on"Thom"
, which results in an error. Calling square brackets on a string with an integer between them can access the character in a string at that index (person1[:first][0]
returns"T"
), but"Thom"
doesn't have a way of handling the:last
symbol inside the square brackets.
There are a number of ways you could get the names printed as you wanted, one of the simplest being combining the string values in person1
:
params[:father][:first] + " " + params[:father][:last]
returns "Thom Bekker"
Upvotes: 2
Reputation: 4580
So here's my question, what exactly makes params[:father][:first][:last] return an error? Is there a way to make that return "Thom Bekker"?
Both of these would work
params[:father][:first] + params[:father][:last]
params[:father].values.join(' ')
But maybe it would be better to think about them like the nested structures that they are:
father = params[:father]
name = father[:first] + father[:last]
puts name
To answer your last question, pretend that there's no difference between a hashrocket =>
and symbol:
. This is one where you don't need to care for a long time. Maybe around year 2 start asking this again, but for learning treat them as if they were equivalent.
(Full disclosure, there are differences, but this is a holy war that you really don't want to see played out)
Upvotes: 0
Reputation: 84333
You're misunderstanding the type of object you're getting back. params[:father]
returns a single Hash object, not an Array or an Array of hashes. For example:
params[:father]
#=> {:first=>"Thom", :last=>"Bekker"}
params[:father].class
#=> Hash
So, you can't access the missing third element (e.g. :last
) because there's no such element within the value of params[:father][:first]
.
Instead, you could deconstruct the Hash:
first, last = params[:father].values
#=> ["Thom", "Bekker"]
or do something more esoteric like:
p params[:father].values.join " "
#=> "Thom Bekker"
The point is that you have to access the values of the Hash, or convert it to an Array first, rather than treating it directly like an Array and trying to index into multiple values at once.
Upvotes: 2