making hash to produce JSON - ruby-on-rails

I am creating a hash which would produce JSON to be used in APIs.
To make Hash I am trying this:
presses = Press.select(:id, :name)
pulls = Pull.select(:id, :name)
response = {list: {presses: presses, pulls: pulls}}
Actually works good and produces:
{"list":{
"presses":[
{"id":1,"name":"p40"},
{"id":2,"name":"p41"}],
"pulls":[
{"id":1,"name":"Best Effort"},
{"id":2,"name":"First Good"}]
}}
But the requirement has changed to make it like:
{"list":{
"presses":[
{"id":1,"name":"p40"
"pulls":[
{"id":1,"name":"Best Effort"},
{"id":2,"name":"First Good"}]},
{"id":2,"name":"p41"
"pulls":[
{"id":1,"name":"Best Effort"},
{"id":2,"name":"First Good"}]},
],
}}
Note Each press object should contain all pull object. So far don't know how to achieve this. Any Idea?

I think this is Rails question. Thus I have #attributes method. Here is my attempt
presses = Press.select(:id, :name)
pulls = Pull.select(:id, :name)
response = { list: {
presses: presses.map do |press|
press.attributes.merge(pulls: pulls.map(&:attributes))
end
}
}.to_json

This will do what you want
pulls = Pull.select(:id, :name)
presses = Press.select(:id, :name)
presses = presses.collect do |press|
press.merge({pulls: pulls})
end
response = {list: {presses: presses}}

Related

How to push a blank name and a name on to this array in Rails

