Rails 3 проверяет, изменился ли атрибут - PullRequest
145 голосов
/ 19 февраля 2011

Необходимо проверить, изменился ли блок атрибутов перед обновлением в Rails 3.

street1, street2, город, штат, почтовый индекс

Я знаю, что могу использовать что-то вроде

if @user.street1 != params[:user][:street1]
  then do something....
end

Но этот кусок кода будет ДЕЙСТВИТЕЛЬНО длинным.Есть ли способ чище?

Ответы [ 5 ]

272 голосов
/ 19 февраля 2011

Извлечение ActiveModel :: Dirty (доступно для всех моделей по умолчанию).Документация действительно хорошая, но она позволяет вам делать такие вещи, как:

@user.street1_changed? # => true/false
53 голосов
/ 12 сентября 2013

Так я решил проблему проверки изменений в нескольких атрибутах.

attrs = ["street1", "street2", "city", "state", "zipcode"]

if (@user.changed & attrs).any?
  then do something....
end

Метод changed возвращает массив атрибутовизменен для этого объекта.

Оба @user.changed и attrs являются массивами, поэтому я могу получить пересечение (см. ary & other ary метод).Результатом пересечения является массив.Вызывая any? для массива, я получаю true, если есть хотя бы одно пересечение.

Также очень полезно, метод changed_attributes возвращает хэш атрибутов с их оригиналомзначения и changes возвращает хэш атрибутов с их исходными и новыми значениями (в массиве).

Вы можете проверить APIDock, для каких версий поддерживаются эти методы.

http://apidock.com/rails/ActiveModel/Dirty

14 голосов
/ 05 февраля 2014

ActiveModel::Dirty не работал для меня, потому что @model.update_attributes() скрыл изменения.Вот как я обнаружил изменения в методе update в контроллере:

def update
  @model = Model.find(params[:id])
  detect_changes

  if @model.update_attributes(params[:model])
    do_stuff if attr_changed?
  end
end

private

def detect_changes
  @changed = []
  @changed << :attr if @model.attr != params[:model][:attr]
end

def attr_changed?
  @changed.include :attr
end

Если вы пытаетесь обнаружить много изменений атрибутов, это может привести к путанице.Вероятно, не следует делать это в контроллере, но ме.

5 голосов
/ 21 июня 2018

Для рельсов 5.1+ обратных вызовов

Чтобы улучшить этот пост и завершить другие ответы

Первый ответ будет отменен для обратных вызовов при следующемрельсы версии (после 5.1).
Таким образом, новый способ проверить, изменился ли атрибут, с помощью сохраненного_изменения_t_attribute?

Вы можете сделать:

@user.saved_change_to_street1? # => true/false

Вы можете увидеть больше примеров здесь, в этом блоге

2 голосов
/ 17 мая 2018

Приведенные выше ответы лучше, но, тем не менее, для понимания у нас есть и другой подход: значение столбца 'catagory' изменилось для объекта (@design),

@design.changes.has_key?('catagory')

.changes вернет хешключ в качестве имени столбца и значения в виде массива с двумя значениями [old_value, new_value] для каждого столбца.Например, категория выше для изменена с 'ABC' на 'XYZ' @ design,

@design.changes   # => {} 
@design.catagory = 'XYZ'
@design.changes # => { 'catagory' => ['ABC', 'XYZ'] }

Для ссылок изменение в ROR

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...