Reputation: 143
I am grabbing a list of open buckets for a particular user with the following code.
@open_buckets = Buckets.order("buckets.id ASC").where(:user_id => @user.id)
There is also a concept of private buckets for the user. I only want the private buckets to be returned when the logged in user is the owner of the bucket. The private field is a boolean. Can I somehow change my query so all users get the public buckets and only the owners get their private buckets and public buckets?
The only thing I thought of was to check to see if the logged in user was the same as the user whose buckets are being requested and do a different query. Something like below.
if :session["user_id"] => :user_id
@open_buckets = Buckets.order("buckets.id ASC").where(:user_id => @user_id)
else
@open_buckets = Buckets.order("buckets.id ASC").where(:user_id => @user_id).where(:private => true)
Thanks
Upvotes: 0
Views: 321
Reputation: 33954
A named_scope
(or just scope
in Rails 3) can do it.
class Bucket
...
named_scope :visible_buckets_for, lambda {|user| { :conditions=>["private = 'f' OR (private = 't' and user_id = ?)", current_user.id], :order=>"buckets.id ASC" } }
Where 'current_user' is whatever method you have to retrieve the id
of the currently logged in user, and 't'
is a DB-specific representation of a true
value. Some DB's use "true", or any non-zero number.
Then you call it like:
> Bucket.visible_buckets_for(current_user)
=> [<#Bucket1>, <#Bucket2>, <#Bucket3> ... ]
...which is an array of Bucket
objects, sorted by id
.
You can pass any user to that named scope, in case you need to find this out for more than just the current user.
Upvotes: 0
Reputation: 8941
Well, although I disagree with using one view (or one list/partial, more specifically) to display two different types of information, here is a way you could do what you're looking for:
@buckets = Buckets.order("buckets.id ASC").where(:user_id => @user_id, :private => false)
@buckets += @buckets.where(:private => true) if current_user.id == user.id
You could also create some cool scopes to handle this semi-complex logic in the model, where it should be, and also utilize your associations more fully:
@user = User.find(params[:user_id])
@buckets = @user.buckets.public
@buckets += @user.buckets.private if @current_user == @user
respond_with @buckets = @buckets.order("buckets.id asc")
and the Buckets
model:
scope :public, where(:private => false)
scope :private, where(:private => true)
As a side note, model class names should always be singular. You have Buckets
in your example, so if that's not a typo then I recommend going back and changing it if it's practical to do so. It will cause confusion further down the line, especially for future developers of your application.
Upvotes: 2