Rails: update_attribute против update_attributes - PullRequest
246 голосов
/ 06 мая 2010
Object.update_attribute(:only_one_field, "Some Value")
Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

Оба они будут обновлять объект без явного указания AR обновлять.

Rails API говорит:

для атрибута обновления

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

для атрибутов обновления

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

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

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

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

Ответы [ 11 ]

318 голосов
/ 06 мая 2010

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

      # 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 ложно, он обходит (пропуски будут правильным словом) все проверки , связанные с 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])
74 голосов
/ 27 июня 2012

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

15 голосов
/ 21 января 2013

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 голосов
/ 09 августа 2012

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

7 голосов
/ 20 апреля 2015

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

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

6 голосов
/ 31 декабря 2014

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

Model.update_attributes(column1: "data", column2: "data")
5 голосов
/ 14 июля 2015

Возможно, вас заинтересует посещение этого блога, касающегося всех возможных способов присвоения атрибута или обновления записи (обновлено до Rails 4). прикосновение к объекту updated_at или запуск обратных вызовов.

В качестве ответа на вопрос ОП update_attribute не пропускает обратные вызовы.

4 голосов
/ 20 марта 2014

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

Также:

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

    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.

3 голосов
/ 21 мая 2014

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

Model.update_all(...) см. https://stackoverflow.com/a/7243777/32453

2 голосов
/ 06 мая 2015

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

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

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