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.