Avec la récente mise à niveau vers Rails 4, la mise à jour des attributs à l'aide de code ressemblant au ci-dessous ne fonctionne pas, j'obtiens un ActiveModel::ForbiddenAttributes
Erreur:
@user.update_attributes(params[:user], :as => :admin)
Où l'utilisateur a la ligne attr_accessible suivante dans le modèle:
attr_accessible :role_ids, :as =>admin
# or any attribute other than :role_ids contained within :user
Comment accomplissez-vous la même tâche dans Rails 4?
Rails 4 possède désormais des fonctionnalités de la gemme strong_parameters intégrée par défaut.
Il n'est plus nécessaire d'appeler :as => :admin
, vous n'avez pas non plus besoin du attr_accessible :user_attribute, :as => admin
dans votre modèle. La raison en est que, par défaut, les applications Rails ont désormais la "sécurité" pour chaque attribut sur les modèles. Vous devez permit
l'attribut auquel vous souhaitez accéder/modifier.
Il ne vous reste plus qu'à appeler permit
pendant update_attributes
:
@user.update_attributes(params[:user], permit[:user_attribute])
ou, pour être plus précis:
@user.update_attributes(params[:user].permit(:role_ids))
Cette seule ligne, cependant, permet à tout utilisateur de modifier le rôle permit
ted. Vous devez vous rappeler de n'autoriser l'accès à cette action que par un administrateur ou tout autre rôle souhaité via un autre filtre tel que le suivant:
authorize! :update, @user, :message => 'Not authorized as an administrator.'
. . . ce qui fonctionnerait si vous utilisez Devise et CanCan pour l'authentification et l'autorisation.
Si vous créez un nouveau site Rails 4, vous remarquerez que les contrôleurs générés incluent désormais une méthode privée que vous utilisez pour recevoir vos paramètres nettoyés. Ceci est un idiome agréable et ressemble à ceci:
private
def user_params
params.require(:user).permit(:username, :email, :password)
end
L'ancienne façon d'autoriser l'attribution de masse consistait à utiliser quelque chose comme:
attr_accessible :username, :email, :password
sur votre modèle pour marquer certains paramètres comme accessibles.
Pour mettre à niveau, vous avez plusieurs options. Votre meilleure solution serait de refactoriser vos contrôleurs avec une méthode params. Cela pourrait être plus de travail que vous n'en avez pour l'instant.
L'alternative serait d'utiliser la gemme protected_attributes qui rétablit la méthode attr_accessible. Cela permet un chemin de mise à niveau légèrement plus fluide avec une mise en garde majeure.
Dans Rails 3 tout modèle sans appel attr_accessible autorise cependant tous les attributs.
Dans Rails 4 avec la gemme protected_attributes, ce comportement est inversé. Tout modèle sans appel attr_accessible a tous les attributs restreints. Vous devez maintenant déclarer attr_accessible sur tous vos modèles. Cela signifie, si vous ne l'avez pas en utilisant attr_accessible, vous devrez l'ajouter à tous vos modèles, ce qui peut être autant de travail que de simplement créer une méthode params.
Ce problème peut également être causé par le bijou Cancan
Ajoutez simplement à application_controller.rb
before_filter do
resource = controller_name.singularize.to_sym
method = "#{resource}_params"
params[resource] &&= send(method) if respond_to?(method, true)
end
Fonctionne sans aucune modification de code supplémentaire ici: https://github.com/ryanb/cancan/issues/835#issuecomment-18663815
N'oubliez pas d'ajouter votre nouvelle méthode user_params à l'action du contrôleur:
def create
@user = User.new(user_params)
@user.save
redirect_to 'wherever'
end