Summing 5 objects after a where statement - ruby-on-rails

I have an active record of 5 objects as follows
#top_sold = Photo.where(photographer_id: #photog).order('qty_sold DESC').first(5)
I want to know the sum of qty_sold for all 5 photos
This isnt working
#top_sold.sum(:qty_sold)
Much thanks in adcance

.first returns Array, use limit instead (which returns ActiveRecord::Relation).
#top_sold = Photo.where(photographer_id: #photog).order('qty_sold DESC').limit(5)

for Array you can do
#top_sold.map(:qty_sold).inject(:+)

Have you tried appending sum to your query?
#top_sold = Photo.where(photographer_id: #photog)
.order('qty_sold DESC').first(5).sum('qty_old')
If you need the original result set, then #Nithin answer is what you want to do.

Related

Active record sum giving the wrong answer

Hi I'm working on a project and I have to get the sum of an attribute of a active record collection. So I used:
#total = #records.sum(:cost)
However this gives the wrong value, for example if I have:
#records.each{ |x| puts x.cost}
I get 118.80 and 108.00
but for #total I get 680.40, which obviously isn't the answer, however if I use:
#total = 0
#records.each{ |x| #total = #total + x.cost}
I get the right answer of 226.80
If anyone can help me understand what is going on here it would be greatly appreciated.
Be careful, as a record collection is an instance of ActiveRecord::Associations::CollectionProxy, not an Array. It means that if you call:
#object.collection.sum(:cost)
actually what gets called is this method: http://apidock.com/rails/v4.2.7/ActiveRecord/Calculations/sum
And it will call sum in the SQL database, so the result gets influenced by the parameters of the query, e.g. groups, joins, etc.
While if you want to use Array sum, as in here: http://apidock.com/rails/Enumerable/sum
You would have to make your object Array first, via to_a:
#object.collection.to_a.sum(&:cost)
try this:
pluck the values of attr cost into an array and aggregate their sum
#total = #records.pluck(:cost).sum

apply ordering on limit query of active record

I need to find 10 records first and then apply ordering on that.
Model.all.limit(10).order('cast(code as integer)')
result of above code is - first it applies order on model and then limit query. So, I get same codes in my listing for given model. But I want to apply limit query first and then order fetched result.
When you call .all on model, it executes the query on DB and returns all records, to apply limit you have to write it before .all - Model.limit(10).all, but after that you can't use SQL function to operate data. So to get first 10 records and apply order to it, try this:
records = Model.limit(10).all.sort_by{|o| o.code.to_i}
or
records = Model.first(10).sort_by{|o| o.code.to_i}
Try this:
Model.limit(10).sort{|p, q| q.cost <=> p.cost}
All you need to do is to remove the .all method:
Model.limit(10).order('cast(code as integer)')
If you want to get 10 random records and then sort them without getting all records from the database then you could use
Model.limit(10).order("RANDOM()")
This uses the PostgreSQL rand() function to randomise the records.
Now you have an array of 10 random records and you can use .sort_by as described by BitOfUniverse.

how to select all values from column a take them to new array?

i have a model Timer(id:integer, track:string, time_point:integer)
before this question i asked on stackoverflow about reorganizing my array with integer values to array with ranges and took a pretty nice answer(biggest thanks for steenslag):
array = [1,4,10,14,22]
array.unshift(-1)
ranges = array.each_cons(2).map{|a,b| a+1..b} #=>[0..1, 2..4, 5..10, 11..14, 15..22]
array.shift
now i want to apply this solution and create an integer array with all my time_points for next reorganizing. how could i get this array?
thanks for help
You can use #pluck method to get all the column values as an Array.
time_points = Time.pluck(:time_point)

Sort Array of AWS3 objects

I have a collection of aws objects. I would like to sort the objects according to last modified time. See the below snippet
array = [<AWS::S3::S3Object:dt_publisher_reports/temp/2013.csv>,
<AWS::S3::S3Object:dt_publisher_reports/temp/2013_October.csv>,
<AWS::S3::S3Object:dt_publisher_reports/temp/2013_September_176.csv>,
<AWS::S3::S3Object:dt_publisher_reports/temp/2013_September_1764.csv>
]
I need to sort the array with respect to last modified time of that particular file.
Try this
array = [<AWS::S3::S3Object:dt_publisher_reports/temp/2013.csv>,
<AWS::S3::S3Object:dt_publisher_reports/temp/2013_October.csv>,
<AWS::S3::S3Object:dt_publisher_reports/temp/2013_September_176.csv>,
<AWS::S3::S3Object:dt_publisher_reports/temp/2013_September_1764.csv>]
array.sort_by &:last_modified
Use this
array.sort_by &:updated_at
or
array.order(:updated_at)

Get specific column from a collection ActiveRecord objects?

How can I extract a list of IDs from a returned ActiveRecord results without re-querying the ID column alone?
For exmaple:
people = People.all
people.get_ids #Returns an array of IDS
My current solution is to loop through people and get the ID manually(which isn't very elegant, IMHO)
You can use pluck method:
e.g. People.pluck(:id)
Refer http://apidock.com/rails/ActiveRecord/Calculations/pluck
Fetching using pluck would be better compared to the process of fetching the same after taking all results.
Hope that helps..
You can use map method
all_ids = people.map(&:id) #[1,2,3,4]
ids = People.all.map(&:id)
This code will return array of ids

Resources