I have this:
produtos = LineItem.select('codigosku, quantity').where("cart_id = #{session[:cart_id] } ")
I need to insert the result of this select (produto variable), here:
message = Hash.new
message = {
"tem:carrinho" => {"gpa:CEP" => params[:cep],
"gpa:CNPJ" => 'doc',
"gpa:IdCampanha" => 1111,
"gpa:Produtos" => {"gpa:DadosListaProdutoCarrinhoDTO" =>
{
HERE! VALUES OF "PRODUTOS VARIABLE"
}
}
}
}
How can I do this?
Thanks in advance!
create your array:
line_items_array = line_items.map{|li| li.attributes }
Then insert the array within your hash.
like in apneadiving example, use map to create an array from the produtos data; use attributes to return all data (it is a hash) from your selected data
message = {
"tem:carrinho" => {
"gpa:CEP" => params[:cep],
"gpa:CNPJ" => 'doc',
"gpa:IdCampanha" => 1111,
"gpa:Produtos" => {
"gpa:DadosListaProdutoCarrinhoDTO" => produtos.map { |item| item.attributes }
}
}
}
or if you need to be more specific about the keys in the produtos and append it after initialization
# initialize the Produtos to nil
message = {
"tem:carrinho" => {
"gpa:CEP" => params[:cep],
"gpa:CNPJ" => 'doc',
"gpa:IdCampanha" => 1111,
"gpa:Produtos" => nil
}
}
# build an array of DadosListaProdutoCarrinhoDTO
list = produtos.map do |item|
{
"gpa:DadosListaProdutoCarrinhoDTO" => {
"codigosku" => item.codigosku,
"quantity" => item.quantity
}
}
end
# set the Produtos key to an array of DadosListaProdutoCarrinhoDTO
message["tem:carrinho"].merge!({ "gpa:Produtos" => list })
Related
I have a Ruby hash that I need to convert to another format.
Considering that the 'array' size is unknown/unlimited, how would you 'flatten' this hash into the desired format?
Original Hash
{
:parameters => {
:'userResponse.objectInstanceType' => 'QuesAnsResponse',
:'userResponse.quesAnsDetailArray' => {
:'0' => {
'.answer'=> 'Texas'
},
:'1' => {
'.answer' => 'w3schools'
}
}
}
}
Desired Format:
{
:parameters => {
:'userResponse.objectInstanceType' => 'QuestionAnsResponse',
:'userResponse.quesAnsDetailArray[0].answer' => 'Texas',
:'userResponse.quesAnsDetailArray[1].answer' => 'w3schools'
}
}
If you can make a few assumptions about the structure of the input i.e. that it has the numbered responses inside a "userResponse.quesAnsDetailArray" section then you could do something along these lines:
new_hash = { 'parameters' =>
{ 'userResponse.objectInstanceType' => 'QuestionAnsResponse' } }
hash['parameters']['userResponse.quesAnsDetailArray'].each_pair do |index, details|
details.each_pair do |field, value|
new_hash['parameters']["userResponse.quesAnsDetailArray[#{index}]#{field}"] = value
end
end
I have assumed the hash is as follows:
h = {
'parameters'=> {
'userResponse.objectInstanceType'=> 'QuesAnsResponse',
'userResponse.quesAnsDetailArray'=> {
'0'=> {
'.answer'=> '',
'.answerFieldType'=> 'text',
'.isRequired'=> 'true',
'.metaData'=> 'QUESTION_1',
'.questionFieldType'=> 'label',
'.question'=> 'What is the name of your state?'
},
'1'=> {
'.answer'=> '',
'.answerFieldType'=> 'text',
'.isRequired'=> 'true',
'.metaData'=> 'QUESTION_2',
'.questionFieldType'=> 'label',
'.question'=> 'What is the name of your first school'
}
}
}
}
and would convert it to the desired format as follows:
{ 'parameters'=> Hash[[
['userResponse.objectInstanceType',
h['parameters']['userResponse.objectInstanceType']],
*h['parameters']['userResponse.quesAnsDetailArray'].
flat_map { |ndx,f|
["userResponse.quesAnsDetailArray[#{ndx}]"].product(f.to_a) }.
map { |prefix,(suffix,value)| [prefix+suffix, value] } ]]
}
#=> {"parameters"=>
{"userResponse.objectInstanceType"=>"QuesAnsResponse",
"userResponse.quesAnsDetailArray[0].answer"=>"",
"userResponse.quesAnsDetailArray[0].answerFieldType"=>"text",
"userResponse.quesAnsDetailArray[0].isRequired"=>"true",
"userResponse.quesAnsDetailArray[0].metaData"=>"QUESTION_1",
"userResponse.quesAnsDetailArray[0].questionFieldType"=>"label",
"userResponse.quesAnsDetailArray[0].question"=>
"What is the name of your state?",
"userResponse.quesAnsDetailArray[1].answer"=>"",
"userResponse.quesAnsDetailArray[1].answerFieldType"=>"text",
"userResponse.quesAnsDetailArray[1].isRequired"=>"true",
"userResponse.quesAnsDetailArray[1].metaData"=>"QUESTION_2",
"userResponse.quesAnsDetailArray[1].questionFieldType"=>"label",
"userResponse.quesAnsDetailArray[1].question"=>
"What is the name of your first school"}}
I have this situation:
skeleton =
{
"timeline" =>
{
"data" => []
}
}
template =
{
"A" => "",
"B" => "",
"C" => "",
}
From the controller I make a query which returns me an array of hashes:
#cdr = Cdr.select("start, end, clid")
then I iterate over the array and set the "template" hash fields and in the last step I append this hash to an array which belongs to "skeleton" hash:
#cdr.each do |cdr|
template["A"] = cdr.start
template["B"] = cdr.end
template["C"] = cdr.clid
skeleton["timeline"]["data"] << template
end
so to expected result is:
skeleton =
{
"timeline" =>
{
"data" => [
{
"A" => "sample1",
"B" => "sample2",
"C" => "sample3",
},
{
"A" => "sample4",
"B" => "sample5",
"C" => "sample6",
}
]
}
}
but the real result I'm getting is:
skeleton =
{
"timeline" =>
{
"data" => [
{
"A" => "sample1",
"B" => "sample2",
"C" => "sample3",
},
{
"A" => "sample1",
"B" => "sample2",
"C" => "sample3",
}
]
}
}
all entries in the array contain same data. Why?
Try creating a new template array through each cycle through. I don't think you can change the value of the key while it is being used as a key.
#cdr.each do |cdr|
temp_inst = template.clone
temp_inst["A"] = cdr.start
temp_inst["B"] = cdr.end
temp_inst["C"] = cdr.clid
skeleton["timeline"]["data"] << temp_inst
end
I have that deep Hash of hashes:
my_hash = {
:category_1 => {
:solution_1 => { :order => 1 },
:solution_2 => { :order => 2 }
},
:category_2 => {
:solution_3 => { :order => 3 },
:solution_4 => { :order => 4 }
}
}
I want to sort :solution_* hashes under :category_* hashes by key :order. Any suggestions?
(fixed)
Let's say you have the following hash of people to ages:
people = {
:fred => { :name => "Fred", :age => 23 },
:joan => { :name => "Joan", :age => 18 },
:pete => { :name => "Pete", :age => 54 }
}
use sort_by to get where we want to go:
people.sort_by { |k, v| v[:age] }
# => [[:joan, {:name=>"Joan", :age=>18}],
[:fred, {:name=>"Fred", :age=>23}],
[:pete, {:name=>"Pete", :age=>54}]]
Ok, you didn't specify your question, so I'm assuming you want one layer removed. I changed the starting hash a bit to actually see if the sorting works:
my_hash = {
:category_1 => {
:solution_1 => { :order => 2 },
:solution_2 => { :order => 3 }
},
:category_2 => {
:solution_3 => { :order => 4 },
:solution_4 => { :order => 1 }
}
}
Hash[my_hash.inject({}) { |h, (k, v)| h.merge(v) }.sort_by { |k,v| v[:order] }]
#=> {:solution_4=>{:order=>1}, :solution_1=>{:order=>2}, :solution_2=>{:order=>3}, :solution_3=>{:order=>4}}
EDIT:
Taking into account your clarification (and still starting from the modified unsorted hash I posted above):
sorted = my_hash.inject({}) do |h, (k, v)|
h[k] = Hash[v.sort_by { |k1, v1| v1[:order] }]
h
end
#=> {:category_1=>{:solution_1=>{:order=>2}, :solution_2=>{:order=>3}}, :category_2=>{:solution_4=>{:order=>1}, :solution_3=>{:order=>4}}}
I have an array like this:
['one','three','two','four']
I have a array of hash like this:
[{'three' => {..some data here..} }, {'two' => {..some data here..} }, {:total => some_total }] # etc...
I want to sort the array of hashes by the first array. I know I can do:
array_of_hashes.sort_by{|k,v| k.to_s} to sort them and it will sort by the key
( and the .to_s to convert :total to a string )
How can I make this happen?
Edit:
I was incorrect about how this is setup, it is actually like this:
{'one' => {:total => 1, :some_other_value => 5}, 'two' => {:total => 2, :some_other_value => 3} }
If I need to put this in a new question, just let me know and I will do that.
Thank you
similar to ctcherry answer, but using sort_by.
sort_arr = ['one','three','two','four']
hash_arr = [{'three' => {..some data here..} }, {'two' => {..some data here..} }]
hash_arr.sort_by { |h| sort_arr.index(h.keys.first) }
The index method of Array is your friend in this case:
sort_list = ['one','three','two','four']
data_list = [{'three' => { :test => 3 } }, {'two' => { :test => 2 } }, {'one' => { :test => 1 } }, {'four' => { :test => 4 } }]
puts data_list.sort { |a,b|
sort_list.index(a.keys.first) <=> sort_list.index(b.keys.first)
}.inspect
Resulting in, the same order as the source array:
[{"one"=>{:test=>1}}, {"three"=>{:test=>3}}, {"two"=>{:test=>2}}, {"four"=>{:test=>4}}]
I am using Ruby on Rails 3 and I would like to "trasform" the following array so that I can use my custom logic to access its data.
This is the original array from which I have to build a new one
[
{
"account" => {
"id" => 45,
"name" => "Test_name",
"..." => ..."
}
},
{
"other" => {
"sub_other" => {...}
}
}
]
I would like to trasform the above array so that I can do in my controller something like
array_name[45]
# => {
"name" => "Test_name",
"..." => ..."
}
but only for the account hashs. The other hash should remain untouched.
How can I proceed to build the new array?
If I understand your requirements correctly, I think you are better off constructing a hash from account id to account data. Perhaps something like this will work:
arr = [
{
"account" => {
"id" => 45,
"name" => "Test_name",
"..." => "..."
}
},
{
"other" => {
"sub_other" => "..."
}
}
]
account_hashes = arr.select {|item| item.keys.first == "account"}
answer = account_hashes.inject({}) do |acc, item|
acc[item["account"].delete("id")] = item["account"]
acc
end