Cannot access specific value of a hash - Rails - ruby-on-rails

Hello i have been trying to access the token value of the following hash with no avail
email.to[{:token=>"example", :host=>"HOSTNAME here", :email=>"example email", :full=>"example#email.com", :name=>nil}]
does it not email.to[:token] give me the value of token?
when i do that i get this
TypeError (no implicit conversion of Symbol into Integer):
if not what is the correct way to do it. Is there any point in doing a loop when i just need one value?

email.to method returns an Array that contains a Hash
[{:a=>"a", :b=>"b"}]
so you have to specify the index of an element in that array first
email.to[0][:a]
or
email.to.first[:a]
In order to access the Hash without an index, email.to method would have to return a Hash and not an Array type. So it would have to be something likes this
def to
{:a=>"a", :b=>"b"}
end

Related

submission of array of hashes

Assuming the following string of parameters which is composed of an array of hashes, what is the proper way to submit them to Rails
&auth=6db2f8aa0af80748&guest={surname:"Tizio",name:"Caio",type:"A"}&guest={surname:"Cane",name:"Pippo",type:"B"}&guest={surname:"Topo",name:"Giggio",type:"C"}'
What your string looks like says that it's about passing parameters in the query string of GET request.
To pass array of hashes you can use this syntax:
&auth=6db2f8aa0af80748&guest[][surname]=Tizio&guest[][name]=Caio&guest[][type]=A&guest[][surname]=Cane&guest[][name]=Pippo&guest[][type]=B&guest[][surname]=Topo&guest[][name]=Giggio&guest[][type]=C
On the server this string is interpreted as:
>> Parameters: {"auth"=>"6db2f8aa0af80748", "guest"=>[{"surname"=>"Tizio", "name"=>"Caio", "type"=>"A"}, {"surname"=>"Cane", "name"=>"Pippo", "type"=>"B"}, {"surname"=>"Topo", "name"=>"Giggio", "type"=>"C"}]}
While parsing query string, Rails interprets guest as an array because of [] following guest. guest[][surname] makes it create a hash with a key surname and add it to array guest. Next param guest[][name] is interpreted as part of a hash too, but instead of creating a new hash it will add this key-value pair to the last hash from guest. Other params will be added to that hash until the key which already exists in the hash is met. In this case a new hash will be created and added.

Rails, how to loop either array of hashes or only a hash

