J'ai installé l'exemple d'application RailsTutorial (l'application similaire à Twitter) et j'essaie de comprendre pourquoi le code de console suivant ne met pas à jour la base de données lorsque j'essaie de mettre à jour la base de données de l'utilisateur. Je m'attends à ce que les informations utilisateur soient mises à jour une fois que j'utilise le user.save
. Cependant, cela revient aux données non éditées. Est-ce dû à une restriction basée sur l'utilisateur?
Contrôleur d'utilisateurs:
class UsersController < ApplicationController
#before_filter :signed_in_user, only: [:index, :edit, :update, :destroy, :following, :followers]
# By default before filters apply to all actions
#before_filter :correct_user, only: [:edit, :update]
def edit
@user = User.find(params[:id])
end
def update
@user = User.find params[:id]
respond_to do |format|
if @user.update_attributes(params[:user])
flash[:notice] = "Profile updated"
format.html { redirect_to(@user, :notice => 'User was successfully updated.') }
format.json { respond_with_bip(@user) }
else
format.html { render :action => "edit" }
format.json { respond_with_bip(@user) }
end
end
end
private
def correct_user
@user = User.find(params[:id])
redirect_to(root_path) unless current_user?(@user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
Console de rails:
1.9.3-p392 :001 > user = User.find(109)
User Load (8.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 109]]
=> #<User id: 109, name: "laurie", email: "[email protected]", created_at: "2013-09-26 18:10:12", updated_at: "2013-09-26 18:10:12", password_digest: "$2a$10$aXEtun8Z2Deqy2wNxvFRNOjPczKQkYc1vDezP5OduJuF...", remember_token: "YhIUhgFm9iMewxdNOHJ45A", admin: false>
1.9.3-p392 :002 > user.name = "larry"
=> "larry"
1.9.3-p392 :003 > user.save
(0.2ms) begin transaction
User Exists (0.6ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('[email protected]') AND "users"."id" != 109) LIMIT 1
(0.1ms) rollback transaction
=> false
Modèle d'utilisateur:
class User < ActiveRecord::Base
# Declaration of public variables
attr_accessible :email, :name, :password, :password_confirmation
has_secure_password
has_many :microposts, dependent: :destroy
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed
has_many :reverse_relationships, foreign_key: "followed_id", class_name: "Relationship", dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower
before_save {email.downcase!}
before_save :create_remember_token
validates :name, presence: true, length: {maximum: 50}
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false}
validates :password, presence: true, length: {minimum: 6}
validates :password_confirmation, presence: true
after_validation {self.errors.messages.delete(:password_digest)}
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
Votre modèle utilisateur a probablement des validations qui ne sont pas satisfaites. Comme vous ne les avez pas postées, je suis incapable de vraiment résoudre votre question. Pour faciliter la vie, vous pouvez déboguer pourquoi votre utilisateur ne veut pas sauvegarder.
Essayez de courir
user.errors.full_messages
ce qui devrait vous donner un indice sur ce qui ne va pas.
Je sais que ceci est un ancien post, mais j'espère que cela pourrait aider quelqu'un à suivre ce tutoriel à l'avenir.
Comme le dit la réponse acceptée, cela est dû à des validations non satisfaites. J'ai rencontré ce problème également et ai découvert qu'une autre solution consiste à utiliser la méthode update_attribute
sur l'objet user
. Par exemple, si vous souhaitez mettre à jour le champ name
d'un objet user
et le sauvegarder automatiquement dans la base de données, sans devoir toucher aux champs virtuels password
et password_confirmation
, utilisez ce qui suit:
user.update_attribute(:name, "larry")
Ceci mettra à jour le champ name
uniquement et l'enregistrera dans la base de données (inutile d'appeler la méthode save
), sans avoir à toucher aux champs password
et password_confirmation
.
Après avoir essayé de sauvegarder ou de valider une instance de modèle d’enregistrement actif, vous pouvez afficher plus d’informations sur ce qui s’est passé avec quelques commandes utiles.
user = User.find(108)
user.name = "Larry"
user.valid? # returns false
user.errors.messages # returns something like {email: "Cant be blank"}
Évidemment, j'ai commis cette erreur parce que je ne sais pas à quoi ressemble votre fichier modèle, mais si les rôles sont rétrogradés, c’est pour l’une des deux raisons suivantes. La première est que vos validations ont échoué. S'il n'y a pas de message d'erreur, c'est probablement parce que quelque chose dans votre chaîne de filtres a renvoyé la valeur false. Par exemple
class User << ActiveRecord::Base
before_save :accidentally_return_false
def accidentally_return_false
self.some_boolean = (condition == value)
end
end
user = User.new( params )
user.save # where condition does not equal value
user.valid? # false because of the before save method
J'espère que cela pourra aider
Lorsque vous sauvegardez des annulations, utilisez save! au lieu de cela, et le journal des erreurs sera imprimé.
Vos validations ne passent pas. Tu peux faire:
user.errors.full_messages
dans la console après l’enregistrement échoué pour voir pourquoi.
J'ai eu le même problème et aucune erreur n'a été enregistrée. Il s'est avéré que ma fonction before_save
retournait la valeur false, ce qui a entraîné l'annulation de la sauvegarde (je suppose? Je suis nouveau dans Rails).
J'essayais de définir la valeur d'un booléen qui ne pourrait être défini qu'une fois le fichier chargé.
Voici ce que je faisais:
before_save :set_orientation
def set_orientation
# ...do stuff...
self[:is_landscape] = ratio > 1 # stores AND returns the boolean value!!
end
La dernière ligne de la fonction était aussi un retour implicite que je ne voulais pas faire. Ma solution était de rendre le retour explicitement:
before_save :set_orientation
def set_orientation
# ...do stuff...
self[:is_landscape] = ratio > 1 # store the boolean value
return # now return
end
La base de données annulait mes transactions dans la console alors que j'essayais de mettre à jour la propriété admin sur un utilisateur. Si vous suivez le didacticiel Hartl Rails, le problème est que si vous tapez user.errors.messages dans la console, cela vous indiquera que le mot de passe est trop court. En effet, dans le modèle, un mot de passe est validé avant qu'il ne soit enregistré et que votre mot de passe soit haché dans le mot de passe password_digest.
La solution consiste à utiliser user.admin = true, puis, lorsque vous avez terminé, entrez user.password = "foobar", puis entrez user.password_confirmation = "foobar", puis vous effectuez user.save, il va valider toutes vos modifications.
Essayez de mettre à jour la base de données:
Rails db:migrate