Search code examples
ruby-on-railsrubyruby-on-rails-3.1

How to update only part of attributes, not all, in rails


I have an edit form for updating some attributes. But it tryes to edit all attributes, and cause of this I have validation error.

My form (edit view)

#person_info.fl_l
  - if @user.errors.any?
    .error_explanation
      %h2 Form is invalid
      %ul
        -for message in  @user.errors.full_messages
          %li= message


  =form_for @user do |f|
    %p
      Birthday:
      %br
      = f.date_select(:birthday,:start_year => 1940)
    %p
      Name:
      %br
      = f.text_field :name, :value=>@user.name
    %p
      Surname:
      %br
      = f.text_field :surname, :value=>@user.surname
    %p
      Nickname:
      %br
      = f.text_field :nickname, :value=>@user.surname       
    %p
      About Myself:
      %br
      = f.text_area :about_myself, :value=>@user.about_myself
    %p
      = f.submit "Update"

My update and edit actions:

def edit
      @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(params[:user])
      redirect_to @user
    else
      render 'edit'
    end
  end

When I submit the form, it outputs validation errors like: "Password can't be blank"

So, how to update only part of attributes, not all? I dont want to update password in my case.

My user model

class User < ActiveRecord::Base

  has_many :posts
  has_many :sent_messages, :class_name => "Message", :foreign_key => "sender_id"
  has_many :received_messages, :class_name => "Message", :foreign_key => "receiver_id"
  attr_accessible :name, :email, :password, :password_confirmation
  has_secure_password
  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name, :presence => true,
            :length => {:maximum => 50}
  validates :email, :presence => true,
            :format => {:with => email_regex},
            :uniqueness => {:case_sensitive => false}

  validates :password, :presence => true,
            :confirmation => true,
            :length => {:within => 6..40}


  before_create { generate_token(:auth_token) }

  def send_password_reset
    generate_token(:password_reset_token)
    self.password_reset_sent_at = Time.zone.now
    save!
    UserMailer.password_reset(self).deliver
  end

  def generate_token(column)
    begin
      self[column] = SecureRandom.urlsafe_base64
    end while User.exists?(column => self[column])
  end
end

Solution

  • I believe your model is invalid in its current state ... you're not sending in the password, so Rails is not touching that attribute.

    In rails console, test:

    user = User.find(whatever_the_id_is)
    puts user.valid?
    puts user.errors.inspect
    

    My hypothesis is that it is invalid --- due to a missing password.