Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails ActiveRecord: building queries dynamically

I'm trying to put together a series of classes that can use ActiveRecord to create and execute complex queries dynamically. I feel very comfortable with the whole practice of doing:

MyModel.select("id, name, floober").join(:creator).where(:is_active => true)

What I'm struggling with is using these things to build up a query w/o being able to determine how many there will be of each possible method (number of joins, number or where clauses, limit, group, etc) ahead of time. I might have 2 joins, or no joins depending upon where it's called from.

Due to the nature of how I'm getting these things--a list of joins, a list of columns, a list of where clauses, etc--I can blindly chain them together. I have to join the columns together, arrange the joins, chain the where clauses, so I can't loop through the various lists.

I'm trying to avoid writing any raw SQL.

One thing I tried was building up the ruby statement as a string then evaling it at the end, and when I got done I felt dirty like I needed a bath. What I'm looking for is a way to cache the state of my query until all the parts have been accumulated, then execute them.

Have I wandered "off the Rails"?

thanks in advance...

like image 733
jaydel Avatar asked May 21 '11 22:05

jaydel


1 Answers

I think I figured it out. I was fairly off base on my understanding of the AR query methods. It turns out that ActiveRecord doesn't actually execute the query until you actually try to use the results. As a result it's possible to do things like:

model_query = MyModel.select("column12, column32")
model_query = model_query.joins(:user)
model_query = model_query.where(:column12 => true)

then after everything is built up you can do

model_query.each do |record|
  ...
end

The query isn't actually executed until you call each (or whatever method you use that demands the results of the query).

I got this by watching Railscasts 202 and 215. I love Ryan Bates.

like image 138
jaydel Avatar answered Oct 15 '22 21:10

jaydel