I am connecting to an API and I get array of hashes or only 1 hash for the data. So when the data comes as array of hashes;
"extras"=>{"extra"=>[{"id"=>"529216700000100800", "name"=>"Transfer Trogir - Dubrovnik (8 persons max)", "price"=>"290.0", "currency"=>"EUR", "timeunit"=>"0", "customquantity"=>"0", "validdatefrom"=>"1970-01-01", "validdateto"=>"2119-07-20", "sailingdatefrom"=>"1970-01-01", "sailingdateto"=>"2119-07-20", "obligatory"=>"0", "perperson"=>"0", "includedinbaseprice"=>"0", "payableoninvoice"=>"1", "availableinbase"=>"-1", "includesdepositwaiver"=>"0", "includedoptions"=>""}, {"id"=>"528978430000100800", "name"=>"Gennaker + extra deposit (HR)", "price"=>"150.0", "currency"=>"EUR", "timeunit"=>"604800000", "customquantity"=>"0", "validdatefrom"=>"1970-01-01", "validdateto"=>"2119-07-19", "sailingdatefrom"=>"1970-01-01", "sailingdateto"=>"2119-07-19", "obligatory"=>"0", "perperson"=>"0", "includedinbaseprice"=>"0", "payableoninvoice"=>"1", "availableinbase"=>"-1", "includesdepositwaiver"=>"0", "includedoptions"=>""}]
I'am looping through the array to get the values as;
b["extras"]["extra"].each do |extra|
puts extra["id"]
puts extra["name"]
end
But when this is not array; only 1 hash, then this is not working, adding each loop makes it array but not array of hashes;
"extras"=>{"extra"=>{"id"=>"640079840000100800", "name"=>"Comfort package (GRE)", "price"=>"235.0", "currency"=>"EUR", "timeunit"=>"0", "customquantity"=>"0", "validdatefrom"=>"1970-01-01", "validdateto"=>"2120-03-25", "sailingdatefrom"=>"2015-01-01", "sailingdateto"=>"2120-03-25", "obligatory"=>"1", "perperson"=>"0", "includedinbaseprice"=>"0", "payableoninvoice"=>"1", "availableinbase"=>"-1", "includesdepositwaiver"=>"0", "includedoptions"=>""}}
b["extras"]["extra"].each do |extra|
puts extra["id"]
puts extra["name"]
end
This time, that gives error TypeError (no implicit conversion of String into Integer);
When I type puts extra.inspect; I get ["id", "640079840000100800"]. So to make it work I should pass extra[1] to get the id number.
But I can not predict either array of hashes or only hash. Is there any easy way to solve this issue that works either array of hashes or just a hash?
Naïve solution: one might check the object’s type upfront:
case b["extras"]["extra"]
when Array
# handle array
when Hash
# handle hash
end
Proper solution: produce an array of hashes no matter what came.
[*[input]].flatten
and deal with it as with an array having at least one hash element (with each.)
Please also refer to valuable comment by #Stefan below if you have no allergy using Rails helpers.
You could try to use Object#kind_of? to determine whether it is an Array or a Hash instance.
if b["extras"]["extra"].kind_of? Array
# handle array
elsif b["extras"]["extra"].kind_of? Hash
# handle hash
end

Serialize Params to store in Database for Logging

I am processing the payment and looking to dump the content i receive from the Gateway into my DB for logging.
#order[:payment_details] = params.to_json.to_s
Getting the following error
no implicit conversion of Symbol into Integer
This error means that #order is an array - the keys must be integers. This sounds like you expected #order to be a hash or activerecord object - review where #order is created.
I think you have no need to explicitly convert params to JSON just declare you params details as
serialize :payment_details
in your model it automatically serialize you params hash and on time of fetching deserialize your hash for reading.
An above error is due to you are trying to convert symbol i.e key in params to integer.

How do you access an object's (ActiveRecord::Relation) value by key in Ruby on Rails?

tl;dr How do I get the corresponding value with the key of an object?
I'm confused why
Atag.where(tag:'brand') gives me what I would call an object for lack of a better term: #<ActiveRecord::Relation [#<Atag id: 1, tag: "brand", created_at: "2015-01-31 04:29:20", updated_at: "2015-01-31 04:29:20">]>
But I'm having the basic difficult of accessing the corresponding value for the key :id.
Atag.where(tag:'brand').id and Atag.where(tag:'brand')[:id] and Atag.where(tag:'brand')(:id) all throw errors, while in this case I'm just trying to have the integer 1 returned.
I seem to be unable to ruby, nor find a succinct answer to this basic question with my google searching skills (or lack there of).
Thanks
From great documentation at the Odin Project.
The key thing to note is that #find returns the actual record while #where returns an ActiveRecord::Relation which basically acts like an array.
So if you're using #where to find a single record, you still need to remember to go into that "array" and grab the first record, e.g. User.where(:email => "foo#bar.com")[0] or User.where(:email => "foo#bar.com").first.
This gets me all the time...
Get the id of your tag = 'brand' with following query:
Atag.find_by(tag:'brand').id
Check following variations:
Atag.find(1)
#gives you the object with the Atag id = 1
Atag.find(100) #let's say this record does not exist then you will
get ActiveRecord::RecordNotFound exception.
Better option :
Atag.where(id: 1)
#this returns you a relation and it's true you are trying to access
only a single object.
Hence, you just need to modify it to :
Atag.where(id: 1).first
#Above one will give you an object of Atag not an association result.
# to verfiy you can execute, Atag.where(id: 1).first.class
Atag.where(id: 999).first
# In this case if there is no record found with id = 999, then it'll
return nil which can be easily handled than an exception found
while using find method.
Get the same flavor using the dynamic finders.
Atag.find_by(id: 1) #gives the Atag with id 1
Atag.find_by_id(1). # same as above.
Atag.find_by(id: 999) #if not found then simply returns nil.
Atag.find_by(name: 'ruby') #return Atag object with name: 'ruby'
Atag.find_by_name('ruby') #same as above.
Yep, looks like you figured it out. For reference, you can use Atag.where(tag:'brand').first to get the first result, and Atag.where(tag:'brand').to_a to get an array of all the matching results.
where return instance of ActiveRecord::Relation which can be treated like an array with records as its members. Even if the result is single it should be accessed like a member of array with single element
Atag.where(tag: 'brand')
returns the array of results and to access id we should get the record from the array first i.e.
Atag.where(tag: 'brand')[0].id
In order to get id of all the matching records we need to use pluck with where. pluck returns an array of attribute that is plucked.
Atag.where(tag: 'brand').pluck(:id)
This would return an array of id from the collection returned by where only.
The find_by method finds the first record matching some conditions. Since find_by returns the record (not an array) , we can do:
Atag.find_by(tag: 'brand').id
PS: No one had mentioned pluck that's why I wrote this answer. Hope its helpful.

Iterate to every element of the multidimension array in ruby

I have a array i getting through an xml .i want to iterate every element to the array which is hash and get the every hash element value using key.
I want to someting like this>>
array>>
education_split = [{"University"=>"Institute Of Engineering And Emerging Technologies", "Degree"=>"MBA", "Year"=>"2007"}, {"University"=>"H.N.B. Garhwal University", "Degree"=>"MSC", "Year"=>"2005"}, {"University"=>"H.P. University", "Degree"=>"Med", "Year"=>"2003"}, {"University"=>nil, "Degree"=>"12th", "Year"=>"1999"}, {"University"=>nil, "Degree"=>"10th", "Year"=>nil}]
now i want to iterate to every element of the array and get the value of university ,degree,year in iteration. something like that..
education_split.each do |edu|
//here are some other things also like creating object
edu["University"]
edu ["Degree"]
edu["Year"]
end
This is also working but in some cases it is though error >> TypeError (no implicit conversion of String into Integer)
here all fields are string and values i am getting are also string.
Just need to check a hash :
education_split.each do |edu|
//here are some other things also like creating object
if edu.is_a? Hash
edu["University"]
edu ["Degree"]
edu["Year"]
end
end
Reading the error, I am sure your collection education_split contains also arrays with hashes. Now to prevent the error and as you interested only to hash that part of the code, just do a check if edu in any particular iteration, is a hash or not. if hash, do your operation or skip it.
TypeError (no implicit conversion of String into Integer) only comes, when you would try to get array elements using strings, instead of integers. Like a = [1, 2], and now do a['x'], and see you would get the exact error you are now getting.

Resources