foobar
foobar

Reputation: 11374

Rails: How to buffer an ActiveRecord query?

I'd like to save a query, then build on top of it, then execute it.

For example, somehow

query = Post.order('likes DESC') # buffer the query
query = query.limit(3) # add on top of it
query.run # run it - this is the wrong syntax fyi

Can this be done? What's the right syntax?

PS. I'm not sure if "buffer" is the right word, please correct me if I'm wrong.

Thanks!

Upvotes: 3

Views: 1963

Answers (4)

Alex Gusev
Alex Gusev

Reputation: 491

You can use ActiveRecord::Relation#load method to force database hit:

https://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-load

Upvotes: 0

evilguc
evilguc

Reputation: 930

You don't need any "buffers" when building queries with ActiveRecord in Rails 3 because it uses Arel. Your query = Post.order('likes DESC') gives you instance of ActiveRecord::Relation. This object contains information about query, but not an actual data. To get data you can invoke .first or .all methods for example. It's way how rails framework (>= 3.0) implements so called "lazy initialization". It means that ActiveRecord::Relation is a kind of proxy. Real query to the database goes only when you're trying to get some fields of your model (or when you force load data with .all, .first, .last etc). Until this action you can build your chain of filtering conditions and be sure that you do not "disturb" database. Your code may be like this:

query = Post.order('likes DESC') # ActiveRecord::Relation object with info about your query
query = query.limit(3) # adds more filtering options
@posts = query.all # here ActiveRecord takes data from the database

#239 ActiveRecord::Relation Walkthrough will give you more understanding about ActiveRecord::Relation

Upvotes: 4

Zach Kemp
Zach Kemp

Reputation: 11904

That's exactly how ActiveRecord works. When it hits an iterator or some other non-AR method, it calls the database using the built-up query. It works a little different in the console, because I believe the .inspect method is called to display the output after you press return.

It's fine to do what you've proposed.

Upvotes: 2

Kevin Sylvestre
Kevin Sylvestre

Reputation: 38032

If you are using AREL and Rails 3 this happens automatically. AREL will built up a query as you chain options and execute the query when you call .all or start accessing data through any other means.

Upvotes: 3

Related Questions