how to make this method more efficient Rails 3? - ruby-on-rails

i want to make my method more efficient. my method take so much time in response. so please edit my code to get more efficient response.i am very thank full to you if you make this method more more efficient. and you are master in ruby on rails then if you can make this method with joins then what a wounder full method is it for me.
thanks
def all_shows_with_videos
#arr = []
tvs = Tv.all
tvs.each do |tv|
tv_tmp = {:name => tv.name, :id => tv.id}
tv_tmp[:videos] = tv.videos
tv_tmp[:seasons] = []
season_tmp = {}
tv.seasons.each do |season|
season_tmp = {:name => season.name, :id => season.id}
season_tmp[:videos] = season.videos
season_tmp[:episodes] = []
season.episodes.each do |episode|
season_tmp[:episodes] << {:name => episode.name, :id => episode.id} if episode.videos?
end
tv_tmp[:seasons].push(season_tmp) if !season_tmp[:videos].blank? or !season_tmp[:episodes].blank?
end
#arr.push(tv_tmp) if !tv_tmp[:videos].blank? or !tv_tmp[:seasons].blank?
end
#arr = Kaminari.paginate_array(#arr).page(params[:page]).per(5)
respond_to do |format|
format.json {render :json => #arr}
end
end
and output is
[
{
"name": "Iron Man",
"id": 95,
"videos": [
{
"id": 1,
"name": "Trailer 1",
"site": "Youtube.com",
"link": "Google.com",
"quality": null,
"video_type": null,
"videoable_id": 95,
"videoable_type": "Tv",
"created_at": "2014-05-26T07:05:39+05:00",
"video_source": null,
"video_source_cd": null
}
],
"seasons": []
},
{
"name": "How I Met Your Mother",
"id": 100,
"videos": [
{
"id": 13,
"name": "Trailer 1",
"site": null,
"link": "google.com",
"quality": "1020",
"video_type": "Trailer",
"videoable_id": 100,
"videoable_type": "Tv",
"created_at": "2014-06-09T10:05:03+05:00",
"video_source": null,
"video_source_cd": null
}
],
"seasons": []
},
{
"name": "my tv",
"id": 124,
"videos": [
{
"id": 59,
"name": "Trailer 1",
"site": null,
"link": "google.com",
"quality": "1020",
"video_type": "Trailer",
"videoable_id": 124,
"videoable_type": "Tv",
"created_at": "2014-06-20T06:59:32+05:00",
"video_source": null,
"video_source_cd": null
}
],
"seasons": []
},
{
"name": "Game of Thrones",
"id": 151,
"videos": [
{
"id": 129,
"name": "",
"site": null,
"link": null,
"quality": null,
"video_type": "Season",
"videoable_id": 151,
"videoable_type": "Tv",
"created_at": "2014-09-02T11:13:40+05:00",
"video_source": null,
"video_source_cd": null
},
{
"id": 130,
"name": "",
"site": null,
"link": "",
"quality": null,
"video_type": null,
"videoable_id": 151,
"videoable_type": "Tv",
"created_at": "2014-09-02T11:13:40+05:00",
"video_source": null,
"video_source_cd": null
},
{
"id": 131,
"name": "",
"site": null,
"link": "",
"quality": null,
"video_type": null,
"videoable_id": 151,
"videoable_type": "Tv",
"created_at": "2014-09-02T11:13:40+05:00",
"video_source": null,
"video_source_cd": null
}
],
"seasons": []
},
{
"name": "Under the Dome",
"id": 160,
"videos": [],
"seasons": [
{
"name": "Season Specials",
"id": 267,
"videos": [],
"episodes": [
{
"name": "Inside Chester's Mill",
"id": 1112
}
]
}
]
}
]

First step is to move your logic to model, that way your controller will get more skinnier
in your Tv model
def self.all_with_seasons_and_episodes
tvs = includes(:videos, :seasons => [:videos, :episodes]).all
# loads all tvs and all its videos and seasons, seasons videos and episodes
tvs.map do |tv|
{
name: tv.name,
id: tv.id,
videos: tv.videos,
seasons: tv.map_seasons
}
end
end
private
def map_seasons
seasons.map do |s|
{
id: s.id,
name: s.name,
videos: s.videos,
episode: s.episodes.map {|e| {name: e.name, id: e.id} }
}
end
end
now you can use in like
def all_shows_with_videos
arr = Tv.all_with_seasons_and_episodes
#arr = Kaminari.paginate_array(arr).page(params[:page]).per(5)
respond_to do |format|
format.json {render :json => #arr}
end
end

Related

How to merge a JSON-object in Jbuilder

I am creating a rails app with Backbone/Marionette frontend.
I want to take the JSON-object below and transform it.
This is how it looks now
[{
"total_entries": 4
},
{
"entries": [{
"user": {
"id": 1,
"fullname": "Paul Paulsen"
},
"reports": [{
"id": 1,
"name": "Anna Pearson",
"relation": "wife",
"phone": "2232",
"email": "adsas#sss.se"
}
]
},
{
"user": {
"id": 2,
"fullname": "Anna Palmgren"
},
"reports": [{
"id": 3,
"name": "Mika",
"relation": "Andersen",
"phone": "12312321",
"email": "aas#sss.se"
}]
}
]
}
]
I want to make it look like this
[{
"total_entries": 4
},
{
"entries": [{
"id": 1,
"fullname": "Paul Paulsen"
}, {
"id": 1,
"name": "Anna Pearson",
"relation": "wife",
"phone": "2232",
"email": "adsas#sss.se"
}, {
"id": 1,
"fullname": "Anna Palmgren"
}, {
"id": 3,
"name": "Mika",
"relation": "Andersen",
"phone": "12312321",
"email": "aas#sss.se"
}
]
}
]
This is the Rabl file/code I use
json.array! [0,1] do |index|
if index == 0
json.total_entries #total
else
json.entries #reports.group_by(&:user) do |user, reports|
json.user user, :id, :fullname
json.reports reports do |report|
json.extract! report, :id, :name, :relation, :phone, :email
end
end
end
end
Try this ruby snippet.
x= [{
"total_entries": 4
},
{
"entries": [{
"user": {
"id": 1,
"fullname": "Paul Paulsen"
},
"reports": [{
"id": 1,
"name": "Anna Pearson",
"relation": "wife",
"phone": "2232",
"email": "adsas#sss.se"
}
]
},
{
"user": {
"id": 2,
"fullname": "Anna Palmgren"
},
"reports": [{
"id": 3,
"name": "Mika",
"relation": "Andersen",
"phone": "12312321",
"email": "aas#sss.se"
}]
}
]
}
]
x[1][:entries] = x[1][:entries].map{|p| [p[:user], p[:reports]]}.flatten

json data stripe webhook

Im trying to implement stripe webhooks in my rails app. The webhook send this json data.
{ "created": 1326853478, "livemode": false, "id": "evt_00000000000000", "type": "invoice.payment_succeeded", "object": "event", "request": null, "pending_webhooks": 1, "api_version": "2017-06-05", "data": {
"object": {
"id": "in_00000000000000",
"object": "invoice",
"amount_due": 500,
"application_fee": null,
"attempt_count": 1,
"attempted": true,
"charge": "_00000000000000",
"closed": true,
"currency": "usd",
"customer": "cus_00000000000000",
"date": 1501950408,
"description": null,
"discount": null,
"ending_balance": 0,
"forgiven": false,
"lines": {
"data": [
{
"id": "sub_BLXcTSekdHflq5",
"object": "line_item",
"amount": 500,
"currency": "usd",
"description": null,
"discountable": true,
"livemode": true,
"metadata": {
},
"period": {
"start": 1507246341,
"end": 1509924741
},
"plan": {
"id": "Subscriber",
"object": "plan",
"amount": 500,
"created": 1501901993,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {
},
"name": "Subscriber",
"statement_descriptor": "WatchBuddie Stream sub",
"trial_period_days": null
},
"proration": false,
"quantity": 1,
"subscription": null,
"subscription_item": "si_1AyqWnFr5iCt1Tv7n23zDLOM",
"type": "subscription"
}
],
"total_count": 1,
"object": "list",
"url": "/v1/invoices/in_1AnV6yFr5iCt1Tv7PnqZ0EUA/lines"
},
"livemode": false,
"metadata": {
},
"next_payment_attempt": null,
"paid": true,
"period_end": 1501950408,
"period_start": 1501950408,
"receipt_number": null,
"starting_balance": 0,
"statement_descriptor": null,
"subscription": "sub_00000000000000",
"subtotal": 500,
"tax": null,
"tax_percent": null,
"total": 500,
"webhooks_delivered_at": 1501950409
} } }
webhook method
def webhooks
begin
event_json = JSON.parse(request.body.read)
event_object = event_json['data']['object']
#refer event types here https://stripe.com/docs/api#event_types
case event_json['type']
when 'invoice.payment_succeeded'
#Update the total subscription total
#Send in email to the user telling them that they resubbed
logger.debug event_object['lines']['id']
end
My question is how do I get the "id": "sub_BLXcTSekdHflq5" I tried
logger.debug event_object['lines']['id']
It doesn't seem to be working what am I doing wrong? I'm sure its just a syntax thing that I am not understanding.
Thanks for all the help!
Figured it out the lines data was in a hash so you had to iterate over it. This is what I did for anyone who comes across this.
event_object['lines']['data'].each{ |i|
sub_id = i['id']
logger.debug sub_id
}

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?

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.

Render json to Grails domain list object

If there is one record in request.json the below code works
class BookController {
def save = {
def book = new Book(JSON.parse(yourJson))
book.save(flush:true)
}
}
But how to get bookList if there is multiple records in my request.JSON like:
[{
"id": 3,
"name": "MYNAME",
"description": "test",
"category": 1,
"venue": null,
"status": "Published",
"deleted": false,
"pricingPolicy": null
}, {
"id": 6,
"name": "YZ",
"description": "test6",
"category": 2,
"venue": null,
"status": "Unpublished",
"deleted": false,
"pricingPolicy": null
}, {
"id": 9,
"name": "YZ",
"description": "test6",
"category": 1,
"venue": null,
"status": "Published",
"deleted": false,
"pricingPolicy": null
}]
request.JSON.each{ new Book( it ).save() }
should do

Resources