Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my rails rollback when I try to user.save?

I have installed the RailsTutorial sample app(the twitter like application) and am trying to understand why the following piece of console code does not update the database when I try updating the user db. I am expecting the user information to get updated once I use the user.save. However, this rolls back to unedited data. Is this due to a user based restriction?

Users controller:

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 console:

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 

User model:

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
like image 262
Venomoustoad Avatar asked Sep 26 '13 20:09

Venomoustoad


People also ask

How do I undo a rollback in rails?

To undo a rails generate command, run a rails destroy command. You can then edit the file and run rake db:migrate again. (See how to roll back a Migration file to rollback a specific migration or multiple migrations.)


3 Answers

Your user model probably has validations which are not satisfied. Since you've not posted those I'm unable to really solve your question. To make live easier you can debug why your user isn't willing to save.

Try running

user.errors.full_messages

which should give you a hint what's going wrong.

like image 60
jewilmeer Avatar answered Oct 09 '22 03:10

jewilmeer


I know this is an old post, but hopefully this might help someone going through this tutorial in the future.

As the accepted answer expresses, this is due to validations which are not being satisfied. I ran into this issue as well and found that another workaround is to use the update_attribute method on the user object. For example, if you want to update the name field of a user object and have it automatically save to the database, without having to touch the virtual password and password_confirmation fields, use the following:

user.update_attribute(:name, "larry")

This will update the name field only and save it to the database (no need to call the save method), without having to touch the password and password_confirmation fields.

like image 20
Richard Gieg Avatar answered Oct 09 '22 05:10

Richard Gieg


After you try to save or validate an active record model instance you can view more information about what happened with a few useful commands.

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

Obviously I made that error up because I don't know what your model file looks like but if it roles back its for one of two reasons usually. The first is your validations failed. If their are no error messages its probably because something in your filter chain returned false. For example

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

Hope that helps

like image 31
Tyrel Richey Avatar answered Oct 09 '22 05:10

Tyrel Richey