Rails update_attributes using has_secure_password
ruby-on-rails, update-attributes
Solution
It looks like you want to validate the presence of password on create only (also notice more concise way to validate password confirmation):
validates :password, length:{minimum:6}, confirmation: true, on: :create
You can then use `update_attributes`
You may want to restrict what params can be submitted by using strong params:
- Gem: https://github.com/rails/strong_parameters
- also included in Rails 4 http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
Problem
I am working in a project where users can either have `admin: true / false`. The application will only let admin users login in to the system, the other users are just clients whose settings only admins can edit. This is some sort of commerce application.(Rails 3.2.13) I would like to keep both concepts in the same table since in the future there will possibly be the option of logging in for non-admin users and interact with their profiles, so all the logic will be already implemented. I've got this `User` resource: ``` ActiveRecord::Schema.define(:version => 20131204200554) do create_table "users", :force => true do |t| t.string "name" t.string "surname" t.boolean "admin" t.string "password_digest" t.string "email" t.string "auth_token" end end ``` This is the user model: ``` class User < ActiveRecord::Base has_secure_password attr_accessible :name, :surname,:email, :password, :password_confirmation validates :name, presence:true, length: { maximum:50} validates :first_surname, 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, length:{minimum:6} validates :password_confirmation, presence:true before_save{ self.email.downcase! } before_save :generate_auth_token private def generate_auth_token self.auth_token=SecureRandom.urlsafe_base64 end end ``` And I am trying to implement the functionality of `User` editing, however I only want to allow the editing of `name`, `surname` and `email`. Hence, I present only those fields in the form: ``` <%= form_for(@user) do |f| %> <%= f.label :name,"Name" %> <%= f.text_field :name %> <%= f.label :surname,"Surname" %> <%= f.text_field :surname %> <%= f.label :email,"Email" %> <%= f.text_field :email %> <%= f.submit "Save" %> ``` I am trying to accomplish the goal with this code: ``` def update @user = User.find(params[:id]) if @user.update_attributes(params[:user]) # Handle a successful update. flash[:success]="User updated successfully" redirect_to @user else flash[:danger]="Error updating user" render 'edit' end end ``` My problem is that when trying to `update_attributes` I get not unexpectedly an error validating `password/password_confirmation`, but since I'm using `has_secure_password`, these fields do not exist in the database, only `password_digest`. I am thinking about the best option to accomplish all this: - Update `@user` object with new field values. - Reflect this change in `User` table. - Run the validations, i.e. email validation. While using `has_secure_password`. These are the options so far: - Use of `update_attribute`(best so far). 1.1 Pro: updates the `User` table 1.2 Con: I have to `update_attribute(field1)` for each of the fields, so more lines of code 1.3 Con: Apparently this method no longer exists in Rails 4, problem in case an upgrade is desirable in the future. 1.4 Con: No validations - Use of `@user.attributes=params[:user]` in the controller method 2.1 Pro: Updates multiple fields at once. 2.2 Con: Does not update the `User` table. - User of `update_attributes` 3.1 Pro: Both multiple fields and table update 3.2 Con: Not working ( duh!) Suggestions?