Mapping JSON Response to Model - ruby-on-rails

New to the notion of Rails mapping, and would love to get some help on this from the stack overflow community.
Currently I have this JSON response from the Embedly API and don't really know how to map it to my very simple 'posts' model. I'm trying to get the image/title/url from the JSON response and map it into my database in the relevant fields, so in the JSON response below these would be 'original_url', 'image' and 'title'.
{
"provider_url": "http://piccsy.com",
"authors": [],
"provider_display": "piccsy.com",
"related": [],
"favicon_url": "http://piccsy.com/favicon.ico",
"keywords": [],
"app_links": [],
"original_url": "http://piccsy.com/2015/02/rihanna-sharks-harpers-bazaar-march-2015-photoshoot3",
"media": {},
"content": null,
"entities": [],
"provider_name": "Piccsy",
"type": "html",
"description": "Beautiful, inspirational and creative images from Piccsy. Thousands of Piccs from all our streams, for you to browse, enjoy and share with a friend.",
"embeds": [],
"images": [
{
"width": 728,
"url": "http://img2.piccsy.com/cache/images/56/8f/bed__396d8_cecf850824130_99f-post.jpg",
"height": 1092,
"caption": null,
"colors": [
{
"color": [
190,
211,
212
],
"weight": 0.3095703125
},
{
"color": [
114,
159,
171
],
"weight": 0.247314453125
},
{
"color": [
0,
52,
68
],
"weight": 0.244140625
},
{
"color": [
25,
99,
117
],
"weight": 0.198974609375
}
],
"entropy": 5.94797179868,
"size": 318918
},
{
"width": 200,
"url": "http://piccsy.com/piccsy/images/layout/logo/e02f43.200x200.jpg",
"height": 200,
"caption": null,
"colors": [
{
"color": [
215,
51,
67
],
"weight": 0.701904296875
},
{
"color": [
250,
252,
252
],
"weight": 0.298095703125
}
],
"entropy": 0.686638083774,
"size": 18691
}
],
"safe": true,
"offset": null,
"cache_age": 86065,
"lead": null,
"language": null,
"url": "http://piccsy.com/2015/02/rihanna-sharks-harpers-bazaar-march-2015-photoshoot3",
"title": "Rihanna-sharks-harpers-bazaar-march-2015-photoshoot3",
"favicon_colors": [
{
"color": [
208,
37,
38
],
"weight": 0.000244140625
},
{
"color": [
0,
0,
0
],
"weight": 0.000244140625
}
],
"published": null
}
My posts model contains very simple name, url and image fields which are all accepting strings. Any help on mapping this to a model would be brilliant, up till now I've only done very simple JSON responses and this one is a bit out of my league.
Thanks for your time.

You can just parse json response, and get required fields from it
json_response = '{your json response from api}'
response_hash = JSON.parse(json_response)
MyModel.create!(url: response_hash[:original_url], title: response_hash[:title])
But there is problem with images, response contains multiple images, so probably you should have ImageModel that belongs to MyModel, and MyModel has_many ImageModels.
Then you can do:
model = MyModel.create!(url: response_hash[:original_url], title: response_hash[:title])
response_hash[:images].each do |image|
model.images.create!(url: image[:url])
end

Related

Shopify products/delete webhook only returns ID

