Beaucoup de gens sur ce fil et sur Google expliquent très bien qui attr_accessible
spécifie une liste blanche d'attributs qui peuvent être mis à jour en masse ( tous les attributs d'un modèle d'objet ensemble en même temps ) C'est principalement (et seulement) pour protéger votre application de l'exploit pirate "Assignation de masse".
Ceci est expliqué ici sur le document officiel de Rails: Mass Assignment
attr_accessor
est un code rubis pour créer (rapidement) des méthodes setter et getter dans une classe. C'est tout.
Maintenant, ce qui manque comme explication est que lorsque vous créez en quelque sorte un lien entre un modèle (Rails) avec une table de base de données, vous n'avez JAMAIS, JAMAIS, JAMAIS besoin attr_accessor
dans votre modèle de créer des setters et des getters afin de pouvoir modifier votre enregistrements de la table.
En effet, votre modèle hérite de toutes les méthodes de la ActiveRecord::Base
classe, qui définit déjà pour vous les accesseurs CRUD de base (créer, lire, mettre à jour, supprimer). Ceci est expliqué dans la doc officielle ici Rails Model et ici Overwriting default accessor (faites défiler jusqu'au chapitre "Overwrite default accessor")
Disons par exemple que: nous avons une table de base de données appelée "utilisateurs" qui contient trois colonnes "prénom", "nom" et "rôle":
Instructions SQL:
CREATE TABLE users (
firstname string,
lastname string
role string
);
J'ai supposé que vous définissiez l'option config.active_record.whitelist_attributes = true
dans votre config / environment / production.rb pour protéger votre application contre l'exploit d'affectation de masse. Ceci est expliqué ici: Affectation en masse
Votre modèle Rails fonctionnera parfaitement avec le modèle ci-dessous:
class User < ActiveRecord::Base
end
Cependant, vous devrez mettre à jour chaque attribut d'utilisateur séparément dans votre contrôleur pour que la vue de votre formulaire fonctionne:
def update
@user = User.find_by_id(params[:id])
@user.firstname = params[:user][:firstname]
@user.lastname = params[:user][:lastname]
if @user.save
# Use of I18 internationalization t method for the flash message
flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
end
respond_with(@user)
end
Maintenant, pour vous faciliter la vie, vous ne voulez pas créer un contrôleur compliqué pour votre modèle utilisateur. Vous utiliserez donc la attr_accessible
méthode spéciale dans votre modèle de classe:
class User < ActiveRecord::Base
attr_accessible :firstname, :lastname
end
Vous pouvez donc utiliser la "route" (affectation de masse) pour mettre à jour:
def update
@user = User.find_by_id(params[:id])
if @user.update_attributes(params[:user])
# Use of I18 internationlization t method for the flash message
flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
end
respond_with(@user)
end
Vous n'avez pas ajouté les attributs "role" à la attr_accessible
liste car vous ne laissez pas vos utilisateurs définir leur rôle par eux-mêmes (comme admin). Vous le faites vous-même sur une autre vue d'administration spéciale.
Bien que votre vue utilisateur ne montre pas de champ "rôle", un pirate pourrait facilement envoyer une requête HTTP POST qui inclut "rôle" dans le hachage des paramètres. L'attribut "role" manquant sur le attr_accessible
est de protéger votre application contre cela.
Vous pouvez toujours modifier votre attribut user.role seul comme ci-dessous, mais pas avec tous les attributs ensemble.
@user.role = DEFAULT_ROLE
Pourquoi diable utiliseriez-vous le attr_accessor
?
Eh bien, ce serait dans le cas où votre formulaire utilisateur affiche un champ qui n'existe pas dans votre table d'utilisateurs sous forme de colonne.
Par exemple, supposons que votre vue utilisateur affiche un champ "veuillez-dire-à-l'administrateur-que-je-suis-ici". Vous ne voulez pas stocker ces informations dans votre table. Vous voulez juste que Rails vous envoie un e-mail vous avertissant qu'un utilisateur "fou" ;-) s'est abonné.
Pour pouvoir utiliser ces informations, vous devez les stocker temporairement quelque part. Quoi de plus simple que de le récupérer dans un user.peekaboo
attribut?
Vous ajoutez donc ce champ à votre modèle:
class User < ActiveRecord::Base
attr_accessible :firstname, :lastname
attr_accessor :peekaboo
end
Vous pourrez donc faire un usage éclairé de l' user.peekaboo
attribut quelque part dans votre contrôleur pour envoyer un e-mail ou faire ce que vous voulez.
ActiveRecord n'enregistrera pas l'attribut "peekaboo" dans votre table lorsque vous effectuez un, user.save
car elle ne voit aucune colonne correspondant à ce nom dans son modèle.
attr_accessor
est utilisé pour générer des méthodes getter et setter. Veuillez voir ma réponse à une question précédente pour une explication assez complète deattr_accessible
: stackoverflow.com/questions/2652907/… puis mettez à jour votre question si vous avez besoin d'autres détails spécifiques après cela.