So aktualisieren Sie Attribute ohne Validierung

131

Ich habe ein Modell mit seinen Validierungen und habe festgestellt, dass ich ein Attribut nicht aktualisieren kann, ohne das Objekt zuvor zu validieren.

Ich habe bereits versucht, on => :createam Ende jeder Validierungszeile eine Syntax hinzuzufügen , aber ich habe die gleichen Ergebnisse erhalten.

Mein Ankündigungsmodell hat folgende Validierungen:

  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

Meine Rechenaufgabe erledigt Folgendes:

  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

Dadurch werden alle Validierungsausnahmen für dieses Modell in der Ausgabe ausgelöst.

Kann jemand ein Attribut aktualisieren, ohne das Modell zu validieren?

Brian Roisentul
quelle

Antworten:

176

USE update_attribute statt update_attributes

Aktualisiert ein einzelnes Attribut und speichert den Datensatz, ohne das normale Validierungsverfahren durchlaufen zu haben.

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

Hinweis: - 'update_attribute' aktualisiert jeweils nur ein Attribut aus dem fraglichen Code. Ich denke, es wird für Sie funktionieren.

Salil
quelle
9
Sie können save (false) ohne Validierung verwenden
Dzmitry
31
update_attributeist in Rails 4, FYI, veraltet. Versuchen Sie stattdessen, a.attributes ({...}). Save (false) zu verwenden. Oder wenn Sie keine Rückrufe ausführen möchten (oder möchten), checken Sie aus update_column.
Joshua Pinter
27
Für Rails 4, save(false)funktioniert nicht, müssen Sie verwendensave(validate: false)
Tobias Cohen
7
@JoshPinter Hm, update_attributescheint in Rails 4.2 nicht veraltet zu sein (es wird als Alias ​​bezeichnet update_column): api.rubyonrails.org/classes/ActiveRecord/…
Tonči D.
3
@ TončiD. Wow, du bist absolut richtig. Es sieht so aus, als wollten sie es in 3.2 verwerfen und in 4.0 entfernen, entschieden sich dann aber, ihre Entscheidung umzukehren, da es nicht austauschbar war mit update_column. In zwei Jahren kann sich viel ändern! :) Danke, dass du darauf hingewiesen hast. Lesen Sie hier mehr darüber: groups.google.com/forum/?hl=de&fromgroups#!topic/…
Joshua Pinter
185

Sie können so etwas tun wie:

object.attribute = value
object.save(:validate => false)
Olivier Grimard
quelle
13
eigentlich sein object.save (: validate => false)
Ken Mazaika
1
Ja. object.save (: validate => false) funktioniert bei mir. Vielen Dank für den Hinweis!
Robert Reiz
1
object.attributes = hashist ein bisschen mehr im Einklang mit der Frage. Wenn sich jemand wundert, update_attributes(hash)tut er es nur self.attributes = hash; save.
Lloeki
1
object.save (false) ist alles, was bei Verwendung von Rails 2 und darunter
funktioniert
Dies ist besser, da weiterhin die Rückrufe ausgeführt werden, mit denen Zeitstempel aktualisiert werden. In der Operation wird ausdrücklich erwähnt, dass Validierungen vermieden werden und nicht ALLE Rückrufe.
Saneshark
79

versuchen Sie es mit

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

funktioniert bei mir

res
quelle
3
Dies ist die gültige Antwort mit Rails 4, einer Kombination aller Kommentare zur aktuell akzeptierten Antwort.
Toobulkeh
33

Sie können verwenden:

a.update_column :state, a.state

Überprüfen Sie: http://apidock.com/rails/ActiveRecord/Persistence/update_column

Aktualisiert ein einzelnes Attribut eines Objekts, ohne save aufzurufen.

William Wong Garay
quelle
6
Dies ist der beste Ansatz, wenn Sie sowohl Überprüfungen als auch Rückrufe überspringen möchten. Dies gilt auch, update_columnswenn Sie mehrere Attribute aktualisieren möchten.
Zach Colon
7

Die gesamte Validierung des Modells wird bei Verwendung übersprungen validate: false

user = User.new(....)
user.save(validate: false)
MZaragoza
quelle
Genau das, was ich brauchte. Ich danke Ihnen lieber Herr!
Ajunpreet Bambrah
-1

Sollte das nicht sein

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

also funktioniert es nur beim erstellen?

Saifis
quelle
Das OP sagte:I already tried to add on => :create syntax at the end of each validation line, but I got the same results.
iwasrobbed