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
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.
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.
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
Wenn Sie Rollbacks speichern, verwenden Sie save! Stattdessen wird ein Fehlerprotokoll gedruckt.
Ihre Validierungen sind nicht bestanden. Du kannst tun:
user.errors.full_messages
in der Konsole nach dem fehlgeschlagenen Speichern, um zu sehen, warum.
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
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.
Versuchen Sie, die Datenbank zu aktualisieren:
Rails db:migrate
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.