2012-10-06 29 views
17

Tengo un controlador RESTful estándar que usa parámetros potentes.CanCan load_and_authorize_resource triggers Forbidden Attributes

class UsersController < ApplicationController 
    respond_to :html, :js 

    def index 
    @users = User.all 
    end 

    def show 
    @user = User.find(params[:id]) 
    end 

    def new 
    @user = User.new 
    end 

    def edit 
    @user = User.find(params[:id]) 
    end 

    def create 
    @user = User.new(safe_params) 

    if @user.save 
     redirect_to @user, notice: t('users.controller.create.success') 
    else 
     render :new 
    end 
    end 

    def update 
    @user = User.find(params[:id]) 

    if @user.update_attributes(safe_params) 
     redirect_to @user, notice: t('users.controller.update.success') 
    else 
     render :edit 
    end 
    end 

    def destroy 
    @user = User.find(params[:id]) 

    if current_user != @user 
     @user.destroy 
    else 
     flash[:error] = t('users.controller.destroy.prevent_self_destroy') 
    end 
    redirect_to users_url 
    end 

    private 

    def safe_params 
    safe_attributes = 
     [ 
     :first_name, 
     :last_name, 
     :email, 
     :password, 
     :password_confirmation, 
     ] 
    if current_user.is?(:admin) 
     safe_attributes += [:role_ids] 
    end 
    params.require(:user).permit(*safe_attributes) 
    end 
end 

En mi config/initializers tengo el archivo strong_parameters.rb

ActiveRecord::Base.send(:include, ActiveModel::ForbiddenAttributesProtection) 

Cuando agrego una simple llamada a load_and_authorize_resource de CanCan consigo

1) UsersController POST create with invalid params re-renders the 'new' template 
Failure/Error: post :create, user: @attr 
ActiveModel::ForbiddenAttributes: 
    ActiveModel::ForbiddenAttributes 
# ./spec/controllers/users_controller_spec.rb:128:in `block (4 levels) in <top (required)>' 

Dónde @attr en la prueba se define como

before(:each) do 
    @attr = 
     { 
     first_name: "John", 
     last_name: "Doe", 
     email: "[email protected]", 
     password: "foobar", 
     password_confirmation: "foobar" 
     } 
    end 

En las pruebas lo tengo todo configurado correctamente para iniciar sesión en el usuario y darles los roles necesarios para ser administrador, así que sé que no es eso. No sé por qué esto está provocando la activación de ForbiddenAttributes. Estoy seguro de que es algo simple que he pasado por alto. ¿Alguien más ha encontrado este problema y ha encontrado una solución?

Respuesta

19

Creo que esto se debe a que CanCan utilizará su propio método getter para el recurso solicitado si no lo precarga con un before_filter. Por lo que podría añadir este al controlador y debería funcionar:

class UsersController < ApplicationController 
    before_filter :new_user, :only => [:new, :create] 

    load_and_authorize_resource 

    def new_user 
    @user = User.new(safe_params) 
    end 
end 

(Y luego hacer lo mismo para las acciones de edición/actualización.)

+0

Creo que estoy teniendo el mismo problema. ¿Te importaría clarificar tu solución más? –

+6

Ha pasado un tiempo, pero lo intentaré;) ¿Qué parte te está causando problemas? Básicamente, si llama a 'load_and_authorize_resource' de cancan, intentará cargar el recurso más" lógico "dado el nombre del controlador, que precede a la operación de la gema de los parámetros fuertes. En este caso, intentará compilar el usuario, '@user = User.new (params [: user])' Pero los strong_parameters no permitirán la asignación masiva de esta manera. Si usa un 'before_filter' para establecer la variable de instancia @user, CanCan simplemente usará eso en su lugar. Si su 'before_filter' cumple con strong_parameters, no debería generar un error. –

+0

Ahhh ¡Muy apreciado! No entendía cómo CanCan estaba "... [usando] su propio método getter ..." pero eso tiene mucho sentido ahora. ¡Gracias de nuevo! –

7
before_filter do 
    params[:user] = safe_params 
end 
load_and_authorize_resource 
+1

Mayor énfasis aquí en el ** before_filter ** antes de ** load_and_authorize_resource ** – Ger