My ruby on rails app is supposed to do some things whenever a product is deleted. According to Shopify's website here the response to products/delete is supposed to be a JSON object with information such as the product_id associated with the product that was deleted:
{
"id": 788032119674292922,
"title": "Example T-Shirt",
"body_html": null,
"vendor": "Acme",
"product_type": "Shirts",
"created_at": null,
"handle": "example-t-shirt",
"updated_at": "2021-07-01T14:08:43-04:00",
"published_at": "2021-07-01T14:08:43-04:00",
"template_suffix": null,
"published_scope": "web",
"tags": "example, mens, t-shirt",
"admin_graphql_api_id": "gid:\/\/shopify\/Product\/788032119674292922",
"variants": [
{
"id": 642667041472713922,
"product_id": 788032119674292922,
"title": "",
"price": "19.99",
"sku": "example-shirt-s",
"position": 0,
"inventory_policy": "deny",
"compare_at_price": "24.99",
"fulfillment_service": "manual",
"inventory_management": "shopify",
"option1": "Small",
"option2": null,
"option3": null,
"created_at": null,
"updated_at": null,
"taxable": true,
"barcode": null,
"grams": 200,
"image_id": null,
"weight": 200.0,
"weight_unit": "g",
"inventory_item_id": null,
"inventory_quantity": 75,
"old_inventory_quantity": 75,
"requires_shipping": true,
"admin_graphql_api_id": "gid:\/\/shopify\/ProductVariant\/642667041472713922"
},
{
"id": 757650484644203962,
"product_id": 788032119674292922,
"title": "",
"price": "19.99",
"sku": "example-shirt-m",
"position": 0,
"inventory_policy": "deny",
"compare_at_price": "24.99",
"fulfillment_service": "manual",
"inventory_management": "shopify",
"option1": "Medium",
"option2": null,
"option3": null,
"created_at": null,
"updated_at": null,
"taxable": true,
"barcode": null,
"grams": 200,
"image_id": null,
"weight": 200.0,
"weight_unit": "g",
"inventory_item_id": null,
"inventory_quantity": 50,
"old_inventory_quantity": 50,
"requires_shipping": true,
"admin_graphql_api_id": "gid:\/\/shopify\/ProductVariant\/757650484644203962"
}
],
"options": [
{
"id": 527050010214937811,
"product_id": 788032119674292922,
"name": "Title",
"position": 1,
"values": [
"Small",
"Medium"
]
}
],
"images": [
{
"id": 539438707724640965,
"product_id": 788032119674292922,
"position": 0,
"created_at": null,
"updated_at": null,
"alt": null,
"width": 323,
"height": 434,
"src": "\/\/cdn.shopify.com\/shopifycloud\/shopify\/assets\/shopify_shirt-39bb555874ecaeed0a1170417d58bbcf792f7ceb56acfe758384f788710ba635.png",
"variant_ids": [
],
"admin_graphql_api_id": "gid:\/\/shopify\/ProductImage\/539438707724640965"
}
],
"image": null
}
However, whenever I go to test it by actually deleting a product in the Shopify Admin interface, I'm only getting the id in my response. Anybody know why this is happening? My setup for the other webhooks is the exact same and I'm not having any other issues.
Seems like this is an open issue on the shopify_api gem for version 2021-01. I don't think you are doing anything wrong. It looks like nobody has responded in a while to the issue, you might want to try to upgrade to another version to see if they fixed it in any of the newer versions.
EDIT: According to a post from 3/2017 the expected behaviour from deleted endpoints is to only return the ID of the resource that was deleted. This could be why the issue on Github is being ignored.

Spree API 3.7 : Images comes as separate object instead of embedded inside product itself

Spree API when hitting /products?include=images path gives the response in following format.
{
"data": [...],
"included": [
{
"id": "4",
"type": "image",
"attributes": {
"viewable_type": "Spree::Variant",
"viewable_id": 3,
"styles": [
{
"url": "/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--bd6df012d992b43227344ecb03dc0ab6e13b1555/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9MY21WemFYcGxTU0lMTkRoNE5EZytCam9HUlZRPSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--504f95c059f17243e0d7d1312e2b387f26a40aff/bg.jpg",
"width": "48",
"height": "48"
},
{
"url": "/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--bd6df012d992b43227344ecb03dc0ab6e13b1555/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9MY21WemFYcGxTU0lOTVRBd2VERXdNRDRHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6InZhcmlhdGlvbiJ9fQ==--594f543b42e0bfafbe9d09df814e1d60837f9ef6/bg.jpg",
"width": "100",
"height": "100"
},
{
"url": "/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--bd6df012d992b43227344ecb03dc0ab6e13b1555/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9MY21WemFYcGxTU0lOTWpRd2VESTBNRDRHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6InZhcmlhdGlvbiJ9fQ==--46583de60196cb1eee5b4a704d67209eee40c09a/bg.jpg",
"width": "240",
"height": "240"
},
{
"url": "/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--bd6df012d992b43227344ecb03dc0ab6e13b1555/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9MY21WemFYcGxTU0lOTmpBd2VEWXdNRDRHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6InZhcmlhdGlvbiJ9fQ==--3b3e65d1d9c712d2d540e15aa84ca541eb12b365/bg.jpg",
"width": "600",
"height": "600"
}
]
}
}],
"meta": {
"count": 14,
"total_count": 14,
"total_pages": 1
},
"links": {
"self": "https://galific.herokuapp.com/api/v2/storefront/products?include=variants.images",
"next": "https://galific.herokuapp.com/api/v2/storefront/products?include=variants.images&page=1",
"prev": "https://galific.herokuapp.com/api/v2/storefront/products?include=variants.images&page=1",
"last": "https://galific.herokuapp.com/api/v2/storefront/products?include=variants.images&page=1",
"first": "https://galific.herokuapp.com/api/v2/storefront/products?include=variants.images&page=1"
}
}
}
Here you can see the image URL's are coming as included object. While developing for mobile its not a good idea to put the very crucial element (product image path in this case) in separate object. This require the mobile dev to loop unnecessary just to get the image path which can be provided within the image relationships object like this:
"images": {
"data": [
{
"id": "2",
"type": "image",
"url" : 'image-path.jpg'
}]
}
The image path should be included in data object itself rather than separated include object. Is there any way to do it without messing with source??

