Comment mettre à jour les attributs sans validation


132

J'ai un modèle avec ses validations et j'ai découvert que je ne peux pas mettre à jour un attribut sans valider l'objet auparavant.

J'ai déjà essayé d'ajouter une on => :createsyntaxe à la fin de chaque ligne de validation, mais j'ai obtenu les mêmes résultats.

Mon modèle d'annonce a les validations suivantes:

  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

Ma tâche de râteau fait ce qui suit:

  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

Cela lève toutes les exceptions de validation pour ce modèle, dans la sortie.

Est-ce que quelqu'un comment mettre à jour un attribut sans valider le modèle?

Réponses:


177

UTILISEZ update_attribute au lieu de update_attributes

Met à jour un seul attribut et enregistre l'enregistrement sans passer par la procédure de validation normale.

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

Remarque: - 'update_attribute' ne met à jour qu'un seul attribut à la fois à partir du code donné en question, je pense que cela fonctionnera pour vous.


9
Vous pouvez utiliser save (false) sans validation
Dzmitry

31
update_attributeest obsolète dans Rails 4, FYI. Essayez d'utiliser a.attributes ({...}). Save (false) à la place. Ou si vous ne vous souciez pas (ou ne voulez pas) que les rappels soient exécutés, vérifiez update_column.
Joshua Pinter

27
Pour Rails 4, save(false)ne fonctionne pas, vous devez utilisersave(validate: false)
Tobias Cohen

7
@JoshPinter Hm, update_attributene semble pas être obsolète dans Rails 4.2 (il est aliasé comme update_column): api.rubyonrails.org/classes/ActiveRecord/…
Tonči D.

3
@ TončiD. Wow, vous avez absolument raison. Il semble qu'ils avaient l'intention de le déprécier dans la version 3.2 et de le supprimer dans la version 4.0, mais ont ensuite décidé de revenir sur leur décision car il n'était pas interchangeable avec update_column. Beaucoup de choses peuvent changer en deux ans! :) Merci de l'avoir signalé. Pour en savoir plus, cliquez ici: groups.google.com/forum/?hl=en&fromgroups#!topic/…
Joshua Pinter

185

Vous pouvez faire quelque chose comme:

object.attribute = value
object.save(:validate => false)

13
en fait son object.save (: validate => false)
Ken Mazaika

1
Oui. object.save (: validate => false) fonctionne pour moi. Merci beaucoup pour l'indication!
Robert Reiz

1
object.attributes = hashest un peu plus conforme à la question. Si quelqu'un se demande, il le fait update_attributes(hash)tout simplement self.attributes = hash; save.
Lloeki

1
object.save (false) est tout ce qui fonctionnera si vous utilisez Rails 2 et inférieurs
stevenspiel

C'est mieux car cela exécuterait toujours les rappels qui mettent à jour les horodatages. L'op mentionne spécifiquement éviter les validations, pas TOUS les rappels.
saneshark

79

essayez d'utiliser

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

travaille pour moi


3
c'est la réponse valide avec Rails 4, une combinaison de tous les commentaires à la réponse actuellement acceptée.
toobulkeh


7

Toutes les validations du modèle sont ignorées lorsque nous utilisons validate: false

user = User.new(....)
user.save(validate: false)

Exactement ce dont j'avais besoin. Merci Monsieur!
Ajunpreet Bambrah

-1

Cela ne devrait-il pas être

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

donc cela ne fonctionne que pendant la création?


L'OP a déclaré:I already tried to add on => :create syntax at the end of each validation line, but I got the same results.
iwasrobbed le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.