Conditionally Chaining ActiveRecord Queries
Sometimes, ActiveRecord queries can get pretty complex, especially if you’re implementing a feature like search over a typical “index” page that also has pagination and the term itself is optional. Fortunately, ActiveRecord queries can be chained in a few ways to make this a little bit nicer.
The most common is like:
user = User.where(name: 'Nick Charlton').limit(1)
Which you’ll see often. But you can also do something like this, which works really well for more complex queries:
user = User.where(name: 'Nick Charlton')
user = user.where(email: 'nick@nickcharlton.net')
user #=> <User id: 1, name: 'Nick Charlton'>
The result isn’t evaluated until you use the resulting object and so the
queries will be combined for you. This is because it returns an
ActiveRecord::Relation
object, and not the fully evaluated query.
This can be a much cleaner solution to conditional filtering of records, like you might wish to do with a reasonably complex search interface:
articles = Article.where(published: true)
articles = articles.search('thing') if params[:term]
I’m following this pattern on a few projects where I’d previously branched on the parameters given, but this is pretty unwieldy and leads to you duplicating a bunch of code. This is much better.