title: Ruby on Rails / Devise - Requiring password on email change
body: <p>This is it, for all the marbles, if I can get this issue solved then I have a project completed.</p>
  
  <p>Anyway, I am using Ruby on Rails 3 with Devise for user authentication. As you may know, in the user admin/edit by default, a user has to enter their current password in the current_password field if they provide a new password. There is a TON of information out there on how to disable current_password so users can change and save freely.</p>
  
  <p>However, I can find very little on doing the opposite: requiring the current password for more fields...in my case, the email field. AND only require the current password when that email addy is changed, not if it remains the same. Currently users can freely change their email without giving their current password, and for security reasons, I don't want this.</p>
  
  <p>After looking through the Devise wiki, I did find <a href="https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-account-without-providing-a-password" rel="noreferrer">this page</a> and I thought I could reverse this code to complete this solution. I managed to work this little bit out in my user.rb model (I stripped out of the unnecessary logic for this post)....</p>
  
  <pre><code>class User &lt; ActiveRecord::Base
    # Include default devise modules. Others available are:
    # :token_authenticatable, :confirmable, :lockable and :timeoutable
    devise :database_authenticatable, :registerable, :confirmable,
           :recoverable, :rememberable, :trackable, :validatable
  
    # Setup accessible (or protected) attributes for your model
    attr_accessible :name, :email, :password, :password_confirmation, :avatar, :remember_me, :agree
    attr_accessor :accessible, :agree, :signed_in
    attr_readonly :name
  
    # Validation
    validates :name, :presence =&gt; TRUE, :uniqueness =&gt; TRUE, :length =&gt; { :within =&gt; 4..20 }
    validates :agree, :term_agreement =&gt; TRUE, :unless =&gt; :signed_in
    validates_attachment_size :avatar, :less_than =&gt; 1.megabyte
    validates_attachment_content_type :avatar, :content_type =&gt; ['image/jpeg', 'image/png', 'image/gif']
    validates :current_password, :presence =&gt; TRUE, :if =&gt; :password_required?
  
    protected
  
    def password_required?
      email_changed?
    end
  
  end
  </code></pre>
  
  <p>It "almost" works. If I save the user profile with changing nothing, or change other non-password required field (like the user avatar), the profile saves fine, no password required. So far, so good.</p>
  
  <p>And if I change the email address, the validation <em>is</em> triggered....but what happens is that both the current_password AND password (for new password) fields trigger as required. And if I fill in the password in all three (password, password_confirmation, current_password) just for the hell of it, it won't take, just gives a validation error again.</p>
  
  <p>Basically, ONLY the current_password should be required if the email address is changed. How would I make this work in my code?</p>
  
  <ul>
  <li>UPDATE *******</li>
  </ul>
  
  <p>I checked out my log in response to the below suggestion by bowsersenior, and see the following lines when I attempt to save and update the email...</p>
  
  <pre><code>User Load (0.2ms)  SELECT `users`.`id` FROM `users` WHERE (LOWER(`users`.`email`) = LOWER('newaddress@changed.com')) AND (`users`.id &lt;&gt; 1) LIMIT 1
    User Load (0.2ms)  SELECT `users`.`id` FROM `users` WHERE (`users`.`name` = BINARY 'Administrator') AND (`users`.id &lt;&gt; 1) LIMIT 1
    SQL (0.1ms)  ROLLBACK
  </code></pre>
  
  <p>I wonder if that 'ROLLBACK' has something to do with the final issue?</p>