2011-11-18 8 views
16

Estoy utilizando Rails 3 con Devise para autenticación de usuario. Supongamos que tengo un modelo de Usuario, con Devise habilitado y un modelo de Producto, y que un Usuario tiene muchos productos.Búsqueda de alcance de rieles con el usuario actual

En mi controlador de Productos, me gustaría que mi método de búsqueda sea examinado por current_user, es decir.

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

a menos que el usuario es un usuario administrador, es decir current_user.admin?

En este momento, estoy corriendo ese código en casi todos los métodos, que parece desordenado:

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

¿Hay una manera más elegante/estándar de hacer esto?

Respuesta

5

Si ejecuta este código en una gran cantidad de los controladores, es probable que debe hacer un filtro antes, y definir un método de hacerlo en su 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 

No sé lo que utiliza para determinar si un usuario es administrador o no (roles), pero si mira en CanCan, tiene un alcance accessible_by que acepta una capacidad (un objeto que controla lo que los usuarios pueden y no pueden hacer) y devuelve registros ese usuario tiene acceso según los permisos que usted mismo escribe. Probablemente eso sea lo que realmente quiere, pero arrancar su sistema de permisos y reemplazarlo puede ser factible o no.

2

Puede agregar un método de clase en Producto con el usuario enviado como argumento.

class Product < ActiveRecord::Base 
    ... 

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

Entonces se le puede llamar así:

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

PD: Probablemente hay una forma mejor de hacer el where({}).

+0

Product.scoped podría reemplazar el @klochner 1 = 1, excepto que – klochner

+0

solo funcionaría si es la primera llamada en la cadena: (funciona: 'Product.for_user (...)', does not: 'Product.enabled.for_user (...)') – mbillard

+0

mbillard - no es cierto, intentalo – klochner

20

Me gustaría hacer esto de la siguiente manera:

class Product 

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

end 

esto le permite escribir lo siguiente en el controlador:

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