Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructing a Rails ActiveRecord where clause

What's the best way to construct a where clause using Rails ActiveRecord? For instance, let's say I have a controller action that returns a list of blog posts:

def index
  @posts = Post.all
end

Now, let's say I want to be able to pass in a url parameter so that this controller action only returns posts by a specific author:

def index
  author_id = params[:author_id]

  if author_id.nil?
    @posts = Post.all
  else
    @posts = Post.where("author = ?", author_id)
  end
end

This doesn't feel very DRY to me. If I were to add ordering or pagination or worse yet, more optional URL query string params to filter by, this controller action would get very complicated.

like image 247
Kevin Pang Avatar asked Apr 28 '11 14:04

Kevin Pang


2 Answers

How about:

def index
  author_id = params[:author_id]

  @posts = Post.scoped

  @post = @post.where(:author_id => author_id) if author_id.present?

  @post = @post.where(:some_other_condition => some_other_value) if some_other_value.present?
end

Post.scoped is essentially a lazy loaded equivalent to Post.all (since Post.all returns an array immediately, while Post.scoped just returns a relation object). This query won't be executed until you actually try to iterate over it in the view (by calling .each).

like image 151
John Gibb Avatar answered Oct 08 '22 10:10

John Gibb


Mmmh, the best approach you want to use can be to spread this in 2 actions

def index
   @post = Post.all
end

def get
  @post = Post.where("author=?", params[:author_id])
end

IMHO it has more sense if you think about a RESTful API, index means to list all and get (or show) to fetch the requested one and show it!

like image 40
Paolo Perego Avatar answered Oct 08 '22 11:10

Paolo Perego