ruby on rails - ¿Por qué mis carriles se deshacen cuando trato de user.save?
ruby-on-rails railstutorial.org (8)
He instalado la aplicación de ejemplo RailsTutorial (la aplicación de twitter) y trato de entender por qué el siguiente código de consola no actualiza la base de datos cuando intento actualizar la base de datos del usuario. Estoy esperando que la información del usuario se actualice una vez que use el user.save
. Sin embargo, esto se remonta a datos no editados. ¿Es esto debido a una restricción basada en el usuario?
Controlador de usuarios:
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
Consola de rieles:
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
Modelo de usuario:
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
Cuando guarde rollbacks, use save! en su lugar, y se imprimirá el registro de errores.
Después de intentar guardar o validar una instancia de modelo de registro activo, puede ver más información sobre lo que sucedió con algunos comandos útiles.
user = User.find(108)
user.name = "Larry"
user.valid? # returns false
user.errors.messages # returns something like {email: "Cant be blank"}
Obviamente, cometí ese error porque no sé cómo se ve el archivo de tu modelo, pero si responde a su respuesta por una de dos razones, generalmente. El primero es tu validación fallida. Si no hay mensajes de error, probablemente se deba a que algo en su cadena de filtros devolvió falso. Por ejemplo
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
Espero que ayude
Intenta actualizar la base de datos:
rails db:migrate
Sé que este es un post antiguo, pero espero que esto pueda ayudar a alguien a seguir este tutorial en el futuro.
Como expresa la respuesta aceptada, esto se debe a validaciones que no se están cumpliendo. También me encontré con este problema y encontré que otra solución es usar el método update_attribute
en el objeto de user
. Por ejemplo, si desea actualizar el campo de name
de un objeto de user
y guardarlo automáticamente en la base de datos, sin tener que tocar los campos de password_confirmation
virtual y password_confirmation
, use lo siguiente:
user.update_attribute(:name, "larry")
Esto actualizará solo el campo de name
y lo guardará en la base de datos (no es necesario llamar al método de save
), sin tener que tocar los campos de password
y password_confirmation
.
Su modelo de usuario probablemente tiene validaciones que no están satisfechas. Ya que no has publicado esos, no puedo resolver tu pregunta. Para facilitar la vida, puede depurar por qué su usuario no está dispuesto a guardar.
Intenta correr
user.errors.full_messages
lo que debería darle una pista de lo que está mal.
Tus validaciones no están pasando. Tu puedes hacer:
user.errors.full_messages
en la consola después del guardado fallido para ver por qué.
Tuve el mismo problema de la base de datos al deshacer mis transacciones en la consola mientras intentaba actualizar la propiedad de administrador en un usuario. Si está haciendo el tutorial de Hartl Rails, el problema es que si escribe user.errors.messages en la consola, le dirá que la contraseña es demasiado corta. Esto se debe a que en el modelo hay una validación de contraseña antes de que se guarde y se borre la contraseña en el password_digest.
La solución a esto es en la consola realizar su actividad normal como configurar user.admin = true, y luego, cuando haya terminado, ingrese user.password = "foobar", luego ingrese user.password_confirmation = "foobar", y luego cuando Usted realiza user.save, confirmará todos sus cambios.
Tuve este mismo problema y no se almacenaban errores. Resultó que mi función before_save
devolvía falso, lo que resultó en la cancelación del guardado (supongo que soy nuevo en los rieles).
Estaba tratando de establecer el valor de un booleano que solo podía establecerse una vez que se había cargado un archivo.
Esto es lo que estaba haciendo:
before_save :set_orientation
def set_orientation
# ...do stuff...
self[:is_landscape] = ratio > 1 # stores AND returns the boolean value!!
end
La última línea en la función también fue un retorno implícito que no pretendía hacer. Mi solución fue hacer la devolución explícitamente:
before_save :set_orientation
def set_orientation
# ...do stuff...
self[:is_landscape] = ratio > 1 # store the boolean value
return # now return
end