ruby-on-rails ruby railstutorial.org

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