Rails 4.Combine 2 arrays - ruby-on-rails

I have 2 arrays and I want to combine them in one which should return nested JSON.
The first one is cleaner which returns:
{
"response": [
{
"id": 1,
"first_name": "Fernando",
"last_name": "Gomez",
"avg_rating": "4.5"
}
]
}
The second one is reviews from the clients
which returns the name of the client, comment and rating:
{
"response": [
{
"id": 1,
"score": 4,
"comment": "Comment",
"first_name": "John Doe"
}
]
}
So, I trie to zip them and loop over each of them. Here is my code:
cleaners.zip(reviews).each do |cleaner, review|
if cleaner.id == review.id
test['first_name'] = cleaner.first_name
test['last_name'] = cleaner.last_name
test['rating'] = review.score
test['comment'] = review.comment
test['client_name'] = review.first_name
end
end
The result is:
{
"response": {
"first_name": "Fernando",
"last_name": "Gomez",
"rating": 4,
"comment": "Comment",
"client_name": "John Doe"
}
}
But my result has to be nested because some of the cleaners will have many reviews. It has to be something like this:
{
"response": {
"first_name": "Fernando",
"last_name": "Gomez",
"score_from_client": [
{
"rating": 4,
"comment": "Comment",
"client_name": "John Doe"
}
]
}
}

Here is the answer of the question :)
unless cleaners.nil?
cleaner_ids = []
cleaners_reviews = []
cleaners.each do |cleaner|
cleaner_review = {
id: cleaner.id,
avg_rating: cleaner.avg_rating,
first_name: cleaner.first_name,
last_name: cleaner.last_name,
ratings: []
}
cleaners_reviews << cleaner_review
cleaner_ids << cleaner.id
end
reviews = Cleaner.get_cleaner_reviews(dates, cleaner_ids)
unless reviews.empty?
i = 0
reviews.each do |review|
cleaners_reviews[i][:ratings] << review
i += i
end
end
return cleaners_review
s

Related

Convert nested hash of array in ruby

How do I convert an array in nested hash in ruby
For example:
From
{
"errors": {
"name": [
"must be filled"
],
"type": [
"must be filled"
],
"address": {
"country_id": [
"must be filled"
]
},
"group": {
"name": [
"is missing"
]
},
"contacts": {
"2": {
"name": [
"must be filled"
],
"phone": {
"0": {
"number": [
"must be filled"
],
"email": [
"must be valid"
]
}
}
}
}
}
}
To
{
"errors": {
"name": "must be filled",
"type": "must be filled",
"address": {
"country_id": "must be filled"
},
"group": {
"name": "is missing"
},
"contacts": [
{
"name": "must be filled",
"index": 2,
"phone": [
{
"number": "must be filled",
"email": "must be valid",
"index": 0
}
]
}
}
}
I want remove key of hash ("2", "0") and convert it to hash of array. Thanks
I tried and succeeded in the following way. Thanks all
def change(messages)
result = {}
array = []
messages.each do |field, message|
if message.is_a?(Hash)
if field.is_a? Integer
value = change(message)
array.push(value.merge(index: field))
result = array
else
value = change(message)
result[field] = value
end
else
result[field] = message.at(0)
end
end
result
end

Reverse a nested array in Ruby

I'm attempting to take a JSON API response, with nested associated resources, and reverse the associations in a Rails app.
So, imagine I get a response like this:
{
"spenders": [
{
"id": 1,
"name": "John Doe",
"accounts": [
{
"id": 1,
"name": "Account One"
},
{
"id": 2,
"name": "Account Two"
}
]
},
{
"id": 2,
"name": "Jane Doe",
"accounts": [
{
"id": 1,
"name": "Account One"
},
{
"id": 3,
"name": "Account Three"
}
]
}
]
}
My goal is to convert this into structure like this:
{
"accounts": [
{
"id": 1,
"name": "Account One",
"spenders": [
{
"id": 1,
"name": "Stephen Margheim"
},
{
"id": 2,
"name": "Greg Barendt"
}
]
},
{
"id": 2,
"name": "Account Two",
"spenders": [
{
"id": 1,
"name": "Stephen Margheim"
}
]
},
{
"id": 3,
"name": "Account Three",
"spenders": [
{
"id": 2,
"name": "Greg Barendt"
}
]
}
]
}
Now, I can do this fairly well with iteration over the hash and building a new hash:
spenders_hash = {}
accounts.each do |account|
account.spenders.each do |spender|
if spenders_hash.key? spender.id
spenders_hash[spender.id][:accounts] << account
else
spenders_hash[spender.id] = hash_from_spender_and_account(spender, account)
end
end
end
spenders_hash
def hash_from_spender_and_account(spender, account)
{
id: spender.id,
name: spender.name,
accounts: [account],
}
end
I'm hoping to find [1] a more flexible solution that isn't reliant on knowing the key names in advance and [2] hopefully more efficient.
Thoughts?

ruby return an array of sub elements using map

I have the following structure:
"countries": [
{
"states" :[
{
"name" :"Texas",
"id": "a1"
},
{
"name" :"Nebraska",
"id": "a1"
}
]
},
{
"states" :[
{
"name" :"New York",
"id": "a1",
},
{
"name" :"Florida",
"id": "a1"
}
]
}
]
I want to return an array of all the states from above.
Here is what I tried:
countries.map { |country| country.states.map { |state| state.name } }
But it returns only the first 2 statest 'Texas' and Nebraska.
Can someone tell me what I am doing wrong here?
you structure wasn't right, so corrected:
countries = [
{
"states" => [
{
"name" => "Texas",
"id"=> "a1"
},
{
"name"=> "Nebraska",
"id"=> "a1"
}
]
},
{
"states" => [
{
"name"=> "New York",
"id"=> "a1",
},
{
"name" =>"Florida",
"id"=> "a1"
}
]
}
]
Ruby wasn't accepting ":" for strings for some weird reasons. Like this(which isn't working):
countries = [
{
"states": [
{
"name": "Texas",
"id": "a1"
},
{
"name": "Nebraska",
"id": "a1"
}
]
},
{
"states": [
{
"name": "New York",
"id": "a1",
},
{
"name" :"Florida",
"id": "a1"
}
]
}
]
For this, you can do:
countries.map{ |c| c["states"].map{|s| s["name"]}}.flatten
#=> ["Texas", "Nebraska", "New York", "Florida"]
Or if you get the repetitive values then:
countries.map{ |c| c["states"].map{|s| s["name"]}}.flatten.uniq
#=> ["Texas", "Nebraska", "New York", "Florida"]
I hope this helps.
Go for Surya's answer, it is the same solution. Just wanna show how I write it:
countries.map{|x|x['states']}
.flatten
.map{|x|x['name']}

