web-dev-qa-db-fra.com

Pourquoi mes Rails sont-ils annulés lorsque j'essaie de sauvegarder user.save?

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
45
Venomoustoad

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.

124
jewilmeer

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.

15
Richard Gieg

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

7
Tyrel Richey

Lorsque vous sauvegardez des annulations, utilisez save! au lieu de cela, et le journal des erreurs sera imprimé.

5
Max Wong

Vos validations ne passent pas. Tu peux faire:

user.errors.full_messages

dans la console après l’enregistrement échoué pour voir pourquoi.

3
mechanicalfish

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
2
Kyle Falconer

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. 

0
Michael Klump

Essayez de mettre à jour la base de données: 

Rails db:migrate
0
giangmt