2012-10-06 9 views
17

Ich habe einen standardmäßigen RESTful-Controller, der starke Parameter verwendet.CanCan load_and_authorize_resource löst verbotene Attribute aus

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 

In meinem config/initializers habe ich die Datei strong_parameters.rb

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

Wenn ich einen einfachen Aufruf zu CanCan der load_and_authorize_resource Gelangen ich

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

Wo @attr im Test als

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

In den Tests habe ich alles richtig eingerichtet, um den Benutzer einzuloggen und ihnen die notwendigen Rollen zu geben, um ein Administrator zu sein, also weiß ich, dass es das nicht ist. Ich weiß nicht, warum ForbiddenAttributes ausgelöst wird. Ich bin sicher, es ist etwas Einfaches, das ich übersehen habe. Ist jemand anderes auf dieses Problem gestoßen und hat eine Lösung gefunden?

Antwort

19

Ich glaube, das ist, weil CanCan seine eigene Getter-Methode für die angeforderte Ressource verwenden wird, wenn Sie es nicht mit einem before_filter laden. So könnte man dies an den Controller hinzufügen und es sollte funktionieren:

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

    load_and_authorize_resource 

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

(Und dann tut das gleiche für die Edit/Update Aktionen.)

+0

Ich glaube, ich das gleiche Problem habe. Würde es Ihnen etwas ausmachen, Ihre Lösung weiter zu klären? –

+6

Es ist eine Weile her, aber ich werde es versuchen;) Welche Rolle gibt dir Ärger? Wenn Sie cancans 'load_and_authorize_resource' aufrufen, wird grundsätzlich versucht, die "logischste" Ressource zu laden, die dem Namen des Controllers vorangestellt ist, der der Operation des starken Parameters gem vorangeht. In diesem Fall wird versucht, den Benutzer zu erstellen, '@user = User.new (params [: user])' 'strong_parameters erlaubt jedoch keine Massenzuweisung auf diese Weise. Wenn Sie einen 'before_filter' verwenden, um die Instanzvariable @user zu setzen, verwendet CanCan stattdessen nur diesen. Wenn Ihr 'before_filter' strong_parameters erfüllt, sollte es keinen Fehler verursachen. –

+0

Ahhh Sehr geschätzt! Ich verstand nicht, wie CanCan "... seine eigene Getter-Methode verwendet hat", aber das macht jetzt sehr viel Sinn. Danke noch einmal! –

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

Hauptgewicht hier auf dem ** bevor_filter ** kommt vor ** load_and_authorize_resource ** – Ger

Verwandte Themen