How to get the progress of a running build using TFS REST API?

I'm monitoring builds on TFS & VSTS and would like to know how to get the overall progress (in percentage) of a running build or release.
You could use Rest API Get build details with timeline.
GET https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/timeline?api-version={version}
Which will return build timeline and some more detail info including a percentComplete result. Note: this is task level based just like the build log in webportal, not the entire build.
Sample response
{
"records": [
{
"id": "bcddc27d-c891-4209-85d6-387e155439b0",
"parentId": "045f4ce9-cb71-424f-84de-4ab19281dc70",
"type": "Task",
"name": "Build solution **\\*.sln",
"startTime": "2015-07-16T19:53:20.853Z",
"finishTime": "2015-07-16T19:53:28.567Z",
"currentOperation": null,
"percentComplete": 100,
"state": "completed",
"result": "succeeded",
"resultCode": null,
"changeId": 16,
"lastModified": "0001-01-01T00:00:00",
"workerName": "Hosted Agent",
"order": 2,
"details": {
"id": "ef959107-e566-4c28-8d9f-354d605dd400",
"changeId": 6,
"url": "https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c/_apis/build/builds/391/Timeline/ef959107-e566-4c28-8d9f-354d605dd400"
},
"errorCount": 0,
"warningCount": 1,
"url": null,
"log": {
"id": 2,
"type": "Container",
"url": "https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c/_apis/build/builds/391/logs/2"
},
"issues": [
{
"type": "warning",
"category": "General",
"message": "The MSBuild version parameter has been deprecated. Ignoring value: latest",
"data": {
"type": "warning"
}
}
]
},
{
"id": "b5bb4de7-a8ea-4c7d-8491-3f745bba7d1b",
"parentId": "045f4ce9-cb71-424f-84de-4ab19281dc70",
"type": "Task",
"name": "Get sources",
"startTime": "2015-07-16T19:53:07.057Z",
"finishTime": "2015-07-16T19:53:19.493Z",
"currentOperation": null,
"percentComplete": 100,
"state": "completed",
"result": "succeeded",
"resultCode": null,
"changeId": 13,
"lastModified": "0001-01-01T00:00:00",
"workerName": "Hosted Agent",
"order": 1,
"details": null,
"errorCount": 0,
"warningCount": 0,
"url": null,
"log": {
"id": 1,
"type": "Container",
"url": "https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c/_apis/build/builds/391/logs/1"
}
},

Beautify JSON parsing with Hashie::Mash Rash?

Trying to parse some ugly JSON:
image = product.images.find { |i| i["sizeName"] == "Large" }
If I use Hashie::Mash Rash, can I make it look like this instead?
image = product.images.find { |i| i["size_name"] == "large" }
If so, why am I getting undefined method 'each_pair' for #<Array:0x007f84a0408540>? Please see https://gist.github.com/frankie-loves-jesus/6b8012f9197ca6c675a9 for a full example including a live app.
Example JSON:
{
"metadata": {
"category": {
"id": "women",
"name": "Women's Fashion"
},
"showSizeFilter": false,
"showColorFilter": true,
"offset": 0,
"limit": 20,
"total": 974184
},
"products": [
{
"id": 377083005,
"name": "BCBGeneration Women's Contrast Sleeve Trench",
"currency": "USD",
"price": 168,
"priceLabel": "$168.00",
"salePrice": 106.43,
"salePriceLabel": "$106.43",
"inStock": true,
"retailer": {
"id": "849",
"name": "Amazon.com",
"url": "http://www.shopstyle.com/browse/Amazon.com-US?pid=uid9616-726296-93"
},
"locale": "en_US",
"description": "This jacket features contrasting leather sleeves",
"brand": {
"id": "51",
"name": "BCBG MAX AZRIA",
"url": "http://www.shopstyle.com/browse/BCBG-MAX-AZRIA?pid=uid9616-726296-93"
},
"clickUrl": "http://api.shopstyle.com/action/apiVisitRetailer?id=377083005&pid=uid9616-726296-93",
"images": [
{
"sizeName": "Small",
"width": 32,
"height": 40,
"url": "http://resources.shopstyle.com/pim/7b/28/7b2894c203529b0956cdd6b760629d4a_small.jpg"
},
{
"sizeName": "Medium",
"width": 112,
"height": 140,
"url": "http://resources.shopstyle.com/pim/7b/28/7b2894c203529b0956cdd6b760629d4a_medium.jpg"
},
{
"sizeName": "Large",
"width": 164,
"height": 205,
"url": "http://resources.shopstyle.com/pim/7b/28/7b2894c203529b0956cdd6b760629d4a.jpg"
}
],
"colors": [
{
"name": "Chino"
}
],
"sizes": [
{
"name": "XX-Small"
},
{
"name": "X-Small"
}
],
"categories": [
{
"id": "raincoats-and-trenchcoats",
"name": "Raincoats & Trenchcoats"
}
]
}
]
}
This is my working code
require 'json'
require 'rash'
#json_text = <<END
{
"metadata": {
"category": {
"id": "women",
"name": "Women's Fashion"
},
"showSizeFilter": false,
"showColorFilter": true,
"offset": 0,
"limit": 20,
"total": 974184
},
"products": [
{
"id": 377083005,
"name": "BCBGeneration Women's Contrast Sleeve Trench",
"currency": "USD",
"price": 168,
"priceLabel": "$168.00",
"salePrice": 106.43,
"salePriceLabel": "$106.43",
"inStock": true,
"retailer": {
"id": "849",
"name": "Amazon.com",
"url": "http://www.shopstyle.com/browse/Amazon.com-US?pid=uid9616-726296-93"
},
"locale": "en_US",
"description": "This jacket features contrasting leather sleeves",
"brand": {
"id": "51",
"name": "BCBG MAX AZRIA",
"url": "http://www.shopstyle.com/browse/BCBG-MAX-AZRIA?pid=uid9616-726296-93"
},
"clickUrl": "http://api.shopstyle.com/action/apiVisitRetailer?id=377083005&pid=uid9616-726296-93",
"images": [
{
"sizeName": "Small",
"width": 32,
"height": 40,
"url": "http://resources.shopstyle.com/pim/7b/28/7b2894c203529b0956cdd6b760629d4a_small.jpg"
},
{
"sizeName": "Medium",
"width": 112,
"height": 140,
"url": "http://resources.shopstyle.com/pim/7b/28/7b2894c203529b0956cdd6b760629d4a_medium.jpg"
},
{
"sizeName": "Large",
"width": 164,
"height": 205,
"url": "http://resources.shopstyle.com/pim/7b/28/7b2894c203529b0956cdd6b760629d4a.jpg"
}
],
"colors": [
{
"name": "Chino"
}
],
"sizes": [
{
"name": "XX-Small"
},
{
"name": "X-Small"
}
],
"categories": [
{
"id": "raincoats-and-trenchcoats",
"name": "Raincoats & Trenchcoats"
}
]
}
]
}
END
hash = JSON.parse(#json_text)
#rash = Hashie::Rash.new( hash )
images = []
#rash.products.each do |product|
images << product.images.find { |i| i.size_name.downcase == "large" }
end
puts images.inspect
#[#<Hashie::Rash height=205 size_name="Large" url="http://resources.shopstyle.com/pim/7b/28/7b2894c203529b0956cdd6b760629d4a.jpg" width=164>]
It doesn't raise the error you have mentioned.
And I use
$ruby --version
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin13.0.0]
gem list --local |grep 'rash'
rash (0.4.0)
$gem list --local |grep 'hashie'
hashie (3.2.0, 2.0.5)
Could you check yours?
And, if possible, dump the json at the moment that it raises the error.

Fetch photos from Instagram

Currently I'm able to fetch the photos of the logged in user in my app. But I want to fetch the photos from my instagram developer account in which I have registered my app. Is this possible? Currently,
NSString *urlString=[NSString stringWithFormat:#"https://api.instagram.com/v1/users/self/feed/?access_token=%#",appDelegate.instagram.accessToken];
fetches the detail of the logged in user. But I want to get the photos from my client's instagram account. Replacing 'self' in the above url with client's username doesn't work. Any ideas ?
Can't you use the /users/user-id/media/recent Endpoint?
Example from Instagram API Documentation, to get Feed for UserID = 3, use following
https://api.instagram.com/v1/users/3/media/recent/?access_token=ACCESS-TOKEN
Returns
{
"data": [{
"comments": {
"data": [],
"count": 0
},
"caption": {
"created_time": "1296710352",
"text": "Inside le truc #foodtruck",
"from": {
"username": "kevin",
"full_name": "Kevin Systrom",
"type": "user",
"id": "3"
},
"id": "26621408"
},
"likes": {
"count": 15,
"data": [{
"username": "mikeyk",
"full_name": "Mike Krieger",
"id": "4",
"profile_picture": "..."
}, {...subset of likers...}]
},
"link": "http://instagr.am/p/BWrVZ/",
"user": {
"username": "kevin",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
},
"created_time": "1296710327",
"images": {
"low_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_7.jpg",
"width": 612,
"height": 612
}
},
"type": "image",
"users_in_photo": [],
"filter": "Earlybird",
"tags": ["foodtruck"],
"id": "22721881",
"location": {
"latitude": 37.778720183610183,
"longitude": -122.3962783813477,
"id": "520640",
"street_address": "",
"name": "Le Truc"
}
},
{
"videos": {
"low_resolution": {
"url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_102.mp4",
"width": 480,
"height": 480
},
"standard_resolution": {
"url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_101.mp4",
"width": 640,
"height": 640
},
"comments": {
"data": [{
"created_time": "1279332030",
"text": "Love the sign here",
"from": {
"username": "mikeyk",
"full_name": "Mikey Krieger",
"id": "4",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1242695_75sq_1293915800.jpg"
},
"id": "8"
},
{
"created_time": "1279341004",
"text": "Chilako taco",
"from": {
"username": "kevin",
"full_name": "Kevin S",
"id": "3",
"profile_picture": "..."
},
"id": "3"
}],
"count": 2
},
"caption": null,
"likes": {
"count": 1,
"data": [{
"username": "mikeyk",
"full_name": "Mikeyk",
"id": "4",
"profile_picture": "..."
}]
},
"link": "http://instagr.am/p/D/",
"created_time": "1279340983",
"images": {
"low_resolution": {
"url": "http://distilleryimage2.ak.instagram.com/11f75f1cd9cc11e2a0fd22000aa8039a_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distilleryimage2.ak.instagram.com/11f75f1cd9cc11e2a0fd22000aa8039a_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distilleryimage2.ak.instagram.com/11f75f1cd9cc11e2a0fd22000aa8039a_7.jpg",
"width": 612,
"height": 612
}
},
"type": "video",
"users_in_photo": null,
"filter": "Vesper",
"tags": [],
"id": "363839373298",
"user": {
"username": "kevin",
"full_name": "Kevin S",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
},
"location": null
},
]
}
Instagram only provides the API to get the feeds of self .. Have a look on
https://api.instagram.com/v1/users/userID/media/recent
this i hope it provides some recent medias of a user for more info look at this
http://instagram.com/developer/api-console/

Resources