2012-10-06 5 views
17

ho un controller RESTful standard che utilizza parametri forti.load_and_authorize_resource CanCan innesca Attributi Forbidden

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 

Nel mio config/initializers ho il file strong_parameters.rb

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

Quando aggiungo una chiamata semplice per load_and_authorize_resource di CanCan ottengo

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)>' 

Dove @attr nel test è definito come

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

Nelle prove ho tutto impostato correttamente il login l'utente e dare loro i ruoli necessari per essere un amministratore quindi so che non è così. Non so perché questo causa l'attivazione di ForbiddenAttributes. Sono sicuro che sia qualcosa di semplice che ho trascurato. Qualcun altro ha riscontrato questo problema e trovato una soluzione?

risposta

19

Credo che questo sia perché CanCan utilizzerà il proprio metodo getter per la risorsa richiesta se non si pre-caricate con un before_filter. Così si potrebbe aggiungere questo al controller e dovrebbe funzionare:

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

    load_and_authorize_resource 

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

(E poi fare lo stesso per le azioni di modifica/aggiornamento.)

+0

Credo sto avendo lo stesso problema. Ti dispiacerebbe chiarire ulteriormente la tua soluzione? –

+6

È passato un po 'di tempo ma ci provo;) Quale parte ti dà problemi? Fondamentalmente se si chiama 'load_and_authorize_resource' di cancan si cercherà di caricare la risorsa più" logica "dato il nome del controller, che precede l'operazione dei parametri forti gem. In questo caso proverà a creare l'utente, '@user = User.new (params [: user])' Ma strong_parameters non consentirà l'assegnazione di massa in questo modo. Se si utilizza un 'before_filter' per impostare la variabile di istanza @user, CanCan lo userà invece. Se il tuo 'before_filter' è conforme a strong_parameters, non dovrebbe generare un errore. –

+0

Ahhh Molto apprezzato! Non capivo come CanCan fosse "... [usando] il suo metodo getter ..." ma ora ha molto senso. Grazie ancora! –

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

Importante enfasi qui sul ** before_filter ** che precede ** load_and_authorize_resource ** – Ger