Как обновить только часть атрибутов, а не все, в рельсах

У меня есть форма редактирования для обновления некоторых атрибутов. Но он пытается редактировать все атрибуты, и из-за этого у меня ошибка проверки.

Моя форма (редактировать вид)

#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"

Мои действия по обновлению и редактированию:

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

Когда я отправляю форму, она выдает ошибки проверки вроде: "Пароль не может быть пустым"

Итак, как обновить только часть атрибутов, а не все? Я не хочу обновлять пароль в моем случае.

Моя модель пользователя

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

5 ответов

Решение

Я считаю, что ваша модель недействительна в своем текущем состоянии... вы не отправляете пароль, поэтому Rails не затрагивает этот атрибут.

В консоли рельсов проверьте:

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

Моя гипотеза заключается в том, что он недействителен - из-за отсутствия пароля.

Я исправил эту проблему, добавив

,:on => :create

на мои строки validates_presence_of и validates_length_of.

Удалить его из хеша params

params.delete(:password)

Или создайте свой собственный хеш для отправки на обновление.

Аутентификация Checkout в Rails 3.1 для сглаживания вашей аутентификации. он берет много кода из вашей модели.

Затем я заметил, что: если поле по какой-либо причине скрыто от формы, rails не передает это в хэш params для обновления. Таким образом, вы можете играть со скрытыми полями в форме. Вот как я решаю свою.

Я решил это в проверке пароля пользователя следующим образом:

validates :password, :presence     => true,
                     :confirmation => true,
                     :if           => :password # only validate if password changed!
Другие вопросы по тегам