Cómo actualizar atributos sin validación

132

Tengo un modelo con sus validaciones, y descubrí que no puedo actualizar un atributo sin validar el objeto antes.

Ya intenté agregar la on => :createsintaxis al final de cada línea de validación, pero obtuve los mismos resultados.

Mi modelo de anuncio tiene las siguientes validaciones:

  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

Mi tarea de rastrillo hace lo siguiente:

  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

Esto arroja todas las excepciones de validación para ese modelo, en la salida.

¿Alguien cómo actualizar un atributo sin validar el modelo?

Brian Roisentul
fuente

Respuestas:

177

USE update_attribute en lugar de update_attributes

Actualiza un solo atributo y guarda el registro sin pasar por el procedimiento normal de validación.

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

Nota: - 'update_attribute' actualiza solo un atributo a la vez desde el código proporcionado en cuestión, creo que funcionará para usted.

Salil
fuente
9
Puede usar guardar (falso) sin validación
Dzmitry
31
update_attributeestá en desuso en Rails 4, FYI. Intente usar a.attributes ({...}). Save (false) en su lugar. O si no le importa (o desea) que se ejecuten devoluciones de llamada, finalice la compra update_column.
Joshua Pinter
27
Para Rails 4, save(false)no funciona, debes usarsave(validate: false)
Tobias Cohen
77
@JoshPinter Hm, update_attributeno parece estar en desuso en Rails 4.2 (tiene el alias de update_column): api.rubyonrails.org/classes/ActiveRecord/…
Tonči D.
3
@ TončiD. Wow, tienes toda la razón. Parece que pretendieron desaprobarlo en 3.2 y eliminarlo en 4.0, pero luego decidieron revertir su decisión ya que no era intercambiable update_column. ¡Mucho puede cambiar en dos años! :) Gracias por mencionarlo. Lea más sobre esto aquí: groups.google.com/forum/?hl=en&fromgroups#!topic/…
Joshua Pinter
185

Puedes hacer algo como:

object.attribute = value
object.save(:validate => false)
Olivier Grimard
fuente
13
en realidad es object.save (: validate => false)
Ken Mazaika
1
Sí. object.save (: validate => false) funciona para mí. Muchas gracias por la pista!
Robert Reiz
1
object.attributes = hashestá un poco más en línea con la pregunta. Si alguien se pregunta, update_attributes(hash)solo lo hace self.attributes = hash; save.
Lloeki
1
object.save (false) es todo lo que funcionará si usa Rails 2 y
versiones
Esto es mejor porque aún ejecutaría las devoluciones de llamada que actualizan las marcas de tiempo. La operación menciona específicamente evitar validaciones, no TODAS las devoluciones de llamada.
saneshark
79

intenta usar

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

funciona para mi

res
fuente
3
Esta es la respuesta válida con Rails 4, una combinación de todos los comentarios a la respuesta actualmente aceptada.
toobulkeh
33

Puedes usar:

a.update_column :state, a.state

Verifique: http://apidock.com/rails/ActiveRecord/Persistence/update_column

Actualiza un solo atributo de un objeto, sin llamar a guardar.

William Wong Garay
fuente
66
Este es el mejor enfoque si desea omitir las validaciones y las devoluciones de llamada. También existe update_columnssi está buscando actualizar varios atributos.
Zach Colon
7

Toda la validación del modelo se omite cuando usamos validate: false

user = User.new(....)
user.save(validate: false)
MZaragoza
fuente
Exactamente lo que necesitaba. ¡Gracias buen señor!
Ajunpreet Bambrah
-1

¿No debería ser eso?

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

¿entonces solo funciona durante la creación?

Saifis
fuente
El OP dijo:I already tried to add on => :create syntax at the end of each validation line, but I got the same results.
Fui robado el