update_attributes() for a single column

I was just faced with a strange ROLLBACK exception when attempting to
execute this code:

$ rails console
user = User.first
  User Load (1.1ms) SELECT "users".* FROM "users" ORDER BY
"users"."id" ASC LIMIT 1
=> #<User id: 1, name: "Michael Hartl", email: "foo@bar.com",
created_at: "2013-05-12 12:47:23", updated_at: "2013-05-12 13:24:26",
password_digest: "$2a
irb(main):005:0> user.update_attributes(email:
   (2.1ms) BEGIN
  User Exists (4.2ms) SELECT 1 AS one FROM "users" WHERE
(LOWER("users"."email") = LOWER('example@railstutorial.org') AND
"users"."id" != 1) LIMIT 1
   (0.7ms) ROLLBACK
=> false

There definitely is no user in the database (Postgres) matching given
blog=> \d users
                                        Table "public.users"
     Column | Type |

class User < ActiveRecord::Base
before_save { email.downcase! }


    validates :password\_confirmation, presence: true
    validates :password, length: \{ minimum: 6 \}

I now think it may be the peculiarity of the model: it validates
presence of password confirmation, which makes no sense when password
itself isn't or shouldn't be updated.

That is indeed weird - the only validation I've ever used in conjunction with the confirmation field is validates_confirmation_of. You can check user.errors to see all the errors rails thinks the object has.


Did you define:

attr_accessible :email, :name, :password, :password_confirmation, … #other attributes if needed

Thanks, it was indeed missing password + confirmation causing the

irb(main):004:0> user.errors
=> #<ActiveModel::Errors:0x29fe1b30 @base=#<User id: 1, name: "Example
User", email: "exampl@railstutorial.org", created_at: "2013-05-12
12:47:23", updated_at: "2013-05-19 07:55:25", password_digest: "$2a
@messages={:password_confirmation=>["can't be blank"], :password=>["is
too short (minimum is 6 characters)"]}>

has_secure_password must be something new in Rails 4. It does
everything validates_confirmation_of does.
And attr_accessible also seems to have become a thing from the past.

Validation should be conditional. Considering that both password and
password_confirmation are virtual and are never saved to the database
(only password_digest, a special field expected by
has_secure_password), their validation should be special cased (like
only password being present to signify desire to change it, thus
trigger the confirmation check).