Rails how to calculate multiple sums from one query data - ruby-on-rails

With the following two models, Company and Response, I am making a query of the total responses per company like this:
#allResponses = Company.find(current_user_company_id).responses
this gives me data like this:
[#<Response id: 1, company_id: 1, created_at: "2013-04-24 02:36:54", feedback_score: 10, feedback_explanation: "I really like the way you guys do xyz.", additional_data: "", updated_at: "2013-04-24 02:36:54">, #<Response id: 2, company_id: 1, created_at: "2013-04-25 03:51:07", feedback_score: 5, feedback_explanation: "customer service is spotty.", additional_data: "", updated_at: "2013-04-25 03:51:07">, #<Response id: 3, company_id: 1, created_at: "2013-04-25 03:52:04", feedback_score: 7, feedback_explanation: "You've got potential.", additional_data: "", updated_at: "2013-04-25 03:52:04">, #<Response id: 4, company_id: 1, created_at: "2013-04-25 03:52:18", feedback_score: 9, feedback_explanation: "Almost perfect.", additional_data: "", updated_at: "2013-04-25 03:52:18">]
I want to get the following two variables out of this data:
#sumOfHighScores = some.thing.here #sum of feedback_scores that are greater than 8
#sumOfLowScores = some.thing.here.too #sum of feedback_scores that are less than 7

You can try this,
#sumOfHighScores = #allResponses.select{ |response| response.feedback_score > 8 }.map(&:feedback_score).sum
#sumOfLowScores = #allResponses.select{ |response| response.feedback_score < 7 }.map(&:feedback_score).sum

Try this..
#sumOfHighScores = #allResponses.select{ |response| response.feedback_score > 8 }.sum
#sumOfLowScores = #allResponses.select{ |response| response.feedback_score < 7 }.sum

I will perform the entire calculation in the database.
company = Company.find(current_user_company_id)
totals = company.responses.sum(
:feedback_score,
:group => "CASE WHEN feedback_score < 7 THEN 'low' ELSE 'high' END")
low, high = (totals['low'] || 0), (totals['high'] || 0 )

Related

Rails effective way of looping through daterange

I have ScheduleDay model as;
=> #<ActiveRecord::Relation [#<ScheduleDay id: 1, from: "2017-01-21 00:00:00", to: "2017-01-30 00:00:00", weekday: 100, weekend: 200, weekly: 90, available: true, check_in: "09:00", check_out: "18:00", min_stay: 2, sevendays: false, check_in_day: nil, created_at: "2017-01-14 11:25:18", updated_at: "2017-01-14 11:27:00">, #<ScheduleDay id: 2, from: "2017-02-05 00:00:00", to: "2017-02-15 00:00:00", weekday: 150, weekend: 200, weekly: 140, available: nil, check_in: "09:00", check_out: "18:00", min_stay: 3, sevendays: false, check_in_day: nil, created_at: "2017-01-14 15:53:21", updated_at: "2017-01-14 15:54:43">, #<ScheduleDay id: 3, from: "2017-03-15 00:00:00", to: "2017-06-15 00:00:00", weekday: nil, weekend: nil, weekly: nil, available: false, check_in: nil, check_out: nil, min_stay: 1, sevendays: false, check_in_day: nil, created_at: "2017-01-14 15:56:01", updated_at: "2017-01-14 15:56:57">, #<ScheduleDay id: 4, from: "2017-08-05 00:00:00", to: "2017-09-30 00:00:00", weekday: 500, weekend: 500, weekly: 500, available: true, check_in: "09:00", check_out: "18:00", min_stay: 7, sevendays: true, check_in_day: "Saturday", boat_id: nil, created_at: "2017-01-14 16:01:00", updated_at: "2017-01-14 16:02:10">]>
I have another date range and I would like to loop over my date range in ScheduleDay table and if record is found get some data. If not found then get data as well. I tried couple different way but I m looking for the most efficient way in ruby.
first = Date.parse("05.2.2017")
last = (Date.parse("16.2.2017"))
schedules = ScheduleDay.where(from: Date.today..(last+1.day))
dates = []
(first..last).each do |date|
flag = 0
catch :date_found do
schedules.each do |s|
(s.from.to_date..s.to.to_date).each do |d|
puts date
puts d
if date == d
flag += 1
puts 'found'
throw :date_found
end
end
end
if flag == 0
puts 'date not found'
end
end
end
This is what I have tried so far. But the problem here is I can not access the record if it is not found. If I take;
if flag == 0
puts 'date not found'
end
inside schedules.each... loop then it prints not found for every record in ScheduleDay. I want to loop through all ScheduleDay record and if not found get some data.
EDIT:
I have database records saved by the user. User can customize any date of the year by selecting date range and pricing. I ask user base pricing as well.
So, lets say user entered 15.01.2017 & 21.01.2017 custom price: 100 and base price 200 (base price will be used if date is not found on database date-range).
I would like to return json array of February. So I need;
01.01.2017 -> custom price exists? if not get base price
02.01.2017 -> custom price exists? if not get base price
...
15.01.2017 -> yes! custom price exists get custom price
16.01.2017 -> yes! custom price exists get custom price
17.01.2017 -> yes! custom price exists get custom price
18.01.2017 -> yes! custom price exists get custom price
...
21.01.2017 -> yes! custom price exists get custom price
...
31.01.2017 -> custom price exists? if not get base price
then create json
EDIT2
What if I use;
first = Date.parse("05.2.2017")
last = Date.parse("16.2.2017")
(first..last).each do |date|
schedules.each do |s|
d2 = (s.from.to_date..s.to.to_date)
puts d2 === date
puts d2
puts date
end
end
=== checks date is in the range.

How to get the data using find_by Or where in rails?

Truck
id: 1,
vehicle_registration_number: "TN38CC6077",
chassis_number: "12345",
created_at: "2016-09-06 05:39:19",
updated_at: "2016-09-06 05:39:19",
company_truck_type_id: 1,
location_id: 492,
available_date: ["2016-09-10",
"2016-09-20"],
booked_status: "Available",
active: true,
manager_id: 3,
loading_supervisor_id: 3,
transport_supervisor_id: 3,
user_id: 3,
status: "just_in",
price: #<BigDecimal:afae0204,'0.109E5',9(18)>,
source_id: 492,
destination_id: 3,
notes: ["HelloWorld"]
This is my data in a table. From Here I have use available_date to find a current data,but it can't working. How can I get based on current date?
#truck[0].where(available_date:["2016-09-10"]["2016-09-20"])
It's not working. I want to check if the current date is between the available_date or not?
you can do something like below:
Truck.where(available_date: (Time.now.midnight - 1.day)..Time.now.midnight)
Hope that helps you.
Try this code snippets ;
def current_date_is_available?(available_date)
current_date = Date.parse(Time.now.to_s)
Date.parse(available_date.first) < current_date && current_date < Date.parse(available_date.second)
end
in controller ;
if current_date_is_available?(#truck[0].available_date)
# do whatever you want
end

'Where-in' query in postgresql for two different queries showing same result

I have the active record assosciation relation as follows.
#tasks = #<ActiveRecord::AssociationRelation [#<Task id: 3130, title: "Commit to at least one small win today", content: "When I check-in on the app it lets me acknowledge m...",created_at: "2016-01-13 01:36:15", updated_at: "2016-01-13 04:47:57", state: "active", #<Task id: 3131, title: "Purposefully walk 3 minutes ", content: "More than just my ordinary day, I choose 5 minutes ...", created_at: "2016-01-13 04:52:32", updated_at: "2016-01-13 04:56:22", state: "active", #<Task id: 3132, title: "1km Walk or Run by Sunday", content: "I pick a direction, start with a 10 minute warm up,...", created_at: "2016-01-13 04:56:05", updated_at: "2016-01-13 04:56:05", state: "active",#<Task id: 3249, title: "1km Walk or Run by Wednesday", content: "I pick a direction, start with a 10 minute warm up,...", created_at: "2016-01-24 23:23:34", updated_at: "2016-01-24 23:23:34", state: "active"]>
#array = []
#tasks.each do |task|
if (condition)
#array << task.id
end
#tasks = #tasks.where.not('tasks.id in (?)',#array)
If I get any non empty value in #array, the above condition is working fine. If I get #array = [] i,e empty array,
#tasks = #tasks.where.not('tasks.id in (?)',#array) is not giving me correct result.
Also, #tasks = #tasks.where('tasks.id in (?)',#array), this condition by removing 'not' giving the same result when not is present when the array is []
#habits = #habits.where.not('habits.id in (?)',#id_s) ====> output => []
#habits = #habits.where('habits.id in (?)',#id_s) ====> output => []
They both are returning same optput if #id_s is []
Why these queries are returning the same value for two different conditions?
If your Rails version is up to date you should switch to the hash notation, which handles all special cases like empty arrays for you:
#tasks = #tasks.where.not(id: #array)

Unexpected behaviour of array.count in ruby

Hi i am using Rails3 when i puts array of subscribers like this
#subscribers = User.all
and puts it.gives me this array
[#<User id: 62, is_activated: true, subscriber: "TEST_DB2", ports_order: 100, created_at: "2012-05-21 14:47:48">, #<User id: 66, is_activated: true, subscriber: "JOHI", ports_order: 100, created_at: "2012-05-22 12:06:19">, #<User id: 68, is_activated: true, subscriber: "ALI-NAQWI", ports_order: 100, created_at: "2012-05-24 11:01:22">]
And when i give command
#subscribers.count #it give me 0 count
Why?????????
Try length instead, it can be a bug in AREL :)
That he is trying to lazy do something. He is giving back proxy object so it can be a problem there. Length will always work on your result value ~ array.

Rails 3: use contents of an array as variables in a where method

I have three models: Isbn, Sale and Channel.
Aim: to get a list in the isbns show.html.erb view which looks something like this:
Isbn: myisbn
Total sales for myisbn: 100
Myisbn sales for channel 1: 50
Myisbn sales for channel 2: 25
Myisbn sales for channel 3: 25
Here are my models.
Isbn.rb model
has_many :sales
has_many :channels, :through => :sales
Sale.rb model (has attributes sales_channel_id, isbn_id, quantity)
has_many :channels
belongs_to :isbn
Channel.rb model:
belongs_to :sale
I've been working in the isbns controller, in the show method, just to get something to work. I thought I'd refactor later - advice on whether any of this stuff should go in the model would be most welcome.
So far I've got this:
#channelisbn = Sale.where("sales_channel_id =?',1).where("isbn_id=?",3)
#channelsalesisbn = 0
#channelisbn.each {|y| #channelsalesisbn =+ y.quantity}
This successfully gets all the sales where Channel ID is 1 and ISBN id is 3. But it's not much use, as the IDs are hard coded. So I got the Channel IDs into an array:
#channellist = Channel.all
#channel = 0
#channelarray = #channellist.map {|z| #channel = z.id}
which gives me a lovely array of [1,2,3,4]
But I can't figure out how to pass the 1, then the 2, then the 3 and then the 4 into a block which can be used to look up an ISBN's sales which have that sales channel id. This is what I tried (still hardcoding the ISBN id - thought I'd tackle one problem at a time), which returned an empty array:
#channelarray.each do |channel|
#channelisbn = []
#channelisbn = Sale.where("sales_channel_id = ?", channel).where("isbn_id = ?",3)
#channelsalesisbn = 0
#result = []
#result << #channelisbn.each {|a| #channelsalesisbn =+ a.quantity}
end
I was then going to sum the contents of the array.
Any help would be gratefully received. This is my first post, so my zero acceptance rate will change soon!
UPDATE
Just to finish this question off, here's where I've ended up, which is great, and ready for tinkering with: an array, nicely grouped, giving me sales by isbn by channel. Thanks for the group_by tip off!
#in the show action in the isbns controller:
#isbn = Isbn.find(params[:id])
#channelarray = Channel.select(:id).all
#channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", #isbn)}
From the console, line breaks added for clarity:
(sneakily set #isbn = 3 first of all, since in the console you can't pass params from a view, so the #isbn instance defined in the controller is nil in the console)
ruby-1.9.2-p180 :067 > #channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", #isbn)}
=> {[#<Sale id: 1, isbn_id: 3, quantity: 10000, value: 12000, currency: "GBP", total_quantity: nil, created_at: "2011-05-06 12:30:35", updated_at: "2011-05-07 17:43:13", customer: "Waterstone's", retail_price: nil, discount: nil, invoice_date: "2011-05-24">, #<Sale id: 2, isbn_id: 3, quantity: 1000, value: 500, currency: "GBP", total_quantity: nil, created_at: "2011-05-07 09:37:53", updated_at: "2011-05-07 19:14:52", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-02-05">]=>[#<Channel id: 1>],
[#<Sale id: 3, isbn_id: 3, quantity: 500, value: 1500, currency: "", total_quantity: nil, created_at: "2011-05-07 09:38:11", updated_at: "2011-05-07 19:15:07", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-12-05">, #<Sale id: 4, isbn_id: 3, quantity: 45, value: 300, currency: "", total_quantity: nil, created_at: "2011-05-07 09:38:38", updated_at: "2011-05-07 19:15:36", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-06-05">]=>[#<Channel id: 2>],
[]=>[#<Channel id: 3>],
[]=>[#<Channel id: 4>]}
UPDATE 2
Ha, the hash I generated had the key value pairs the wrong way round. The array containing the sales data was the key - it should have been the value. Rubydocs saved the day:
#salesbychannel = #salesbychannelwrong.invert
The invert method switches the key-value pairs. Sweet.
What you're looking for is passing an array to a ARel#where(), like this:
Sale.where(:sales_channel_id => #channelarray)
This should execute an IN query. If that's not working, you can always pass the array to ActiveRecord#find, like this:
Sale.find(#channelarray)
Hope this helps

Resources