Правильный ответ больше не работает для рельсов 4 .Я считаю, что мой ответ - самый чистый и универсальный , который будет работать, когда вы захотите пропустить любые атрибуты (не только пароль).Этот подход понадобится, если вы хотите обновить отдельные атрибуты любой модели в нескольких разных местах.
Например, если вы хотите сделать то, что делает переполнение стека, и пароли можно обновлять с помощью security
страница, изображение профиля, обновляемое с помощью представления пользователя, и большая часть информации о пользователе, обновляемая с помощью представления редактирования пользователя.
1) Расширьте hash class
методом класса, чтобы удалить пустые значения,Мы будем использовать этот метод для удаления пустых значений, которые не обновляются, но все еще присутствуют в хэше params:
1a) Создайте файл hash.rb
в вашем lib
каталог, в каталоге ext
:
командная строка
$ mkdir lib/ext
$ touch lib/ext/hash.rb
1b) Внутри hash.rb
, «создать» aHash
Класс и создать .delete_blanks!
метод:
lib / ext / hash.rb
class Hash
def delete_blanks!
delete_if { |k, v| v.nil? }
end
end
1c) Требовать этогофайл (и весь каталог lib) в рельсы, ссылающиеся на него в инициализаторе:
config / boot.rb
# other things such as gemfiles are required here, left out for brevity
Dir['lib/**/*.rb'].each { |f| load(f) } # requires all .rb files in the lib directory
2) Внутриuser # update action, реализуйте наши новые блестящие delete_blanks!Метод класса для удаления атрибутов, которые мы не обновляем из хэша params.Затем обновите пользовательский экземпляр с помощью метода update_attributes
, * не метода update
!
2a) Во-первых, давайте использовать delete_blanks!способ исправить наш хэш user_params:
app / controllers / users_controller.rb
new_params = user_params.delete_blanks!
2b) А теперь давайте обновим экземпляр, используяupdate_attributes
метод (опять же, не update
метод):
app / controllers / users_controller.rb
@user.update_attributes(new_params)
Вот как закончил users#update
действие должно выглядеть так:
app / controllers / users_controller.rb
def update
new_params = user_params.delete_blanks!
if @user.update_attributes(new_params)
redirect_to @user, notice: 'User was successfully updated.'
else
render action: 'edit' // or whatever you want to do
end
end
3) В User
модель, добавьте параметр if: :<attribute>
для всех ваших проверок.Это делается для того, чтобы проверка запускалась только в том случае, если атрибут присутствует в хэше params.Наш метод delete_blanks!
удалит атрибут из хэша params, поэтому проверка пароля, например, не будет выполняться.Также стоит отметить, что delete_blanks!
удаляет только хеш-записи со значением nil , но не с пустыми строками.Поэтому, если кто-то пропустит пароль в пользовательской форме создания (или любой форме с полем для пароля), проверка присутствия вступит в силу, потому что: пароль в хэше не будет равен нулю, он будет пустымстрока:
3a) Используйте параметр if:
для всех проверок:
app / models / user.rb
VALID_EMAIL_REGEX = /[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9\-.]/
validates :first_name, presence: true, if: :first_name
validates :last_name, presence: true, if: :last_name
validates :user_name, presence: true, if: :user_name
validates :email, presence: true,
uniqueness: { case_sensitive: false },
format: { with: VALID_EMAIL_REGEX }, if: :email
validates :password, length: { minimum: 6, maximum: 10 }, if: :password
И это все.Теперь пользовательская модель может быть обновлена во множестве различных форм по всему вашему приложению.Подтверждения присутствия для атрибута все еще вступают в игру в любой форме, которая содержит поле для него, например, проверка присутствия пароля все равно вступает в игру в представлении user#create
.
Это может показаться более подробным, чем другие ответыНо я считаю, что это самый надежный способ.Вы можете отдельно обновить бесконечное количество атрибутов для экземпляров User
на бесконечном количестве различных моделей.Просто помните, когда вы хотите сделать это с новой моделью, вам нужно повторить шаги 2a) , 2b) и 3a)