submission of array of hashes - ruby-on-rails

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.

Related

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

How to convert rails active resource object to hash?

Let's say I have some active resource object fetched as the following:
x = Resource.find(some_id)
And x in the remote server has some field h as a complex nested hashes which is represented here as nested active resource objects, but then accessing it is a tedious task, so is it possible to convert h to hash? I can just make another call Resource.get(some_id) and the result will be one big hash, but this is risky as the resource -theoretically- may have changed between subsequent calls, so is there a way to convert active resource object to hash ?
Edit
For more clarification, Suppose that some invoice record r[id=some_id] has attribute extras, which is a hash with the value: {:x=>1, :y=>2, :z=>{:a=>1, :b=>2}}
Then when fetching this record through active resource, we get the following result for extras field, -extracted from the response-:
"extras"=>
#<App::Invoice::Extras:0x00000008202cb0
#attributes=
{"x"=>1,
"y"=>2,
"z"=>
#<App::Invoice::Extras::Z:0x00000008201978
#attributes={"a"=>1, "b"=>2},
#persisted=true,
#prefix_options={}>},
#persisted=true,
#prefix_options={}>,
Then how to convert this extras field to a ruby hash ?
JSON.parse(x.to_json) did the trick.
Try:
x = Resource.find(some_id)
hash = OpenStruct.new(x).to_h
or
hash = OpenStruct.new(x.attributes).to_h

Convert a hash of objects to json in Ruby

I have a hash H which should contain various users as json. "users" list contains all users and every user object contains various user's details like name, age etc. I don't want to iterate over every user in the list and do user.as_json and then merge into the hash.
Is there a single line query which does this?
You can do this, in your action convert it to JSON by using to_json
#users = users.to_json
In the Javascript code, parse it using jQuery's $.parseJSON()
$.parseJSON(#users)

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.

ruby on rails session data returns false even when data exists

I have a code like,
session[:my_data] = 'abcd'
and when i try to get,
puts session.has_key?("my_data") then it returns false always.
Ruby allows any object to be a hash key. If the hash key is a symbol, you will not be able to access it using a string.
In this case, you have various options:
convert the string to a symbol
session.has_key?("my_data".to_sym)
use Rails' with_indifferent_access method to allow both symbol and string queries on the hash
s = session.with_indifferent_access
puts s.has_key?("my_data")

Resources