Jak zaktualizować atrybuty bez weryfikacji

136

Mam model z jego walidacjami i dowiedziałem się, że nie mogę zaktualizować atrybutu bez walidacji obiektu wcześniej.

Próbowałem już dodać on => :createskładnię na końcu każdego wiersza walidacji, ale otrzymałem te same wyniki.

Mój model ogłoszenia ma następujące walidacje:

  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

Moje zadanie prowizji wykonuje następujące czynności:

  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

Spowoduje to zgłoszenie wszystkich wyjątków walidacji dla tego modelu w danych wyjściowych.

Czy ktoś jak zaktualizować atrybut bez walidacji modelu?

Brian Roisentul
źródło

Odpowiedzi:

180

UŻYJ update_attribute zamiast update_attributes

Aktualizuje pojedynczy atrybut i zapisuje rekord bez przechodzenia przez normalną procedurę sprawdzania poprawności.

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

Uwaga: - 'update_attribute' aktualizuje tylko jeden atrybut na raz z podanego kodu, myślę, że będzie działać dla Ciebie.

Salil
źródło
9
Możesz użyć save (false) bez walidacji
Dzmitry
32
update_attributejest przestarzałe w Rails 4, FYI. Spróbuj użyć a.attributes ({...}). Save (false). Lub jeśli nie obchodzi cię (lub nie chcesz) uruchamiać wywołań zwrotnych, do kasy update_column.
Joshua Pinter
27
Dla Rails 4 save(false)nie działa, musisz użyćsave(validate: false)
Tobias Cohen,
7
@JoshPinter Hm, update_attributenie wydaje się być przestarzały w Railsach 4.2 (ma alias update_column): api.rubyonrails.org/classes/ActiveRecord/…
Tonči D.
3
@ TončiD. Wow, masz całkowitą rację. Wygląda na to, że zamierzali wycofać ją z wersji 3.2 i usunąć w wersji 4.0, ale potem zdecydowali się cofnąć swoją decyzję, ponieważ nie można jej było zastąpić update_column. Wiele może się zmienić w ciągu dwóch lat! :) Dzięki za zwrócenie uwagi. Przeczytaj więcej na ten temat tutaj: groups.google.com/forum/?hl=en&fromgroups#!topic/…
Joshua Pinter
188

Możesz zrobić coś takiego:

object.attribute = value
object.save(:validate => false)
Olivier Grimard
źródło
13
w rzeczywistości jego obiekt.save (: validate => false)
Ken Mazaika
1
Tak. object.save (: validate => false) działa dla mnie. Wielkie dzięki za podpowiedź!
Robert Reiz
1
object.attributes = hashjest trochę bardziej zgodne z pytaniem. Jeśli ktoś się dziwi, update_attributes(hash)po prostu robi self.attributes = hash; save.
Lloeki
1
object.save (false) to wszystko, co zadziała, jeśli używasz Rails 2 i
starszych
1
W ten sposób jest znacznie bardziej oczywiste dla następnego programisty, że walidacje są wyraźnie
niepożądane
82

spróbuj użyć

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

pracuje dla mnie

res
źródło
3
to jest poprawna odpowiedź z Rails 4, kombinacja wszystkich komentarzy do aktualnie zaakceptowanej odpowiedzi.
toobulkeh
33

Możesz użyć:

a.update_column :state, a.state

Sprawdź: http://apidock.com/rails/ActiveRecord/Persistence/update_column

Aktualizuje pojedynczy atrybut obiektu bez wywoływania save.

William Wong Garay
źródło
6
To najlepsze podejście, jeśli chcesz pominąć zarówno walidację, jak i wywołania zwrotne. Jest też, update_columnsjeśli chcesz zaktualizować wiele atrybutów.
Zach Colon,
8

Cała walidacja z modelu jest pomijana, gdy używamy validate: false

user = User.new(....)
user.save(validate: false)
MZaragoza
źródło
Dokładnie to, czego potrzebowałem. Uprzejmie panu dziękuję!
Ajunpreet Bambrah
-1

Nie powinno tak być

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

więc działa tylko podczas tworzenia?

Saifis
źródło
OP powiedział:I already tried to add on => :create syntax at the end of each validation line, but I got the same results.
iwasrobbed