I have an array of names. I want the first option to be blank, and the last option to be "Joe".
Here is the code:
def index
#case_managers = client.personnel_search_by_client(current_client.client_id, nil, groupMnemonic: 'reimbursement_whitelist')
#case_managers_drop_down = {}
#case_managers.each do |case_manager|
#case_managers_drop_down[case_manager.name] = case_manager.to_json
end
end
In my views I have:
= form_tag work_lists_path, :method=> 'put' do |f|
.fieldset.field-group.field-group-inline.pull-left
.field.field-text.field-required
%label= t('workflow.duplicate_claim_manager')
= select_tag('case[case_manager]', options_for_select(#case_managers_drop_down, #selected_case_manager))
This correctly gets all the names. I thought before the array I would do something like #case_managers_drop_down.push(" ") to get a blank option and then likewise for Joe. But this doesnt seem to be working. Any idea on how I can append to this array?
To get a blank option at first place in select_tag use include_blank boolean attribute like :
= select_tag('case[case_manager]', options_for_select(#case_managers_drop_down, #selected_case_manager), :include_blank => true)
OR use prompt like :
= select_tag('case[case_manager]', options_for_select(#case_managers_drop_down, #selected_case_manager), :prompt => "Please select")
For last option as joe do it like :
def index
#case_managers = client.personnel_search_by_client(current_client.client_id, nil, groupMnemonic: 'reimbursement_whitelist')
#case_managers_drop_down = {}
#case_managers.each do |case_manager|
#case_managers_drop_down[case_manager.name] = case_manager.to_json
end
#case_managers_drop_down["joe"] = ""
end
Hopefully it will work!

Creating a record from a third-party object with same field names?

I have a Charge model in my database with field names that match up to the fields returned from a third-party API.
charge = ThirdPartyChargeAPI.find(1)
Charge.create do |e|
e.object = charge.object
e.paid = charge.paid
e.amount = charge.amount
e.currency = charge.currency
e.refunded = charge.refunded
e.amount_refunded = charge.amount_refunded
e.failure_message = charge.failure_message
e.failure_code = charge.failure_code
e.description = charge.description
e.metadata = charge.metadata
e.captured = charge.captured
e.balance_transaction = charge.balance_transaction
e.customer = charge.customer
e.invoice = charge.invoice
e.created = charge.created
end
Seems painfully redundant, though. Is there some way to merge this without having to basically set every single field manually?
Assuming there's no way to get a direct hash from the API (I would imagine there would be, since it's probably coming in as XML or JSON), you could try a direct map of instance variables:
Charge.create do |c|
charge.instance_variables.each do |var|
value = charge.instance_variable_get(var)
c.instance_variable_set(var, value)
end
end
This is making some pretty bold assumptions about the structure of the charge you're getting back from the API though - any instance variable in it that you don't want will be included.

How to access the value that is rendered after decoding in rails?

How can i access the year from the json shown below which i fetch from a url and decode using
obj = ActiveSupport::JSON.decode(response.body)
The folloowing is the response i get after decode
{
"educations"=>{"_total"=>1,
"values"=>[
{"id"=>18234534505,
"schoolName"=>"Test",
"startDate"=>{"year"=>2013}
}
]
}
}
How can i access the year? I can able to access the values as
obj['educations']['values']
and it responds as
{"id"=>18234534505, "schoolName"=>"Test", "startDate"=>{"year"=>2013}}
but how can i get the year? please help me.
UPDATE:
how can i add if condition here?
obj["educations"]["values"].each do |value|
#user_education = Education.new("start_date" =>
value['startDate']['year'], "education_id" => value['id'],
"school_name" => value['schoolName'])
end
so here if there is no year then how can i check as you said? and there may also be endDate similar to the startDate so how can i check this?
Just access the key as
obj["educations"]["values"].first["startDate"]["year"]
# above is answer if there is always one array inside `obj["educations"]["values"]`
For multiple arrays's
year = []
obj["educations"]["values"].each do |object|
year << object["startDate"]["year"] if !object["startDate"].blank? and !object["startDate"]["year"].blank?
end
update :
If you want to add attributes to the
#user_education = Education.new
#user_education.start_date = value['startDate']['year'] if !value['startDate'].blank? and !value['startDate']['year'].blank?
#user_education.education_id = value['id'] if !value['id'].blank?
#user_education.school_name = value['schoolName'] if !value['schoolName'].blank?
Similarly for any other attribute..
obj["educations"]["values"].each do |value|
#user_education = Education.new("education_id" => value['id'], "school_name" => value['schoolName'])
#user_education.start_date = value["startDate"]["year"] if !value["startDate"].blank? and !object["startDate"]["year"].blank?
#user_education.save! #To save the object
end

search for key in a nested hash in Rails

I have the following nested hash (from Ominauth-Facebook) captured in an object called myAuth
<Ominauth::AuthHash credentials
extra=#<Hashie:: Mash
raw_info=#<Hashie::Mash email="myemail#gmail.com">>>
I would like to extract email, so I use:
myAuth['extra']['raw_info']['email']
However, I would like to search the entire hash and get the value for key email without knowing exact hash structure. How should I go about it?
Thank you.
Don't know if this is the best solution, but i would do:
h = {seal: 5, test: 3, answer: { nested: "damn", something: { email: "yay!" } } }
def search_hash(h, search)
return h[search] if h.fetch(search, false)
h.keys.each do |k|
answer = search_hash(h[k], search) if h[k].is_a? Hash
return answer if answer
end
false
end
puts search_hash(h, :email)
This will return the value if the key exists or false.

Params contain an array that wants to be a hash

I have an array (coming from a file_field, :multiple => true) in my params that I want to turn into a hash so I can build associated models for each element and process in my create action.
Currently receiving:
{"gallery"=>{"name"=>"A Gallery", "photos_attributes"=>{"0"=>{"image"=>[#<1st Image data removed for brevity>, #<2nd Image data removed for brevity>]}}}, "commit"=>"Save"}
I'd like to turn it into something like:
{"gallery"=>{"name"=>"A Gallery", "photos_attributes"=>{"0"=>{"image"=>#<1st Image data removed for brevity>}, "1"=>{"image"=>#<1st Image data removed for brevity>}}}, "commit"=>"Save"}
considered something like this but it's clearly wrong:
i = 0
params[:gallery][:photos_attributes]["0"][:image].reduce({}) do |result, element|
result[i++.to_s] = element
end
What's the "Rail's Way"?
You need to return the result hash at the end of each iteration.
i = 0
params[:gallery][:photos_attributes]["0"][:image].reduce({}) do |result, element|
result[(i += 1).to_s] = element
result
end
I've done something similar when receiving data from an iOS device. But, if I understand what you want and what your model(s) look like, to get nested attributes to work you don't want it to look like:
{ "photos_attributes" => { "0" => <image1>, "1" => <image2>, ... }
You want it to look like:
{ "photos_attributes" => [ <image1>, <image2>, ... ] }
And to do that all you need to do is:
params["gallery"]["photos_attributes"] = params["gallery"]["photos_attributes"]["0"]["image"]
Now, if I've misunderstood what you need, to get what you've asked for what you have might work (I don't use much reduce aka inject) or you could use tap:
i = 0
params["gallery"]["photos_attributes"] = {}.tap do |hash|
params["gallery"]["photos_attributes"]["0"]["image"].each do |image|
hash[i.to_s] = image
i = i + 1
end
end
Not a whole lot better IMO.

Resources