Convert array of JSON to array of Activerecord models? - ruby-on-rails

I have an array of JSON strings. How do I convert them to an array of Activerecord models?
My current code looks like this, and I'd to not iterate it one by one:
jsons = ['{"id": 1, "field1" : "value1"}'] #this is an array of jsons
models = [] #i want an array of models back
jsons.each do |json|
if(json == nil)
next
end
begin
hash = JSON.parse(json)
rescue
next
end
model = className.new
model.attributes = hash
model.id = hash["id"]
models << model
end

You should do:
models = jsons.compact.map { |json| Klass.new(JSON.parse(json)) }
where Klass is the ActiveRecord model class
EDIT
Based on the comments, you don't want to mass assign ID's, it could really get clumsy, it's better to leave rails to generate it for you, non mass assignment is:
models = jsons.compact.map { |json| Klass.new(JSON.parse(json).except(:id, "id")) }
:id, "id" is because I am not sure if the parsed JSON uses symbol or strings as keys

Related

Generate a Key, Value JSON object from a Ruby Object Array

I have a Ruby array of students. Student class has attributes id, name and age.
students = [
{id:"id1",name:"name1",age:"age1"},
{id:"id2",name:"name2",age:"age2"},
{id:"id3",name:"name3",age:"age3"}
]
I want to create a JSON key value object from this array as follows.
json_object = {id1:name1, id2:name2, id3:name3}
input = [ {id:"id1",name:"name1",age:"age1"},
{id:"id2",name:"name2",age:"age2"},
{id:"id3",name:"name3",age:"age3"}]
require 'json'
JSON.dump(input.map { |hash| [hash[:id], hash[:name]] }.to_h)
#⇒ '{"id1":"name1","id2":"name2","id3":"name3"}'
Give this a go:
students = [
{id:"id1",name:"name1",age:"age1"},
{id:"id2",name:"name2",age:"age2"},
{id:"id3",name:"name3",age:"age3"}
]
json_object = students.each_with_object({}) do |hsh, returning|
returning[hsh[:id]] = hsh[:name]
end.to_json
In console:
puts json_object
=> {"id1":"name1","id2":"name2","id3":"name3"}
Your data is all identical, but if you wanted to generate a hash that took the value of students[n][:id] as keys and students[n][:name] as values you could do this:
student_ids_to_names = students.each_with_object({}) do |student, memo|
memo[student[:id]] = student[:name]
end
For your data, you'd end up with only one entry as the students are identical: { "id1" => "name1" }. If the data were different each key would be unique on :id.
Once you have a hash, you can call json_object = students_ids_to_names.to_json to get a JSON string.

Ruby convert all values in a hash to string

I have the following snippet of code to fetch certain columns from the db:
#data = Topic.select("id,name").where("id in (?)",#question.question_topic.split(",")).map(&:attributes)
In the resulting Array of Hashes which is :
Current:
#data = [ { "id" => 2, "name" => "Sports" }]
To be changed to:
#data = [ { "id" => "2", "name" => "Sports" }]
I want to convert "id" to string from fixnum. Id is integer in the db. What is the cleanest way to do this?
Note: After using .map(&:attributes) it is not an active record relation.
You can do it with proper map usage:
topics = Topic.select("id,name").where("id in (?)",#question.question_topic.split(","))
#data = topics.map do |topic|
{
'id' => topic.id.to_s,
'name' => topic.name
}
end
What you're looking for is simply
#data.each { |obj| obj["id"] = obj["id"].to_s }
There isn't really a simpler way (I think that's straightforward enough anyway).
Going by the title which implies a different question - converting every value in the hash to a string you can do this:
#data.each do |obj|
obj.map do |k, v|
{k => v.to_s}
end
end
Just leaving that there anyway.
You can use Ruby's #inject here:
#data.map do |datum|
new_datum = datum.inject({}) do |converted_datum, (key, value)|
converted_datum[key] = value.to_s
converted_datum
end
end
This will work to convert all values to strings, regardless of the key.
If you are using Rails it can be even cleaner with Rails' #each_with_object:
#data.map do |datum|
datum.each_with_object({}) do |(key, value), converted_datum|
converted_datum[key] = value.to_s
end
end
This will iterate all the key names in the hash and replace the value with the #to_s version of the datum associated with the key. nil's converted to empty strings. Also, this assumes you don't have complex data within the hash like embedded arrays or other hashes.
def hash_values_to_string(hash)
hash.keys.each {|k| hash[k]=hash[k].to_s}; hash
end

