Rails update_attributes без збереження?


386

Чи існує альтернатива update_attributes, яка не зберігає запис?

Тож я міг би зробити щось на кшталт:

@car = Car.new(:make => 'GMC')
#other processing
@car.update_attributes(:model => 'Sierra', :year => "2012", :looks => "Super Sexy, wanna make love to it")
#other processing
@car.save

До речі, я знаю, що можу @car.model = 'Sierra', але хочу оновити їх усі в одному рядку.


що означає "не зберегти запис"?
Анатолій

update_attributes зберігає модель БД. Мені цікаво, чи існує подібний метод, який ні.
tybro0103

3
приписує неруйнівний метод. Дивіться API для деталей
Анатолій

3
Ви можете використовувати update_column (ім'я, значення) Оновлення одного атрибута об'єкта, не викликаючи збереження. 1. Перевірка пропускається. 2. Відклики викликів пропускаються. 3. Сторінка оновлений_ат / оновлений_он не оновлюється, якщо цей стовпець доступний. apidock.com/rails/ActiveRecord/Persistence/update_column
Антуан

10
Для 3.1+, використання assign_attributes apidock.com/rails/ActiveRecord/Base/assign_attributes
elado

Відповіді:


597

Я вірю, що ви шукаєте assign_attributes.

Це в основному те саме, що update_attributes, але він не зберігає запис:

class User < ActiveRecord::Base
  attr_accessible :name
  attr_accessible :name, :is_admin, :as => :admin
end

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }) # Raises an ActiveModel::MassAssignmentSecurity::Error
user.assign_attributes({ :name => 'Bob'})
user.name        # => "Bob"
user.is_admin?   # => false
user.new_record? # => true

Ваш приклад трохи вводить в оману, оскільки ви не вставили цей рядок із моделі attr_accessible :is_admin, :as => :admin:;)
Робін

@ Робін Або просто : attr_protected :is_admin. Або: attr_accessible :nameСправа в тому, що в цьому прикладі: is_admin захищено. Слід також зазначити, що спроба масового присвоєння захищеному атрибуту .assign_attributesсправді викликає значення ActiveModel::MassAssignmentSecurity::Error, хоча це не показано в прикладі.
Ajedi32

Так, але мій рядок - від документа, з яким ви пов’язані. Я просто кажу, що ти повинен був скопіювати / вставити весь приклад. Але так, ви можете просто сказати, що це захищено.
Робін

@Robin Я відновлю приклад, щоб бути трохи більш конкретним. Приклад у документах також трохи оманливий, оскільки він не згадує, що user.assign_attributes({ :name => 'Josh', :is_admin => true })викликає повідомлення про помилку і фактично не встановлює властивість імені користувача.
Ajedi32

7
assign_attributes доступний з Rails 3.1 і далі, тому ви не можете використовувати його, якщо ви все ще використовуєте стару версію Rails.
Хаегін

173

Ви можете використовувати assign_attributesабо attributes=(вони однакові)

Методи оновлення шпаргалки (для Rails 6):

  • update= assign_attributes+save
  • attributes= = псевдонім assign_attributes
  • update_attributes = застарілий, псевдонім update

Джерело:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment .rb

Ще один шпаргалка:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet


1
Чіткий і короткий. Дякую.
freemanoid

1
у випадку .attributes = val, якщо ваша модель has_one і приймає_nested_attributes_для іншої моделі, передача that_model_attributes (без ідентифікатора) видалить існуючу модель has_one, навіть якщо ви не збереглися (наприклад, збережіть). Але присвоювати_attributes не поводиться так.
ClassyPimp

65

Ви можете використовувати метод "атрибути":

@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}

Джерело: http://api.rubyonrails.org/classes/ActiveRecord/Base.html

attributes = (new_attributes, guard_protected_attributes = true) Дозволяє встановлювати всі атрибути одночасно, передаючи в хеш-клавіші, що відповідають назвам атрибутів (що знову відповідає назвам стовпців).

Якщо true_protected_attributes вірно (за замовчуванням), то чутливі атрибути можна захистити від цієї форми присвоєння маси за допомогою макроса attr_protected. Або ви можете вказати, до яких атрибутів можна отримати доступ з макросом attr_accessible. Тоді всі атрибути, не включені до цього, забороняються призначати масово.

class User < ActiveRecord::Base
  attr_protected :is_admin
end

user = User.new
user.attributes = { :username => 'Phusion', :is_admin => true }
user.username   # => "Phusion"
user.is_admin?  # => false

user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
user.is_admin?  # => true

7

Для масового присвоєння значень моделі ActiveRecord без збереження використовуйте assign_attributesабо attributes=методи, або методи. Ці методи доступні в Rails 3 і новіших. Однак існують незначні відмінності та проблеми, пов'язані з версіями.

Обидва методи дотримуються цього використання:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }

@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }

Зауважте, що жоден метод не буде виконувати перевірки або виконувати зворотні дзвінки; Відкликання та перевірка викликів відбудеться колиsave .

Рейки 3

attributes=трохи відрізняється від assign_attributesRails 3. attributes=перевірить, чи переданий йому аргумент є Hash, і повернеться негайно, якщо його немає; assign_attributesне має такої перевірки на хеш. Див. Документацію API присвоєння атрибутів ActiveRecord дляattributes= .

Наступний недійсний код мовчки не вдасться, просто повернувшись без встановлення атрибутів:

@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]

attributes= буде мовчки поводитись так, ніби завдання були виконані успішно, коли насправді їх не було.

Цей недійсний код створить виняток, коли assign_attributesнамагається впорядкувати хеш-ключі вкладеного масиву:

@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])

assign_attributesстворить NoMethodErrorвиняток для stringify_keys, вказуючи на те, що перший аргумент - це не хеш. Виняток сам по собі не дуже інформативний про фактичну причину, але той факт, що виняток має місце, є дуже важливим.

Єдина відмінність між цими випадками полягає в методі, який використовується для масового призначення: attributes=мовчки досягає успіху та assign_attributesстворює виняток, щоб повідомити про помилку.

Ці приклади можуть здатися надуманими, і вони є певною мірою, але такий тип помилок може легко виникнути при перетворенні даних з API або навіть просто за допомогою серії перетворень даних і забуття до Hash[]результатів остаточного .map. Забезпечте деякий код 50 рядків вище та 3 функції, вилучені з призначення атрибутів, і ви отримали рецепт відмови.

Урок з Rails 3 такий: завжди використовувати assign_attributesзамістьattributes= .

Рейки 4

У Rails 4 attributes=це просто псевдонім до assign_attributes. Див. Документацію API присвоєння атрибутів ActiveRecord дляattributes= .

З рельсами 4 будь-який метод може використовуватися взаємозамінно. Якщо не пройти хеш, як перший аргумент, це стане дуже корисним винятком:ArgumentError: When assigning attributes, you must pass a hash as an argument.

Перевірки

Якщо ви готуєте завдання до вильоту перед підготовкою до документа save, вам може бути цікаво перевірити його і перед збереженням. Для цього можна використовувати valid?і invalid?методи. Обидва повертають булеві значення. valid?повертає true, якщо збережена модель проходить усі перевірки або false, якщо вона не виконується. invalid?просто зворотнеvalid?

valid? можна використовувати так:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?

Це дасть вам можливість вирішувати будь-які проблеми перевірки до виклику save.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.