Pretty BSON::OrderedHash using Rails

If I pass a BSON::OrderedHash (from a MongoDb collection) to JSON.pretty_generate I get the json document but unformatted. How can I get a bson document formatted like .pretty() does?
It works for me with mongo 1.9.1, bson 1.9.1, and json 1.8.0 as shown in the following test code, as close as can be expected.
pretty_bson.rb
require 'mongo'
require 'bson'
require 'json'
require 'test/unit'
class BsonPrettyTest < Test::Unit::TestCase
def setup
#client = Mongo::MongoClient.new
#db = #client['test']
#coll = #db['people']
#coll.remove
assert_equal 0, #coll.count
end
test "bson pretty" do
text = <<-EOF
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
EOF
hash = JSON.parse(text)
#coll.insert(hash)
doc = #coll.find_one
assert_equal BSON::OrderedHash, doc.class
puts JSON.pretty_generate(hash)
puts JSON.pretty_generate(doc)
end
end
ruby pretty_bson.rb
Loaded suite pretty_bson
Started
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
],
"_id": {"$oid": "51df0c537f11bab55d000001"}
}
{
"_id": {"$oid": "51df0c537f11bab55d000001"},
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
.
Finished in 0.005689 seconds.
1 tests, 2 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
175.78 tests/s, 351.56 assertions/s

Rails - better flow control - loop

I am grabbing value data: name, uid, highschool_name, graduateschool_name like this:
def add_friends
facebook.get_connections("me", "friends", :fields => "name, id, education").each do |hash|
self.friends.where(:name => hash['name'],
:uid => hash['id'],
:highschool_name => hash['education']['school']['name'] unless hash["education"].blank?,
:graduateschool_name => hash['education']['school']['name'] unless hash["education"].blank?).
first_or_create
end
end
From an array of hash:
"education": [
{
"school": {
"id": "110703012290674",
"name": "Kunskapsgymnasiet Malmö"
},
"year": {
"id": "136328419721520",
"name": "2009"
},
"type": "High School"
},
{
"school": {
"id": "112812485399398",
"name": "Malmö University"
},
"year": {
"id": "118118634930920",
"name": "2012"
},
"concentration": [
{
"id": "104076956295773",
"name": "Computer Science"
}
],
"type": "Graduate School",
"classes": [
{
"id": "165093923542525",
"name": "Programmering",
"description": "Kursen fokuserar på metoder och tekniker vid utveckling av webbapplikationer med hjälp av HTML5."
}
]
}
],
EDIT:
This code dosent work. I would like to pick every hichschool and Graduate School from this array of hash and save it.
high_schools = response['education'].collect{|ed| ed['school']['name'] if ed['type'] == "High School" }
grad_schools = response['education'].collect{|ed| ed['school']['name'] if ed['type'] == "Graduate School" }

Resources