Rails build JSON object from hash and arrays via model - ruby-on-rails

I am trying to post data to an API, the API is requesting a JSON request as this:
{
"blacklists": {
"list1": [{
"id": "123",
"find": "foo",
"type": "text"
}],
"list2": [{
"id": "321",
"find": "bar",
"type": "text"
}]
}
}
My problem is building a JSON with hash and arrays representing the above.
This is the code I have so far:
#blacklist = {}
#bl = {}
key_category = KeywordCategory.where("global_list = ? OR unit_id = ?",1,1)
key_category.each do |kc|
bl_name = kc.name # <- "list1, list2 etc."
kc.keywords.each do |kw|
#keywords = {}
#keywords['id'] = kw.id
#keywords['find'] = kw.data
#keywords['type'] = kw.is_regexp ? "regexp" : "text"
#bl.merge!(#keywords)
end
end
#blacklist['blacklist'] = #bl
return #blacklist.to_json
This code gives me this JSON (which is a bit from the one the API wants):
{
"blacklists":
{"id":123,
"find":"foo",
"type":"text"
}
}
How do I change my code so it spits out according to the top JSON?

Try something like this:
#blacklist = {}
#bl = {}
key_category = KeywordCategory.where("global_list = ? OR unit_id = ?",1,1)
key_category.each do |kc|
tmparray = []
kc.keywords.each do |kw|
#keyword = { id: kw.id, find: kw.data, type: kw.is_regexp ? 'regexp' : 'text" }
tmparray << #keyword
end
#bl.merge!(kc.name: tmparray)
end
#blacklist['blacklist'] = #bl
return #blacklist.to_json

Related

Correct test in .lua

