Ruby on Rails. Различные способы задания атрибутов для модели ActiveRecord

8 мая 2015, пятница

В Rails 4 у разработчиков есть возможность задавать атрибуты модели ActiveRecord различными способами. Каждый способ делает это по-разному и иногда с побочными эффектами. Важно понимать какой способ использорвать в той или иной ситуации. Вот вам шпаргалка с подробной информацией по всем способам.

Шпаргалка

Метод Использует метод доступа Сохранение в базе Валидации Колбэки Изменение updated_at Проверка readonly
attribute= Да Нет n/a n/a n/a n/a
write_attribute Нет Нет n/a n/a n/a n/a
update_attribute Да Да Нет Да Да Да
attributes= Да Нет n/a n/a n/a n/a
update Да Да Да Да Да Да
update_column Нет Да Нет Нет Нет Да
update_columns Нет Да Нет Нет Нет Да
User:update Да Да Да Да Да Да
User:update_all Нет Да Нет Нет Нет Нет

В деталях

В последующих примерах будем устанавливать атрибут name для объекта user.

user.name = «Rob»

Это обычное присвоение является наиболее распространенным и простым в использовании. Атрибут name будет помечен как измененный, но не будет сохранен в базе.

Вы можете откатить изменения, вызвав функцию reload! или сохранить изменения функцией save.

user.write_attribute(:name, «Rob»)

Этот метод используется стандатной функцией присвоения выше. Является псевдонимом для метода user[:name] = «Rob». Также имеется и функция read_attribute.

Как и вышеприеденный способ, этот способ не сохраняет атрибут в базе данных. Этот способ используется везде, гду нужно обойти стандартный метод присваивания атрибута, например, если вы захотите переопределить метод attribute= в своей модели, чтобы приваиваемое имя было с большой буквы:

def name=(new_name)
  write_attribute(:name, new_name.upcase)
  # Это эквивалентно:
  # self[:name] = new_name.upcase
end

user.update_attribute(:name, «Rob»)

Этот метод изменит атрибут и сохранит его сразу же в базе данных без вызова валидаций, но с вызовом коллбэков и обновлением updated_at.

Подводные камни:

  • другие измененные атрибуты также сохраняться в базе данных
  • валидации пропускаются и погут быть сохранены некорректные данные

Поэтому лучше использовать update даже если вам надо изменить только один атрибут.

user.attributes = {name: «Rob»}

Этот способ изменить все, переданные атрибуты. Изменения не будут сохранены в базе данных. Остальные атрибуты останутся неизменными. Вы также можете использовать метод assign_attributes:

user.attributes = {name: "Rob", age: 12}
user.assign_attributes {name: "Rob", age: 12}

user.update(name: «Rob»)

Этот метод изменят атрибуты, выполняет валидации и вызывает коллбэки, сохраняет запись в базе данных, если данные валидны, и обновляет updated_at записи.

user.update_columns(name: «Rob»)

Этот метод работает так же как и User:update_all, он выполняет прямой SQL UPDATE запрос в базу данных и пропускает валидации и коллбэки. Но в отличие от первого, если колонка помечена как readonly, будет сгенерировано исключение.

user.update_column(:name, «Rob»)

Эквивалентно вызову описанного выше user.update_columns(name: «Rob»).

User.update(1, name: «Rob»)

Метод находит объект по переданному ID и обновляет атрибуты, переданные в хэше. Метод вызывает коллбэки и валидации, обновляет updated_at записи.

Можно одноверменно изменять несколько объектов:

User.update(
  [1,2,3],
  [
    {name: "Rob"},
    {name: "David", age: 12},
    {age: 15, location: "London"},
  ]
)

Второй аргумент массив хэшей.

User.update_all(1, name: «Rob»)

Этот метод выполняет прямой SQL UPDATE запрос в базу данных, пропуская коллбэки и валидации. Ва можете вызывать этот метод для набора объектов:

User.where(name: "Robbie").update_all(name: "Rob")
#обновит всех пользователей с именем Robbie