Szyny: atrybut_aktualizacji vs atrybut_aktualizacji


255
Object.update_attribute(:only_one_field, "Some Value")
Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

Oba z nich zaktualizują obiekt bez konieczności jawnego informowania AR o aktualizacji.

Rails API mówi:

dla update_attribute

Aktualizuje pojedynczy atrybut i zapisuje rekord bez przechodzenia przez normalną procedurę sprawdzania poprawności. Jest to szczególnie przydatne w przypadku flag boolowskich w istniejących rekordach. Zwykła metoda update_attribute w Base jest zastępowana tą, gdy dodaje się moduł sprawdzania poprawności, co jest domyślnie.

dla update_attributes

Aktualizuje wszystkie atrybuty z przekazanego skrótu i ​​zapisuje rekord. Jeśli obiekt jest nieprawidłowy, zapisywanie zakończy się niepowodzeniem, a false zostanie zwrócony.

Więc jeśli nie chcę, aby obiekt został sprawdzony, powinienem użyć update_attribute. Co się stanie, jeśli będę mieć tę aktualizację przed zapisaniem, czy zostanie ona przepełniona?

Moje pytanie brzmi, czy update_attribute omija również przed zapisaniem lub po prostu sprawdzanie poprawności.

Jaka jest poprawna składnia, aby przekazać skrót do update_attributes ... sprawdź mój przykład na górze.


Dlaczego chcesz umieścić update_attributeoświadczenie w before_savewywołaniu zwrotnym? Nie mogę wymyślić dobrego powodu.
— Daniel Pietzsch

1
Mam obiekty, które muszą zostać zaktualizowane na podstawie ilości zaktualizowanego obiektu. Jaki jest lepszy sposób?
— thenengah

Czy mam rację, że obiekty, które musisz zaktualizować, są atrybutami obiektu, który zapisujesz? Jeśli tak, możesz po prostu je ustawić, a one i tak zostaną zaktualizowane wraz z obiektem, który jest zapisany (ponieważ są ustawione w ramach before_savewywołania zwrotnego). Fe zamiast update_attribute(:discount, 0.1) if amount > 100ciebie mógł zrobić discount = 0.1 if amount > 100. update_attributewywołuje saveobiekt, co w tym przypadku nie jest konieczne, ponieważ instrukcja znajduje się w before_savewywołaniu zwrotnym i zostanie zapisana. Mam nadzieję, że to ma sens.
— Daniel Pietzsch,

Tak i nie. Jednak stan obiektów, do których się odwołujesz, zależy od innych warunków, których nie można przetworzyć przed zapisaniem.
— thenengah

3
Uwaga: metody te pomijają sprawdzanie poprawności, ale nadal wykonują wywołania zwrotne, takie jak after_save ...
— rogerdpack

Odpowiedzi:


328

Proszę odnieść się do update_attribute. Po kliknięciu pokaż źródło otrzymasz następujący kod

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2614
2614:       def update_attribute(name, value)
2615:         send(name.to_s + '=', value)
2616:         save(false)
2617:       end

a teraz polecaj update_attributesi spójrz na otrzymany kod

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2621
2621:       def update_attributes(attributes)
2622:         self.attributes = attributes
2623:         save
2624:       end

różnica między nimi to update_attributezastosowania, save(false)podczas gdy update_attributeszastosowania savelub można powiedzieć save(true).

Przepraszam za długi opis, ale to, co chcę powiedzieć, jest ważne. save(perform_validation = true), jeśli perform_validationjest fałszem, pomija (pominięcie będzie właściwym słowem) wszystkie walidacje związane z save.

Na drugie pytanie

Jaka jest poprawna składnia, aby przekazać skrót do update_attributes ... sprawdź mój przykład na górze.

Twój przykład jest poprawny.

Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

lub

Object.update_attributes :field1 => "value", :field2 => "value2", :field3 => "value3"

lub jeśli dostaniesz wszystkie pola danych i nazwę w haszu, powiedz params[:user]tutaj użyj just

Object.update_attributes(params[:user])

7
Twoje oświadczenie o oddzwanianiu jest nieprawidłowe, przynajmniej w Rails 3. W komentarzach w źródle jest napisane bardzo wyraźnie, że „wywoływane są wywołania zwrotne”.
— Batkins

Popieram to, co mówi @Batkins
— Raf

3
@Batkins nadal nie są sprawdzane - to jest najważniejsza część :)
— Tigraine,

1
Powyższe linki nie są już dokładne, przynajmniej od wersji 5.1 . Metody te zostały przeniesione do ActiveRecord :: Persistence. Zaktualizowaną informację można znaleźć tutaj: atrybut aktualizacji i tutaj aktualizacja_atrybuty Uwaga: update_attributesjest teraz aliasem dlaupdate
— tgf

74

Wskazówka: update_attribute jest przestarzałe w Railsach 4 przez Commit a7f4b0a1 . Usuwa update_attributena korzyść update_column.


45
To już nie jest prawda; metoda została ponownie dodana. Zobacz github.com/rails/rails/pull/6738#issuecomment-39584005
— Dennis

