ActiveRecord model.update_column with subquery
Asked Answered
B

0

0

I want to update a column in a Supply model that updates with its stock based on a sum of a subset. The thing is that actually hits two queries to make it works.

total_stock = History.sum(:quantity) # first query
Supply.update_columns(stock: total_stock) # second query

Then, I tried to write a subquery so:

total_stock_subquery = mysubset.select(Arel.sql('SUM(quantity)')).to_sql
Supply.update_columns(stock: total_stock_subquery) # it should be only one query

But, ActiveRecord will replace the total_stock_subquery variable as a string inside the resulting sql statement, then query fails.

I tried to wrap the total_stock_subquery parameter inside an Arel.sql thinking that ActiveRecord will detect that the parameter is not a string, but Arel.sql, and would escape this as raw sql, but it didnt work.

Supply.update_columns(stock: Arel.sql(total_stock_subquery)) # dont work too

Then, do you know how can I pass an sql subquery as parameter for a column inside .update_column, o maybe how to tell ActiveRecord that some parameter should be treated as pure sql not as string?

I know I could write this update as raw sql but I think it would be off Rails style.

EDIT: Table definitions

History

  • id: integer
  • supply_id: reference
  • quantity: decimal(9,2)

Supply

  • id: integer
  • product: string
  • stock: decimal(9,2)

class History belongs_to: supply end

class Supply has_many: histories end

We use the History model to track in and out (positive for in, negative for out) of supplies, then the sum of the histories will be the current stock.

Of course I can implement an after_save on History model to update the stock when some quantity changes it, but for this example, Im implementing a "rebase" or "recalculate" method for all supplies stock, then I need to make the sum for each Supply.

Beitz answered 9/5, 2020 at 21:4 Comment(4)
are both queries done to the same model to different models ?Erotogenic
can we know how the tables look like ?Erotogenic
the first query, the SUM, is maked to one model, and the second, the UPDATE, to anotherBeitz
I added the models definitionsBeitz

© 2022 - 2024 — McMap. All rights reserved.