Как обновить атрибуты без проверки

132

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

Я уже пытался добавить on => :createсинтаксис в конец каждой строки проверки, но получил те же результаты.

Моя модель объявления имеет следующие проверки:

  validates_presence_of :title
  validates_presence_of :description
  validates_presence_of :announcement_type_id

  validate :validates_publication_date
  validate :validates_start_date
  validate :validates_start_end_dates
  validate :validates_category
  validate :validates_province

  validates_length_of :title, :in => 6..255, :on => :save
  validates_length_of :subtitle, :in => 0..255, :on => :save
  validates_length_of :subtitle, :in => 0..255, :on => :save
  validates_length_of :place, :in => 0..50, :on => :save

  validates_numericality_of :vacants, :greater_than_or_equal_to => 0,  :only_integer => true
  validates_numericality_of :price, :greater_than_or_equal_to => 0,  :only_integer => true

Моя задача по граблям делает следующее:

  task :announcements_expiration => :environment do
    announcements = Announcement.expired

    announcements.each do |a|
      #Gets the user that owns the announcement
      user = User.find(a.user_id)
      puts a.title + '...'

      a.state = 'deactivated'

      if a.update_attributes(:state => a.state)
        puts 'state changed to deactivated'
      else
        a.errors.each do |e|
          puts e
        end

      end
    end

Это вызывает все исключения проверки для этой модели на выходе.

Кто-нибудь, как обновить атрибут без проверки модели?

Брайан Ройзентул
источник

Ответы:

177

ИСПОЛЬЗУЙТЕ update_attribute вместо update_attributes

Обновляет один атрибут и сохраняет запись без прохождения обычной процедуры проверки.

if a.update_attribute('state', a.state)

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

Salil
источник
9
Вы можете использовать save (false) без проверки
Дмитрий
31
update_attributeустарела в Rails 4, к вашему сведению. Попробуйте вместо этого использовать a.attributes ({...}). Save (false). Или, если вам все равно (или вы хотите), чтобы выполнялись обратные вызовы, оформляйте заказ update_column.
Джошуа Пинтер
27
Для Rails 4 save(false)не работает, вы должны использоватьsave(validate: false)
Тобиас Коэн
7
@JoshPinter Хм, update_attributeпохоже, не устарел в Rails 4.2 (он имеет псевдоним update_column): api.rubyonrails.org/classes/ActiveRecord/…
Тончи Д.
3
@ TončiD. Вау, вы абсолютно правы. Похоже, они намеревались исключить его в версии 3.2 и удалить в 4.0, но затем решили отменить свое решение, поскольку оно не было взаимозаменяемым update_column. За два года многое может измениться! :) Спасибо, что указали на это. Подробнее об этом читайте
Джошуа Пинтер,
185

Вы можете сделать что-то вроде:

object.attribute = value
object.save(:validate => false)
Оливье Гримар
источник
13
на самом деле его object.save (: validate => false)
Кен Мазайка
1
Ага. object.save (: validate => false) у меня работает. Большое спасибо за подсказку!
Роберт Рейз
1
object.attributes = hashнемного больше соответствует вопросу. Если кому интересно, update_attributes(hash)просто делает self.attributes = hash; save.
Lloeki
1
object.save (false) - это все, что будет работать при использовании Rails 2 и ниже
stevenspiel
Это лучше, потому что он все равно будет выполнять обратные вызовы, обновляющие временные метки. В op особо упоминается отказ от проверок, а не ВСЕ обратные вызовы.
saneshark
79

попробуйте использовать

@record.assign_attributes({ ... })
@record.save(validate: false)

работает для меня

Рез
источник
3
это правильный ответ с Rails 4, комбинация всех комментариев к принятому в настоящее время ответу.
toobulkeh 09
33

Вы можете использовать:

a.update_column :state, a.state

Проверить: http://apidock.com/rails/ActiveRecord/Persistence/update_column

Обновляет отдельный атрибут объекта без вызова save.

Уильям Вонг Гарай
источник
6
Это лучший подход, если вы хотите пропустить как проверки, так и обратные вызовы. Также есть, update_columnsесли вы хотите обновить несколько атрибутов.
Zach Colon
7

Все проверки модели пропускаются, когда мы используем validate: false

user = User.new(....)
user.save(validate: false)
MZaragoza
источник
Именно то, что мне было нужно. Спасибо, добрый сэр!
Ajunpreet Bambrah
-1

Разве это не должно быть

validates_length_of :title, :in => 6..255, :on => :create

так это работает только во время создания?

Saifis
источник
ОП сказал:I already tried to add on => :create syntax at the end of each validation line, but I got the same results.
Меня ограбили