There is an efficient way: make sure you only run one query, and that the query you run returns exactly the objects you want. Easier said than done, of course.
One way to handle this is to construct your conditions using scopes.
@posts = @thread.posts.not_deleted.this_week.not_secret
If all those methods are scopes, that will be only one query.
If your conditions are too complex to easily make them scopes, you should probably just write a method to return the visible objects for the user.
class User
def posts_for(thread)
if is_admin?
thread.posts
elsif thread.owner == self
thread.posts.not_deleted
else
Post.find(:all, :conditions => something_complicated(thread, self))
end
end
end
My application has a lot of kinds of objects, and very complicated permissions, so we capture calls like that with method_missing, and route them to a permission library that knows how to make all the various queries.