Rails sum all prices inside a record - ruby-on-rails

I have a model Products that belongs_to model Kit
Kit has_many Products
¿How can I sum all of the prices of each product that belongs to a kit?
I tried with no luck:
#kitprice = Kit.products.price.sum

Try this:
#kitprice = kit.products.sum(:price)
In my case i have wallet with many operations
wallet = Wallet.first
amount = wallet.operations.sum(:amount)

Question is slightly ambiguous. Assuming you have an instance of Kit named as kit, and a kit has many product objects; following would get you the desired result.
sum = 0
kit_id = <enter kit id here>
kit = Kit.find_by_id(kit_id)
# iterate through every product object and compound price here
kit.products.each{|product| sum = sum + product.price}
puts sum
Basically you need to iterate through every product object and compute the sum, since it's a has many relationship.

This will give you every kit with the sum of it's products, i assume there is a column named name in your kit model
#kit_products_price = Kit.includes(:products).group(:name).sum('products.price')
If you want the sum of all the kit products :
#kit_price = Kit.includes(:products).sum('products.price')

The following should work I believe:
Active Record collection
#total = kit.products.sum("price")
Ruby array
#total = kit.products.sum(&:price)

Related

Rails match 2 arrays

I have 2 models Donation and BankDeposit
Donation has a column sender_id
Bank Deposit has a column donated_by_id
So let say I have:
#donations = Donation.all
#bank_deposits = BankDeposit.all
and these 2 arrays return this values for mentioned columns:
#donations.sender_id = [1,3,6,8,9]
#bank_deposits.donated_by_id = [2,3,7,8]
In this example, assuming ids of donations are 1 to 5, result I want to achieve is selecting rows with id 2 and 4 (as they contain 3 and 8 present on bank_deposits.donated_by_id).
How should I implement the code to achieve this?
If you ONLY need the donations you can change the code and try:
#donations = Donation.where(sender_id: BankDeposit.pluck(:donated_by_id))
If you want to keep both and use all the records just filter using select:
bank_deposit_donated_by_ids = #bank_deposits.map(&:donated_by_id)
matched_donations = #donations.select do |elem|
bank_deposit_donated_by_ids.include?(elem.sender_id)
end
Didn't test the syntax/API, but that's the idea.
Try below code
#donations.sender_id & #bank_deposits.donated_by_id
This will give you output of common element id from the both array after that you can filter it in any sense you like.
Hope it will work for you.

Sort a resource based on the number of associated resources of other type

I have a Movie model that has many comments,
I simply want to sort them (Movies) using SQL Inside active record based on the number of associated comments per movie.
How can we achieve a behavior like this in the most efficient way.
I want to do this on the fly without a counter cache column
you can do something like this
#top_ten_movies = Comment.includes(:movie).group(:movie_id).count(:id).sort_by{|k, v| v}.reverse.first(10)
include(:movie) this to prevent n+1 in sql
group(:movie_id) = grouping based on movie for each comment
sort_by{|k,v|v} = this will result an array of array for example [[3,15],[0,10][2,7],...]
for first part [3,15] = meaning movie with id = 3, has 15 comments
you can access array #top_ten_movies[0] = first movie which has top comments
default is ascending, with reverse you will get descending comments

Ruby on Rails: Subquerying an array of found objects' relational objects?

I have a model Profile that has a onetoone with the model Interest. If I query an array of Profiles using where, how would I then get another separate array composed of the Interests associated with those originally queried Profiles?
Something like
#foundProfiles = Profile.where(field: data)
into
#foundInterests = #foundProfiles.Interest.all
this doesn't work, but that's the idea I'm trying to get at.
Make use of association:
#foundProfiles = Profile.includes(:interest).where(field: data)
# Eager load interest to avoid n + 1 queries
#foundInterests = #foundProfiles.map(&:interest)
EDIT
If you need to query further on the Interest records you can do something like:
#foundInterests = Interest.where(profile_id: #foundProfiles.map(&:id))
This will return you Interest records associated with #foundProfiles and you can chain where on it

TypeError: no implicit conversion of Array into Integer Rails 4.2

I am building a shopping cart app in rails. CartItems model has a column for quantity of the type integer and a column for cart_price of the type decimal. For each item added to the cart a new row is added to the database
Model name CartItems. The controller retrieves quantity and price successfully. But when multiplying I receive the error message above. Once the multiplication works I want to add the products together to get the subtotal for the cart.
def subtotal
#cart_content = #cart_item.pluck(:quantity,:cart_price)
#subtotal = #cart_content.inject(:*)
end
When I remove .inject(:*) from #subtotal the controller retrieves the correct data.
Example output from view for two products, with quantity and price value present
[[3, #BigDecimal:7fc9a9b2d980,'0.1285E3',18(36)>], [1, # BigDecimal:7fc9a9b2d7c8,'0.115E3',9(27)>]]
I'm not 100% sure but what you probably wanted to achieve is:
#cart_content.sum { |c| c.inject(:*) } - single reduce won't work because it expects a number not an array
You are probably better of adding a column to the model that already contains the value of quantity * cart_price # name it row_total
Then you can easily sum the new column like this:
ModelName.sum(:row_total)
You seem to be trying to multiplying the individual elements, which ruby does not like as they are arrays themselves.
As djaszczurowski suggested, I'd recommend summing over the array after multiplying the elements.
Extending on his answer, I'd suggest to replace the inject with the following, as in (at least for me) it is more descriptive of what (I think) you want to do with the code:
#subtotal = #cart_content.sum { |count, price| count * price }

getting records from 2 tables and merge them by date

Lets say I have 2 tables in my database, both have 'updated_at' field.
I want to retrieve all the records in both tables in one active record query.
I should return one large activerecord relation ordered by updated_at field.
Let assume these two tables are really similar.
If it is possible, it would be better to have the ability to only return the first 50, or second 50, or so on.
here's an example
cats = Cat.all
dog = Dog.all
animals = (cats | dogs).sort!{|a,b| a.updated_at <=> b.updated_at}.limit(50)
It is pretty costly to get all dogs then cats then merge them into one, and then get the first 50 animals.
I need a way to make one query to db and the db returns the first 50 animals.
or the second 50 animals.
Given that these models are so similar, wouldn't be better to use ActiveRecord's Single table inheritance? For the example you provided, you would have base class Animal, and you would get the results you want with just Animal.order("updated_at").limit(50)
It's not a single query, but an obvious optimization would be to only grab the first 50 of each instead of the whole tables:
cats = Cat.order_by(:updated_at).limit(50)
dogs = Dog.order_by(:updated_at).limit(50)
animals = (cats + dogs).sort_by(&:updated_at).first(50)
You could then get the next 50 by querying on the last updated_at
last_animal_date = animals.last.updated_a
next_cats = Cat.where("updated_at > ?", last_date).order_by(:updated_at).limit(50)
next_dogs = Dog.where("updated_at > ?", last_date).order_by(:updated_at).limit(50)
# etc ...
Clearly with the amount of repetition this needs to be factored into a method but I leave that as an exercise to the reader :)

Resources