Rails: update_attribute vs update_attributes

229
Object.update_attribute(:only_one_field, "Some Value")
Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

Оба из них будут обновлять объект без необходимости явно указывать AR для обновления.

API Rails говорит:

для update_attribute

Обновляет один атрибут и сохраняет запись без прохождения обычной процедуры проверки достоверности. Это особенно полезно для булевых флагов в существующих записях. Обычный метод update_attribute в Base заменяется на это, когда модуль валидации смешан, в котором он по умолчанию.

для update_attributes

Обновляет все атрибуты из переданного хэша и сохраняет запись. Если объект недействителен, сохранение завершится неудачно и будет возвращено значение false.

Итак, если я не хочу, чтобы объект был проверен, я должен использовать update_attribute. Что делать, если у меня есть это обновление на before_save, будет ли он stackoverflow?

Мой вопрос: update_attribute также обходит перед сохранением или просто проверку.

Кроме того, что такое правильный синтаксис для передачи хэша update_attributes... проверьте мой пример вверху.

  • 0
    Почему вы хотите поместить оператор update_attribute в before_save вызов before_save ? Я не могу придумать вескую причину для этого.
  • 1
    У меня есть объекты, которые должны быть обновлены в зависимости от количества обновленного объекта. Какой способ лучше?
Показать ещё 3 комментария
Теги:
callback

11 ответов

280
Лучший ответ

Обратитесь к update_attribute. При нажатии на ссылку show source вы получите следующий код

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2614
2614:       def update_attribute(name, value)
2615:         send(name.to_s + '=', value)
2616:         save(false)
2617:       end

и теперь отсылайте update_attributes и посмотрите на свой код, который вы получаете

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2621
2621:       def update_attributes(attributes)
2622:         self.attributes = attributes
2623:         save
2624:       end

разница между двумя update_attribute использует save(false) тогда как update_attributes использует save или вы можете сказать save(true).

Извините за длинное описание, но то, что я хочу сказать, важно. save(perform_validation = true), если perform_validation является ложным, он обходит (пропуски будут правильным словом) все validations, связанный с save.

Для второго вопроса

Кроме того, что такое правильный синтаксис для передачи хэша update_attributes... проверьте мой пример вверху.

Ваш пример верный.

Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

или

Object.update_attributes :field1 => "value", :field2 => "value2", :field3 => "value3"

или если вы получите все данные полей и имя в хеше, скажите params[:user] здесь используйте только

Object.update_attributes(params[:user])
  • 6
    Ваше утверждение о обратных вызовах неверно, по крайней мере, в Rails 3 . В комментариях в источнике очень ясно сказано, что «обратные вызовы вызываются».
  • 0
    Я второй, что говорит @Batkins
Показать ещё 2 комментария
73

Совет: update_attribute устаревает в Rails 4 через Commit a7f4b0a1. Он удаляет update_attribute в пользу update_column.

  • 37
    Это больше не правда; метод был повторно добавлен. См. Github.com/rails/rails/pull/6738#issuecomment-39584005
  • 15
    update_attribute пропускает проверку, но учитывает обратные вызовы, update_column будет пропускать как проверки, так и обратные вызовы и не будет обновлять :updated_at , update - это обычная функция, которая будет учитывать как обратные вызовы, так и проверку
Показать ещё 2 комментария
15

update_attribute

Этот метод обновляет отдельный атрибут объекта без активации проверки на основе модели.

obj = Model.find_by_id(params[:id])
obj.update_attribute :language, "java"

update_attributes

Этот метод обновляет несколько атрибутов одного объекта, а также проверяет основанную на модели модель.

attributes = {:name => "BalaChandar", :age => 23}
obj = Model.find_by_id(params[:id])
obj.update_attributes(attributes)

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

11

Также стоит отметить, что при update_attribute, требуемый атрибут, который необходимо обновить, не должен быть белым, указанным с помощью attr_accessible, чтобы обновить его, а не метод массового присвоения update_attributes, который будет обновлять только attr_accessible указанные атрибуты.

6

Отличные ответы. обратите внимание, что как для ruby ​​1.9 и выше вы могли бы (и я думаю, должен) использовать новый синтаксис хэша для update_attributes:

Model.update_attributes(column1: "data", column2: "data")
5

update_attribute просто обновляет только один атрибут модели, но мы можем передать несколько атрибутов в методе update_attributes.

Пример:

user = User.last

#update_attribute
user.update_attribute(:status, "active")

Он проходит проверку

#update_attributes
user.update_attributes(first_name: 'update name', status: "active")

он не обновляется, если проверка не выполняется.

  • 0
    Очень хорошо объяснил. Спасибо!
4

Вам может быть интересно посетить это сообщение в блоге, касающееся всех возможных способов назначения атрибута или записи обновления (обновлено до Rails 4) update_attribute, update, update_column, update_columns etc. http://www.davidverhasselt.com/set-attributes-in-activerecord/. Например, он отличается в таких аспектах, как запуск проверки, касание объекта update_at или запуск обратных вызовов.

В качестве ответа на вопрос OP update_attribute не передаются обратные вызовы.

  • 0
    Да, конечно, я изменил ответ. Спасибо за ответ.
2

Недавно я столкнулся с update_attribute vs. update_attributes и ошибкой проверки, поэтому похожие имена, так что разные поведения, так запутались.

Чтобы передать хэш на update_attribute и выполнить проверку байпаса, вы можете сделать:

object = Object.new
object.attributes = {
  field1: 'value',
  field2: 'value2',
  field3: 'value3'
}
object.save!(validate: false)
2

Чтобы ответить на ваш вопрос, update_attribute пропустит предварительную сохранение "валидации", но все еще выполняет любые другие обратные вызовы, такие как after_save и т.д. Поэтому, если вы действительно хотите "просто обновить столбец и пропустить любой AR-треск", тогда вам нужно использовать (по-видимому)

Model.update_all(...) см. https://stackoverflow.com/questions/7243729/how-to-update-attributes-without-executing-before-save

2

update_attribute и update_attributes похожи, но с одной большой разницей: update_attribute не выполняет проверки.

также:

  • update_attribute используется для обновления записи с помощью одного атрибута.

    Model.update_attribute(:column_name, column_value1)
    
  • update_attributes используется для обновления записи несколькими атрибутами.

    Model.update_attributes(:column_name1 => column_value1, :column_name2 => column_value2, ...)
    

Эти два метода очень легко путать, учитывая их похожие имена и работы. Поэтому update_attribute удаляется в пользу update_column.

Теперь в Rails4 вы можете использовать Model.update_column(:column_name, column_value) в месте Model.update_attribute(:column_name, column_value)

Нажмите здесь, чтобы получить дополнительную информацию о update_column.

1

Я думаю, ваш вопрос в том, что если update_attribute в before_save приведет к бесконечному циклу (из вызовов update_attribute в before_save обратные вызовы, изначально вызванные вызовом update_attribute)

Я уверен, что он обходит обратный вызов before_save, поскольку он фактически не сохраняет запись. Вы также можете сохранить запись без запуска проверки с помощью

Model.save false

Ещё вопросы

Сообщество Overcoder
Наверх
Меню