rspec for testing json results - ruby-on-rails

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

Related

Using Json Slurper + Groovy + Azure answer

So I am trying to write a Jenkins job using groovy to fetch me some data
The data inside the variable answer after the 3rd line would be some like
[
{
"endIpAddress": "11.21.115.9",
"id": "blabla1",
"name": "blabla",
"resourceGroup": "stg",
"startIpAddress": "11.12.115.9",
"type": "blablafirewallRules"
},
{
"endIpAddress": "1.2.15.9",
"id": "blabla2",
"name": "function1-blabla",
"resourceGroup": "stg",
"startIpAddress": "1.2.15.9",
"type": "blablafirewallRules"
},
{
"endIpAddress": "7.7.7.7",
"id": "blabla2",
"name": "function2-blabla",
"resourceGroup": "stg",
"startIpAddress": "7.7.7.7",
"type": "blablafirewallRules"
},
.
.
.
.
]
What id like to do is to build a list or a 2-dimentions-array that would parse this json and the it will hold all the startipaddress of all the items where name contains "function", so based on this JSON, the data should be
desiredData[0] = [function1-blabla, 1.2.15.9]
desiredData[1] = [function2-blabla, 7.7.7.7]
Up until now I wasn't using JsonSlurper and I was manipulating the text and building the array which is pretty stupid thing to do since this is kind of what JSON is all about I guess.
import groovy.json.JsonSlurper
command = "az mysql server firewall-rule list --resource-group ${rgNameSrvr} --server-name ${BLA} --output json"
answer = azure.executeAzureCliCommand(command, "BLA")
def jsonSlurper = new JsonSlurper()
def json = new JsonSlurper().parseText(answer)
def data = json.findAll{ it.name =~ /^function/ }.collectEntries{ [it.name, it.startIpAddress] }
Code above returns map where key=name and value=ip
If you want 2dim array:
def data = json.findAll{ it.name =~ /^function/ }.collect{ [it.name, it.startIpAddress] }

Convert json to hash to insert with Active Record

I'm still practising processing arrays and hashes, and particularly getting to details in 2d or 3d structures. I'm trying to use details in a json file to process some data ready to insert into the db with Active Record.
Here is my json structure for 'my_file.json'
# my_file.json
[
{
"name": "Joe Bloggs",
"telephone": "012-345-6789"
},
{
"name": "Hilda Bloggs",
"telephone": "012-345-6789"
}
]
and here is the code I'm using to convert the json data into something I can insert into my db
def json_insert_to_db
require 'json'
file = File.read('my_file.json')
json_data = JSON.parse(file)
details = json_data.map do |x|
user = User.new
user.name = json_data[x]['name']
user.telephone = json_data[x]['telephone']
end
end
With this I get
NameError: uninitialized constant User
(User does exist in the database, by the way)
I can't work out where I'm going wrong, but I know it's something simple I am overlooking. Thanks for any help.
The User model was set up but my db had a migration issue. However, beyond that, at the time I was still unable to build what I needed when importing the json file.
I have now worked out how to do it. The migration issue was resolved and I also revised the structure of my json file first, for clarity.
# my_file.json
{
"new_users":
[{
"name": "Joe Bloggs",
"telephone": "012-345-6789",
},
{
"name": "Hilda Bloggs",
"telephone": "012-345-6789",
}]
}
And my script...
require 'json'
file = File.read('my_file.json')
json_data = JSON.parse(file)['new_users']
#new_users = json_data.each do |key,value|
#new_user = User.new
#new_user.name = key['name']
#new_user.telephone = key['telephone']
end
#new_users.each { |x| puts x }

Rails build JSON object from hash and arrays via model

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

Remove metadata from json results

I'm using ActiveResource to establish a REST connection with rails 4.2 to an ADS Advantage server using the WebPlatform from ADS. It returns json with "__metadata". How can I remove the "__metadata"?
{
"__metadata": {
"uri": "http://.....",
"key_fields": "ID",
"rows_affected": 0,
"last_autoinc": 0
},
In my class I have added self.include_format_in_path = false, to remove the .json from the end of the uri.
Thanks.
you can achieve this in the following steps:
parse the JSON:
parsed_json = JSON.parse('{ "__metadata": { "uri": "http://.....", "key_fields": "ID", "rows_affected": 0, "last_autoinc": 0 }}')
then you will get a hash type and you just need to get the inside of __metadata:
result = parsed_json['__metadata']
then you can just return it or print it:
puts result.to_json
#=> {"uri"=>"http://.....", "key_fields"=>"ID", "rows_affected"=>0, "last_autoinc"=>0}

rails extract data from simple json response

I need to extract some data from a JSON response i'm serving up from curb.
Previously I wasn't calling symbolize_keys, but i thought that would make my attempt work.
The controller action:
http = Curl.get("http://api.foobar.com/thing/thing_name/catalog_items.json?per_page=1&page=1") do|http|
http.headers['X-Api-Key'] = 'georgeBushSucks'
end
pre_keys = http.body_str
#foobar = ActiveSupport::JSON.decode(pre_keys).symbolize_keys
In the view (getting undefined method `current_price' )
#foobar.current_price
I also tried #foobar.data[0]['current_price'] with the same result
JSON response from action:
{
"data": {
"catalog_items": [
{
"current_price": "9999.0",
"close_date": "2013-05-14T16:08:00-04:00",
"open_date": "2013-04-24T11:00:00-04:00",
"stuff_count": 82,
"minimum_price": "590000.0",
"id": 337478,
"estimated_price": "50000.0",
"name": "This is a really cool name",
"current_winner_id": 696969,
"images": [
{
"thumb_url": "http://foobar.com/images/93695/thumb.png?1365714300",
"detail_url": "http://foobar.com/images/93695/detail.png?1365714300",
"position": 1
},
{
"thumb_url": "http://foobar.com/images/95090/thumb.jpg?1366813823",
"detail_url": "http://foobar.com/images/95090/detail.jpg?1366813823",
"position": 2
}
]
}
]
},
"pagination": {
"per_page": 1,
"page": 1,
"total_pages": 131,
"total_objects": 131
}
}
Please note that accessing hash's element in Rails work in models. To use it on hash, you have to use OpenStruct object. It's part of standard library in rails.
Considering, #foobar has decoded JSON as you have.
obj = OpenStruct.new(#foobar)
obj.data
#=> Hash
But, note that, obj.data.catalog_items willn't work, because that is an hash, and again not an OpenStruct object. To aid this, we have recursive-open-struct, which will do the job for you.
Alternative solution [1]:
#foobar[:data]['catalog_items'].first['current_price']
But, ugly.
Alternative solution [2]:
Open Hash class, use method_missing ability as :
class Hash
def method_missing(key)
self[key.to_s]
end
end
Hope it helps. :)

Resources