20
update_attributepomija sprawdzanie poprawności, ale szanuje wywołania zwrotne, update_columnpomija sprawdzanie poprawności i wywołania zwrotne oraz nie aktualizuje :updated_at, updatejest normalną funkcją, która będzie respektować zarówno wywołania zwrotne, jak i sprawdzanie poprawności
— Mohammad AbuShady

2
czy już zdecydują. reset_column, update_column również jest przestarzałe.
— ahnbizcad

2
update_columnnie jest przestarzałe, ale update_columns(name: value)jest uprzywilejowane. reset_columnzostało usunięte.
— onebree

15

update_attribute

Ta metoda aktualizuje pojedynczy atrybut obiektu bez wywoływania sprawdzania poprawności na podstawie modelu.

obj = Model.find_by_id(params[:id])
obj.update_attribute :language, “java”

aktualizacja_atrybutów

Ta metoda aktualizuje wiele atrybutów pojedynczego obiektu, a także przekazuje sprawdzanie poprawności na podstawie modelu.

attributes = {:name => “BalaChandar”, :age => 23}
obj = Model.find_by_id(params[:id])
obj.update_attributes(attributes)

Mam nadzieję, że ta odpowiedź wyjaśni, kiedy użyć jakiej metody aktywnego zapisu.


12

Warto również zauważyć, że za pomocą update_attribute, żądany atrybut do aktualizacji nie musi znajdować się na białej liście, attr_accessibleaby go zaktualizować, w przeciwieństwie do metody przypisywania masy, update_attributesktóra aktualizuje tylko attr_accessibleokreślone atrybuty.


8

update_attributepo prostu aktualizuje tylko jeden atrybut modelu, ale możemy przekazać wiele atrybutów update_attributesmetodą.

Przykład:

user = User.last

#update_attribute
user.update_attribute(:status, "active")

Przeszedł walidację

#update_attributes
user.update_attributes(first_name: 'update name', status: "active")

nie aktualizuje się, jeśli sprawdzanie poprawności się nie powiedzie.


Bardzo dobrze wyjaśnione. Dzięki!
— Diego Somar

6

Świetne odpowiedzi. zauważ, że jak w Ruby 1.9 i nowszych, możesz (i myślę, że powinien) użyć nowej składni skrótu dla update_attributes:

Model.update_attributes(column1: "data", column2: "data")

6

Możesz być zainteresowany odwiedzeniem tego postu na blogu, dotyczącym wszystkich możliwych sposobów przypisania atrybutu lub aktualizacji rekordu (zaktualizowanego do wersji Rails 4) update_attribute, update, update_column, update_columns etc. http://www.davidverhasselt.com/set-attributes-in-activerecord/ . Na przykład różni się aspektami, takimi jak uruchamianie sprawdzania poprawności, dotykanie obiektu updated_at obiektu lub wyzwalanie wywołań zwrotnych.

Jako odpowiedź na pytanie PO update_attributenie przekazuje oddzwaniania.


Tak, zmodyfikowałem odpowiedź. Dziękujemy za opinię.
— adamliesko

4

update_attributei update_attributessą podobne, ale z jedną dużą różnicą: update_attribute nie przeprowadza walidacji.

Również:

  • update_attributesłuży do aktualizacji rekordu za pomocą jednego atrybutu.

    Model.update_attribute(:column_name, column_value1)
  • update_attributessłuży do aktualizacji rekordu z wieloma atrybutami.

    Model.update_attributes(:column_name1 => column_value1, :column_name2 => column_value2, ...)

Te dwie metody są naprawdę łatwe do pomylenia, biorąc pod uwagę ich podobne nazwy i prace. Dlatego update_attributejest usuwany na korzyśćupdate_column .

Teraz w Rails4 możesz używać Model.update_column(:column_name, column_value)zamiastModel.update_attribute(:column_name, column_value)

Kliknij tutaj, aby uzyskać więcej informacji na temat update_column.


4

Aby odpowiedzieć na twoje pytanie, update_attributepomiń wcześniej „sprawdzanie poprawności”, ale nadal uruchamia inne wywołania zwrotne, takie jak after_saveitp. Więc jeśli naprawdę chcesz „po prostu zaktualizować kolumnę i pominąć dowolne cruft AR”, musisz użyć (najwyraźniej)

Model.update_all(...)patrz https://stackoverflow.com/a/7243777/32453


2

Ostatnio wpadłem na update_attributevs. update_attributesemisyjna walidacji, więc podobne nazwy, więc różne zachowania, więc mylące.

Aby przekazać skrót update_attributei pominąć sprawdzanie poprawności, możesz:

object = Object.new
object.attributes = {
  field1: 'value',
  field2: 'value2',
  field3: 'value3'
}
object.save!(validate: false)

1

Myślę, że twoje pytanie dotyczy tego, czy posiadanie atrybutu update_attave w zapisie before_save doprowadzi do niekończącej się pętli (wywołań update_attribute w wywołaniach zwrotnych before_save, pierwotnie wywołanych wywołaniem update_attribute)

Jestem prawie pewien, że omija wywołanie zwrotne before_save, ponieważ tak naprawdę nie zapisuje rekordu. Możesz także zapisać rekord bez uruchamiania sprawdzania poprawności za pomocą

Model.save false

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.