Sum and Group Query doesn't group - ruby-on-rails

I need to filter records and then sum and group those records, in my controller I have done it like so:
def view
#templates = Template.where("user_id = #{current_user.id} OR user_id = 1").where("category = 5")
#user_docs = Doc.where("user_id = #{current_user.id}")
#transactions = Transaction.where("doc_id in (?)", #user_docs.map(&:id)).where("template_id in (?)", #templates.map(&:id))
#month = #transactions.select("DATE_TRUNC('month', date) AS month, SUM(amount) AS total_amount_per_month").group('month')
end
It gives an error with the month grouping and the amount is the total of all the months summed in my view, any idea why the above isn't working? What am I doing wrong?

The reason I got an error at the date was because the date was added later to my model with a migration and I didn't add it to attributes accessible. After that the error was fixed.

Related

Activerecord query where current employer is X and previous employer is Y

Basically I'd like to return all people whose current job title is X and whose previous job title is Y. As an example, I have a talent whose current emnployment is "Airbnb (company_id = 1)" and whose previous employment is at "Youtube (company_id = 2)".
If I run a query to find talent where current employment is Airbnb:
Talent.joins(:job_histories).where(["job_histories.company_id = ? and job_histories.end_year = ?", 1, "Present"])
I get the person.
If I run a query where previous employment is Youtube (hence the end_year != "Present" below)
Talent.joins(:job_histories).where(["job_histories.company_id = ? and job_histories.end_year != ?", 2, "Present"])
I also get the same person.
However, if I chain them together to find talents where current employer is Airbnb AND previous employer is Youtube, like this:
#talents = Talent.all
#talents = #talents.joins(:job_histories).where(["job_histories.company_id = ? and job_histories.end_year = ?", 1, "Present"])
#talents = #talents.joins(:job_histories).where(["job_histories.company_id = ? and job_histories.end_year != ?", 2, "Present"])
I do not get any results. I've tried several variations of the query but none return anything.
The only way I can get it to work is by using the first query and then looping over each talent to find where job_histories.company_id == 2.
if params[:advanced_current_company] && params[:advanced_previous_company]
#talents = #talents.joins(:job_histories).where(job_histories: { company_id: params[:advanced_current_company] }).distinct if params[:advanced_current_company]
#talents.each do |talent|
talent.job_histories.each do |job_history|
if job_history.company_id == params[:advanced_previous_company][0].to_i
new_talents.append(talent.id)
end
end
end
#talents = Talent.where(id: new_talents)
end
Any direction would be amazing. Thanks!
You had the right idea with a double join of the job_histories, but you need to alias the job_histories table names to be able to differentiate between them in the query, as otherwise activerecord will think it's only one join that needs to be done.
Talent.joins("INNER JOIN job_histories as jh1 ON jh1.talent_id = talents.id")
.joins("INNER JOIN job_histories as jh2 ON jh2.talent_id = talents.id")
.where("jh1.company_id = ? and jh1.end_year = ?", 1, "Present")
.where("jh2.company_id = ? and jh2.end_year != ?", 2, "Present")

Sum ActiveRecord Relationship (Model + Model = Array?)

I'm trying to sum two Active Model Relationship and order it by created_at.
The sum of dogs and cats make an Array. So I try to sort this array by created_at with .sort_by( &:created_at ) but I get this strange error:
dogs = current_user.dogs
cats = current_user.cats
total = (dogs + cats).sort_by( &:created_at )
comparison of ActiveSupport::TimeWithZone with nil failed
There is another best way to sum two active record relationship and order it by created_at ?
Thank you very much.
One of your results has a created_at of nil it seems like, which is why you're getting that error. You can do the following to filter nil results
dogs = current_user.dogs.where.not(created_at: nil)
cats = current_user.cats.where.not(created_at: nil)
sorted_results = (dogs + cats).sort_by(&:created_at)
If you want to see which record(s) have created_at as nil do
nil_created_at_dogs = current_user.dogs.where(created_at: nil)
nil_created_at_cats = current_user.cats.where(created_at: nil)
I solve the problem.
If use .where, all works properly.
dogs = Dog.where(user_id: current_user.id)
cats = Cat.where(user_id: current_user.id)
total = (dogs + cats).sort_by( &:created_at )
I don't know why, but this is the way.