I'm new in lua.
Sorry for too much text, but I really need help
There is a space "company". Inside it's "information" map. Inside this map is a "job" object and an array of "users" objects. The "users" array consists of 2 objects. Each object has 4 fields.
"company": {
"company_id" : 1,
"type" : "01",
"number" : "YES",
"information":
{
"job":
{
"job_name": "N",
"job_address": 1670392687114
},
"users":
[
{
"id": 1,
"name": "Alex",
"rate": 4,
"address": "bla bla bla"
},
{
"id": 2,
"name": "Jenifer",
"rate": 5,
"address": "bla bla bla"
}
]
}
}
There is a migration for renaming fields in a space and adding new field data, provided:
local space_name = 'company'
local space = box.space[space_name]
local key_parts = space.index.primary.parts
local updated = 0
local counter = 0
local isUpdateType = {
["01"] = true,
["02"] = true,
["03"] = true,
["04"] = true,
}
for _, tuple in space:pairs() do
if tuple.information ~= nil and tuple.information.users ~= nil then
local information = tuple.information
local users = tuple.information.users
-- rename fields and assign nil to the old fields
for _, attr in pairs(users) do
attr.user_rate = attr.rate
attr.rate = nil
attr.user_address = attr.address
attr.address = nil
end
-- update data according to the condition
if isUpdateType[tuple.type] and tuple.number == "YES" then
for _, attr in pairs(users) do
attr.status = "UPDATED"
end
end
local key = {}
for _, part in ipairs(key_parts) do table.insert(key, tuple[part.fieldno]) end
space:update(key, { {'=', 'information', information} })
updated = updated + 1
end
counter = counter + 1
if counter % 1000 == 0 then
fiber.yield()
end
if counter % 10000 == 0 then
log.info('%s: %s tuples have been checked in space %s', migration, counter, space_name)
end
end log.info('%s: %s tuples have been updated from space %s', migration, updated, space_name)
Here we are at the beginning
rename fields and assign nil to the old fields
update data according to the condition: if type = "01" or "02" or "03" or "04" and number = "YES", then add a new field status = "UPDATED" to each element of the users array
I wrote a part of the test that checks if there is a "company" space and if it contains an "information" map and if it contains an array "users" in which the fields from "rate" and "address" have been renamed to the new "user_rate" and "user_address".
I'm not sure I wrote the test correctly.
Also I'm missing part of the test for the second condition of the migration: adding a new field status = "UPDATED" under a certain condition.
local space_name = 'company'
g.before_all(function()
utils.init_config_loader(helper)
utils.apply_migrations_before(helper, '005')
end)
g.after_all(function()
utils.cleanup(helper)
end)
g.check_if_exist_space = function()
local operation = 'upsert'
utils.data_into_space(helper, space_name, 4, operation)
utils.apply_migrations(helper, { '005_update_company.lua' },
{ './migrations/005_update_company.lua' })
for index = 1, 4 do
local res, err = helper.cluster.main_server.net_box:eval([[
local router_helper = require('app.utils.router_helper')
local space_name, key, shard_value = ...
return crud.get(space_name, key, { fields = {'information'}})
]], { space_name, 'company_id' .. index })
t.assert_equals(err, nil)
t.assert_equals(#res.rows, 1)
t.assert_equals(#res.rows[1], 1)
local information = res.rows[1][1]
t.assert_equals(#information, 1)
t.assert_equals(information.users[1].rate, 'user_rate' .. index)
t.assert_equals(information.users[1].address, 'user_address' .. index)
end
end
Can you help me please?

how to generate a Json object from string in ruby

I have an array of strings of this format ['config = 3', 'config_b.root.a.b.c = 13'] ;
my goal is to create the following json object from them
{
"config": 3,
"config_b": {
"root": {
"a": {
"b": {
"c": 13
}
}
}
}
}
this is my current working approach
# inputs is an array of strings
def create_config(inputs)
hash={}
inputs.each do |x|
value = x.split("=")[1]
keys = x.split("=")[0].strip.split(".")
add_item(keys,value,hash)
end
print hash
end
# recusive function for adding items
def add_item(keys,value,hash)
current = keys.shift
if keys.empty?
hash[current] = value
else
hash[current] = {}
add_item(keys,value,hash[current])
end
end
I would like to know if anyone has a better approach for solving this, Thanks
I think I have a solution.
def create_config(inputs)
inputs.map do |e|
keys, value = e.split(' = ')
keys.split('.').reverse.inject(value) { |assigned_value, key| { key => assigned_value } }
end.reduce(:merge)
end
I tried it with
['config = 3', 'config_b.root.a.b.c = 13']
and got
{"config"=>"3", "config_b"=>{"root"=>{"a"=>{"b"=>{"c"=>"13"}}}}}

Grouping the array of codes

I have two different types of codes.
AllCodes = [
{
group_name: 'Marked',
group_codes: [
{
code: '1A',
description: 'Marked.'
}
],
.. //next group codes.
}
]
AllCodes = [
{
code: '2',
description: 'Located. Facilities Marked.'
}
.. //next codes.
]
I need to form an array of this format.
[
{
code: '1A',
description: 'example'
},
.. // next code
]
I did it this way, but I do not really like this approach, how can I dry up the code?
def up
Account.all.each do |account|
arrayed_codes = []
account.one_call_center.response_codes_repository_class::AllCodes.collect do |codes|
if response_code[:group_codes]
response_code[:group_codes].each do |group_codes|
arrayed_codes << {
code: group_codes[:code],
description: group_codes[:description]
}
end
else
arrayed_codes << {
code: response_code[:code],
description: response_code[:description]
}
end
end
arrayed_codes.each do |res_code|
ResponseCode.create!(account: account,
one_call_center_id: account.one_call_center.id,
close_code: res_code[:code],
description: res_code[:description],
ticket_types: account.one_call_center.ticket_types.keys)
end
end
end
# obj is an each element of your AllCodes array
codes = AllCodes.inject([]) do |codes_array, obj|
if obj.has_key?(:group_codes)
codes_array += obj[:group_codes]
else
codes_array << obj
end
end
codes_array is an injected array. Iterating over your AllCodes, if current object has_key?(:group_codes), we should take obj[:group_codes] (because it's already an array of needed format), so we merge our codes_array with it: codes_array += obj[:group_codes]. If it doesn't have that key, than it's already hash of needed format. So we just add this element to the array.

rspec for testing json results

So I am basically trying to write rspec to test my json results:
patient_allergies = patient.patient_allergies
expect(response_body['allergies'].size).to eq(patient_allergies.size)
patient_allergies.each_with_index do |allergy, index|
expect(response_body['allergies'][index]['name']).to eq(allergy.name)
allergy.patient_allergy_reactions.each_with_index do |reaction, index|
expect(response_body['reactions'][index]['name']).to eq(reaction.name)
end
end
My tables above are patient_allergies and patient_allergy_reactions.
The above tests work fine. But the problem is I am comparing by index.
If the order of the json changes, the test would fail. Is there a better way to write tests for this?
my json looks like this:
"allergies": [
{
"name": "Allergy1",
"reactions": [
]
},
{
"name": "Allergy2",
"reactions": [
{
"name": "Reaction1",
"severity": "Medium"
}
]
}
],
Use detect and the include matcher to help you out here:
patient_allergies = patient.patient_allergies
response_allergies = response['allergies'] || []
expect(response_allergies.size).to eq(patient_allergies.size)
patient_allergies.each |allergy| do
response_allergy = response_allergies.detect{|a| a['name'] == allergy.name}
expect(response_allergy).to_not be_nil
patient_reactions = allergy.patient_allergy_reactions
response_reactions = (response_allergy['reactions'] || []).map{|r| r['name']}
expect(response_reactions.size).to eq(patient_reactions.size)
expect(response_reactions).to include(*patient_reactions.map(&:name))
end

Ruby Array of Arrays returning query to be used for chartjs,

def self.return_this_data_for_map_method
data = { :labels => [], datasets: [data: []] }
dictionary = {}
results.each do |teams|
team = teams[0]
teamMembers = teams[1]
if dictionary[team].nil?
dictionary[team] = teamMembers
else
dictionary[team] += teamMembers
end
end
data[:labels] << dictionary.keys
data[:datasets][0][:data] << dictionary.values
data
end
This is the data I am getting out
=> {:labels=>[["CUBS", "CARDS", "ROCKIES", "ASTROS"]]:datasets=>[{:data=>[[72, 93, 74, 28]]}]}
This is how I am trying to get my data
=> {:labels=>["CUBS", "CARDS", "ROCKIES", "ASTROS"], :datasets=>[{:data=>[72, 93, 74, 28]}]}
It's wrapping it like it's still in an Array of Arrays, I am not quite seeing how to break how of it. Any suggestions on how I can fix my code would be appreciated.
using ruby 2.3.1
The simplest solution is to flatten the arrays prior to returning the data:
data = { :labels => [], datasets: [data: []] }
dictionary = {}
results.each do |teams|
team = teams[0]
teamMembers = teams[1]
if dictionary[team].nil?
dictionary[team] = teamMembers
else
dictionary[team] += teamMembers
end
end
data[:labels] << dictionary.keys
data[:datasets][0][:data] << dictionary.values
data[:labels].flatten!
data[:datasets][0][:data].flatten!
data
#maxpleaner and #rails_id were correct
def self.return_this_data_for_map_method
data = { :labels => [], datasets: [data: []] }
dictionary = {}
results.each do |teams|
team = teams[0]
teamMembers = teams[1]
if dictionary[team].nil?
dictionary[team] = teamMembers
else
dictionary[team] += teamMembers
end
end
data[:labels] += dictionary.keys
data[:datasets][0][:data] += dictionary.values
data
end

Resources