Say I have a Candle
model with 'today
' scope. The scope runs a few heavy conditions and gives me around 5k rows as the result.
today_candles = Candle.today
I want to later filter this collection with a column value. For eg:
aaa_candles = today_candles.where(type: 'AAA')
bbb_candles = today_candles.where(type: 'BBB')
...
But each of this filter is making a new db request as follows:
Candle.today.where(type: 'AAA')
Candle.today.where(type: 'BBB')
...
Is there a way to filter on the initial collection today_candles
data without making new multiple db requests? It feels like a basic functionality but I cannot find it.
I am currently storing the collection as an array and then looping through them to filter and avoid multiple db calls. But this feels stupid.
Please note: I'm not sure if Rails does cache the AR collection and filter them without new db_queries in a production environment. I'm currently on webrick (development).
You can avoid most n+1 queries in rails by simply eager loading associations. Eager loading allows you to load all of your associations (parent and children) once instead of n+1 times (which often happens with lazy loading, rails' default).
Whereas an instance of ActiveRecord::Relation is a representation of a query that can be run against your database (but wasn't run yet). Once you run that query by calling to_a , each , first etc. on that Relation a single instance or an array of ActiveRecord::Base instances will be returned.
where returns an ActiveRecord::Relation (not an array, even though it behaves much like one), which is a collection of model objects. If nothing matches the conditions, it simply returns an empty relation. find (and its related dynamic find_by_columnname methods) returns a single model object.
If you want to filter later - just treat relation as array. For example, filter with select:
today_candles.select { |x| x.type == 'AAA' }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With