Rails 5: iteration with condition to map matching records

I have this method in my rating/rating.rb Model, where I basically need to create array of arrays with matching inventory and rating IDs:
def inventory_ratings
inventory = Inventory::Inventory.where(id: inv).order(date: :desc)
rating = Rating::Rating.where(id: rtg).order(valid_from: :desc)
columns = [:inventory_id, :rating_id]
values = inventory.map {|inv|
if (inv.position_id == rating.position_id &&
rating.valid_from..rating.valid_to.include?(inv.date))
r = rating.id
end
[ inv.id, r ]
}
Rating::InventoryRating.import columns, values, validate: false
end
At the moment I get this error:
NoMethodError: undefined method "position_id" for #<Rating::Rating::ActiveRecord_Relation:0x007ffff6067bf8> since I probably have to somehow iterate through each rating to get position_id, valid_from and valid_to.
How do I add that extra iteration so each inventory record iterates through each rating record and maps if it matches IF statement, please? Thank you!
How about this:
values = []
inventory.each do |inv|
values.concat([inv.id].product(rating.where('position_id = ? AND valid_from <= ? AND valid_to >= ?', inv.position_id, inv.date, inv.date).ids))
end.uniq.compact

Rails Iteration by month given range of dates

I'm trying to follow this Railscast and create a morris.js line chart for my Enquiry model.
I've grouped the counts using date_trunc into months, but now I'm not quite sure at how to get the X-axis to iterate over months (e.g Jun 2012, Jul 2013) as opposed to by date as in the railscasts notes.
I've tried the range#step method here, but now the graph displays only one date (2012-07-01) without a count and nothing else. Commenting out the .step(1.month) method from the range variable and the graph works fine but the x-axis iterates by date.
class Enquiry < ActiveRecord::Base
def self.chart_data(start = 1.year.ago)
total_count = total_count_by_month(start)
start = start.to_date.beginning_of_month
today = Date.today.beginning_of_month
range = (start..today).step(1.month)
range.map do |month|
{
created_at: month,
total_enquiries: total_count[] || 0
}
end
end
def self.total_count_by_month(start)
enquiries = unscoped.where(created_at: start.beginning_of_month..Time.now)
enquiries = enquiries.group("date_trunc('month', created_at)")
enquiries = enquiries.select("date_trunc('month', created_at) as created_at, count(*) as count")
enquiries.each_with_object({}) do |enquiry, counts|
counts[enquiry.created_at.to_date] = enquiry.count
end
end
end
How do I get the chart's x-axis to iterate by months (Jun 2013, Jul 2013 ....) instead of by dates?
For anyone else facing the same problem, the solution is outlined below:
def self.chart_data(start = 1.year.ago)
total_count = total_count_by_month(start)
##############################################
start = start.to_date.beginning_of_month
today = Date.today.beginning_of_month
range = (start..today).select {|d| d.day == 1}
##############################################
range.map do |month|
{
created_at: month,
total_enquiries: total_count[] || 0
}
end
end
The chart's x-axis now iterates by month.
The solution is found here.
I'm still looking for solutions on how the chart dates might display (%b %Y) as opposed to the current format of (yyyy-mm-dd).

Best way to get resultset and calculation from activerecord grouped by total, page or date?

I have a model with date, hours and description and want to display this data in a table with paging. I want to sum up hours per date, page and total.
Is this possible with one query or do i have query for my result set, then query for total sum and sum up in view for page sum?
# controller
#result = Data.page(params[:page])
#total = Data.sum('hours')
# #total_page = Data.page(params[:page]).sum('hours')
# view
#total_page = 0
#total_date = 0
previous = nil
#result.each do |result|
....
if previous.date != result.date
#total_data = result.hours
else
#total_data += result.hours
end
....
#total_page += result.hours
end

Resources