webentwicklung-frage-antwort-db.com.de

Warum rollen meine Rails zurück, wenn ich user.save versuche?

Ich habe die Beispiel-App "RailsTutorial" (die Anwendung "Twitter") installiert und verstehe, warum der folgende Konsolencode die Datenbank nicht aktualisiert, wenn ich versuche, die Benutzer-Datenbank zu aktualisieren. Ich erwarte, dass die Benutzerinformationen aktualisiert werden, sobald ich den user.save verwende. Dies führt jedoch zu unbearbeiteten Daten zurück. Liegt dies an einer benutzerbasierten Einschränkung? 

Benutzersteuerung:

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

Rails Konsole:

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 

Benutzermodell:

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+\-.][email protected][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

Ihr Benutzermodell hat wahrscheinlich Validierungen, die nicht erfüllt werden. Da Sie diese nicht gepostet haben, kann ich Ihre Frage nicht wirklich lösen. Um das Leben einfacher zu machen, können Sie debuggen, warum Ihr Benutzer nicht zum Speichern bereit ist.

Versuchen Sie zu laufen

user.errors.full_messages

was Ihnen einen Hinweis geben sollte, was falsch läuft.

124
jewilmeer

Ich weiß, dass dies ein alter Beitrag ist, aber hoffentlich kann dies jemandem helfen, der sich in Zukunft mit diesem Tutorial befasst.

Wie die akzeptierte Antwort ausdrückt, liegt dies an Validierungen, die nicht erfüllt werden. Ich bin auch auf dieses Problem gestoßen und habe festgestellt, dass eine andere Problemumgehung darin besteht, die update_attribute-Methode für das user-Objekt zu verwenden. Wenn Sie beispielsweise das Feld name eines user-Objekts aktualisieren und automatisch in der Datenbank speichern möchten, ohne die virtuellen Felder password und password_confirmation berühren zu müssen, verwenden Sie Folgendes:

user.update_attribute(:name, "larry")

Dadurch wird nur das Feld name aktualisiert und in der Datenbank gespeichert (die Methode save muss nicht aufgerufen werden), ohne die Felder password und password_confirmation berühren zu müssen.

15
Richard Gieg

Nachdem Sie versucht haben, eine Instanz eines aktiven Datensatzmodells zu speichern oder zu validieren, können Sie mit ein paar nützlichen Befehlen weitere Informationen zu den Vorgängen anzeigen.

user = User.find(108)
user.name = "Larry"
user.valid? # returns false
user.errors.messages # returns something like {email: "Cant be blank"}

Offensichtlich habe ich diesen Fehler gemacht, weil ich nicht weiß, wie Ihre Modelldatei aussieht, aber ob sie normalerweise aus einem von zwei Gründen eine Rolle spielt. Der erste ist Ihre Validierung ist fehlgeschlagen. Wenn es keine Fehlermeldungen gibt, liegt dies wahrscheinlich daran, dass etwas in Ihrer Filterkette false zurückgegeben hat. Zum Beispiel

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

Hoffentlich hilft das

7
Tyrel Richey

Wenn Sie Rollbacks speichern, verwenden Sie save! Stattdessen wird ein Fehlerprotokoll gedruckt.

5
Max Wong

Ihre Validierungen sind nicht bestanden. Du kannst tun:

user.errors.full_messages

in der Konsole nach dem fehlgeschlagenen Speichern, um zu sehen, warum.

3
mechanicalfish

Ich hatte das gleiche Problem und es wurden keine Fehler gespeichert. Es stellte sich heraus, dass meine before_save-Funktion false zurückgab, was dazu führte, dass die Speicherung abgebrochen wurde (ich glaube, ich bin neu bei Rails).

Ich habe versucht, den Wert eines Booleschen Werts festzulegen, der nur eingestellt werden kann, wenn eine Datei hochgeladen wurde.

Folgendes habe ich gemacht:

before_save :set_orientation

def set_orientation
  # ...do stuff...
  self[:is_landscape] = ratio > 1  # stores AND returns the boolean value!!
end

Die letzte Zeile in der Funktion war auch eine implizite Rückkehr, die ich nicht wollte. Meine Lösung war, die Rückkehr explizit zu machen:

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

Ich hatte das gleiche Problem mit der Datenbank, in der meine Transaktionen in der Konsole zurückgesetzt wurden, während ich versuchte, die Admin-Eigenschaft eines Benutzers zu aktualisieren. Wenn Sie das Hartl Rails-Tutorial durchführen, besteht das Problem darin, dass Sie, wenn Sie user.errors.messages in die Konsole eingeben, Ihnen mitteilen, dass das Kennwort zu kurz ist. Dies liegt daran, dass im Modell eine Kennwortüberprüfung erfolgt, bevor es Ihr Kennwort speichert und in das Kennwort_digest einpflastert. 

Um dies zu umgehen, führen Sie in der Konsole Ihre normale Aktivität aus, beispielsweise user.admin = true. Wenn Sie fertig sind, geben Sie user.password = "foobar" und dann user.password_confirmation = "foobar" ein Sie führen user.ave durch. Es werden alle Ihre Änderungen übernommen. 

0
Michael Klump

Versuchen Sie, die Datenbank zu aktualisieren: 

Rails db:migrate
0
giangmt

Für den Fall, dass dies jemals jemandem in der Zukunft hilft - ich hatte ein ähnliches Problem und was die Rollbacks verursachte, war, dass meine Daten die Validierung nicht bestanden haben (Validierungen implementiert, nachdem das Problem gefunden wurde). Durch manuelles Korrigieren der Daten wurde das Problem behoben.

0
John