Rails scope find with current user

15,820

Solution 1

If you're running this code in a lot of your controllers, you should probably make it a before filter, and define a method to do that in your ApplicationController:

before_filter :set_product, :except => [:destroy, :index]

def set_product
  @product = current_user.admin? ? Product.find(params[:id]) : current_user.products.find(params[:id]) 
end

I don't know what you use to determine if a user is an admin or not (roles), but if you look into CanCan, it has an accessible_by scope that accepts an ability (an object that controls what users can and can't do) and returns records that user has access to based on permissions you write yourself. That is probably really what you want, but ripping out your permissions system and replacing it may or may not be feasible for you.

Solution 2

I like to do this as follows:

class Product

  scope :by_user, lambda { |user|
    where(:owner_id => user.id) unless user.admin?
  }

end

this allows you to write the following in your controller:

Product.by_user(current_user).find(params[:id])

Solution 3

You could add a class method on Product with the user sent as an argument.

class Product < ActiveRecord::Base
  ...

  def self.for_user(user)
    user.admin? ? where({}) : where(:owner_id => user.id)
  end

Then you can call it like this:

Product.for_user(current_user).find(params[:id])

PS: There's probably a better way to do the where({}).

Share:
15,820

Related videos on Youtube

ideaoforder
Author by

ideaoforder

Sitesteaders Development :: custom web application development Schmolio :: artist website/portfolio management :: http://schmolio.com Whiplash Merchandising :: merchandising logistics :: http://www.whiplashmerch.com VGKids :: High Quality Screen Printing :: http://www.vgkids.com

Updated on June 04, 2022

Comments

  • ideaoforder
    ideaoforder almost 2 years

    I'm using Rails 3 with Devise for user auth. Let's say I have a User model, with Devise enabled, and a Product model, and that a User has_many Products.

    In my Products controller I'd like my find method to be scoped by current_user, ie.

    @product = current_user.products.find(params[:id])

    unless the user is an admin user, i.e. current_user.admin?

    Right now, I'm running that code in almost every method, which seems messy:

    if current_user.admin?
      @product = Product.find(params[:id])
    else
      @product = current_user.products.find(params[:id])
    end
    

    Is there a more elegant/standard way of doing this?

  • klochner
    klochner almost 11 years
    Product.scoped could replace the 1=1
  • mbillard
    mbillard almost 11 years
    @klochner except that it would only work if it's the first call in the chain: (works: Product.for_user(...), doesn't: Product.enabled.for_user(...))
  • klochner
    klochner almost 11 years
    mbillard - not true, try it