How to cycle through rails model parameters

I'm trying to set up a method in rails so that if there is a parameter has a nil value, the name of the parameter is returned.
I have a model called Usages(gas,elec,biomass)
I know how to do this in ruby:
u = {elec: 100, gas: 200, biomass: nil}
t = %w(gas elec chp)
t.each do |t|
s=t.to_sym
if u[s] == nil
puts "#{t}"
end
end
, which returns "biomass"
Say I had this in Rails:
u = Usage.create(elec:100, gas:200)
How would I return "biomass"??
Cheers!
There is an attributes hash on ActiveRecord models that is based on the database table linked to the class. Empty fields are mapped with nil values, so you can look them up like this:
u.attributes.select {|_,v| v.nil? }.keys
I think you just want to loop through the active record attributes?
u = Usage.create(elec:100, gas:200)
u.attributes.each do |x|
if u.public_send(x).nil?
puts "#{x} is nil"
end
end

Using a method while looping through an array in ruby

I am using ruby-aaws to return Amazon Products and I want to enter them into my DB. I have created a model Amazonproduct and I have created a method get_amazon_data to return an array with all the product information. When i define the specific element in the array ( e.g. to_a[0] ) and then use ruby-aaws item_attributes method, it returns the name I am searching for and saves it to my DB. I am trying to iterate through the array and still have the item_attributes method work. When i don't define the element, i get this error: undefined method `item_attributes' for #Array:0x7f012cae2d68
Here is the code in my controller.
def create
#arr = Amazonproduct.get_amazon_data( :r ).to_a
#arr.each { |name|
#amazonproduct = Amazonproduct.new(params[:amazonproducts])
#amazonproduct.name = #arr.item_attributes.title.to_s
}
EDIT: Code in my model to see if that helps:
class Amazonproduct < ActiveRecord::Base
def self.get_amazon_data(r)
resp = Amazon::AWS.item_search('GourmetFood', { 'Keywords' => 'Coffee Maker' })
items = resp.item_search_response.items.item
end
end
Thanks for any help/advice.
I'm not familiar with the Amazon API, but I do observe that #arr is an array. Arrays do not usually have methods like item_attributes, so you probably lost track of which object was which somewhere in the coding process. It happens ;)
Try moving that .item_attributes call onto the object that supports that method. Maybe amazonproduct.get_amazon_data(:r), before its being turned into an array with to_a, has that method?
It's not quite clear to me what your classes are doing but to use #each, you can do something like
hash = {}
[['name', 'Macbook'], ['price', 1000]].each do |sub_array|
hash[sub_array[0]] = sub_array[1]
end
which gives you a hash like
{ 'name' => 'Macbook', 'price' => 1000 }
This hash may be easier to work with
#product = Product.new
#product.name = hash[:name]
....
EDIT
Try
def create
#arr = Amazonproduct.get_amazon_data( :r ).to_a
#arr.each do |aws_object|
#amazonproduct = Amazonproduct.new(params[:amazonproducts])
#amazonproduct.name = aws_object.item_attributes.title.to_s
end
end

returning an array that contains an array and hash in ruby method?

HI
is it possible to return an array that contains an array and hash from a method in ruby?
i.e
def something
array_new = [another_thing, another_thing_2]
hash_map = get_hash()
return [array_new, hash_map]
end
and to retrieve the array:
some_array, some_hash = something()
thanks
Sure, that's perfectly possible and works exactly as in your example.
You will only ever be able to return one thing. What you are returning there is an array containing an array and a hash.
Ruby methods can be treated as if they return multiple values so you can collect the items in an array or return them as separate objects.
def something
array_new = Array.new
hash_new = Hash.new
return array_new, hash_new
end
a, b = something
a.class # Array
b.class # Hash
c = something
c.class # Array

Resources