Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: How do I filter a ActiveRecord collection result without making new db queries?

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).

like image 637
Nein Avatar asked Mar 02 '17 19:03

Nein


People also ask

How do you get rid of N 1?

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).

What is ActiveRecord relation?

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.

What does where return rails?

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.


1 Answers

If you want to filter later - just treat relation as array. For example, filter with select:

today_candles.select { |x| x.type == 'AAA' }
like image 129
Igor Pavlov Avatar answered Oct 24 '22 03:10

Igor Pavlov