Raylar: update_attribute ve update_attributes


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

Her ikisi de bir nesneyi açıkça AR'ye güncellemesini bildirmek zorunda kalmadan güncelleyecektir.

Rails API diyor:

update_attribute için

Tek bir özelliği günceller ve normal doğrulama prosedüründen geçmeden kaydı kaydeder. Bu özellikle mevcut kayıtlardaki boole bayrakları için kullanışlıdır. Base'deki normal update_attribute yöntemi, varsayılan olarak onaylama modülü karıştırıldığında bununla değiştirilir.

update_attributes için

Aktarılan Karma öğesindeki tüm öznitelikleri günceller ve kaydı kaydeder. Nesne geçersizse, kayıt başarısız olur ve false döndürülür.

Nesnenin doğrulanmasını istemiyorsam update_attribute kullanmalıyım. Bu güncelleştirmeyi bir önceki_kaydımda varsa, yığın akışı olacak mı?

Benim sorum update_attribute da önce kaydetmek veya sadece doğrulama atlamak olduğunu.

Ayrıca, update_attributes öğesine bir karma iletmek için doğru sözdizimi nedir ... üstteki örneğime göz atın.


Neden geri aramanın içine bir update_attributeifade koymak istiyorsunuz before_save? Bunun için iyi bir neden düşünemiyorum.
Daniel Pietzsch

1
Güncellenen nesnenin miktarına göre güncellenmesi gereken nesneler var. Daha iyi bir yol nedir?
thenengah

Güncellemeniz gereken nesnelerin kaydettiğiniz nesnenin nitelikleri olması doğru mudur? Eğer evet ise, o zaman onları ayarlayabilirsiniz, ve yine de kaydedilen nesne ile birlikte güncellenecektir (çünkü onlar bir before_savegeri arama içinde ayarlanır ). update_attribute(:discount, 0.1) if amount > 100Senin yerine Fe yapabilirdi discount = 0.1 if amount > 100. ifade bir geri arama içinde olduğundan ve yine de kaydedilecektir , bu durumda gereksiz olan nesne üzerinde update_attributeçağırır . Umarım bu mantıklıdır. savebefore_save
Daniel Pietzsch

Evet ve hayır. Ancak, başvurduğunuz nesnelerin durumu, kaydetmeden önce işlenemeyen diğer koşullara bağlıdır.
thenengah

3
not olarak, bu yöntemler doğrulamayı atlar, ancak
after_save

Yanıtlar:


328

Lütfen bakın update_attribute. Şov kaynağını tıkladığınızda aşağıdaki kodu alırsınız

      # 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

ve şimdi update_attributesaldığınız koduna bakın ve bakın

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

ikisi arasındaki fark update_attributekullanımlarıdır, save(false)oysa update_attributeskullanır saveya da söyleyebilirsiniz save(true).

Uzun açıklama için özür dilerim ama söylemek istediğim önemli. save(perform_validation = true), perform_validationyanlışsa, ilgili tüm doğrulamaları atlar (atlar doğru kelime olur) save.

İkinci soru için

Ayrıca, update_attributes öğesine bir karma iletmek için doğru sözdizimi nedir ... üstteki örneğime göz atın.

Örneğiniz doğrudur.

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

veya

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

veya bir karma içindeki tüm alanların verilerini ve adını alırsanız, params[:user]burada kullanın

Object.update_attributes(params[:user])

7
Geri aramalarla ilgili ifadeniz yanlış, en azından Rails 3. Kaynaktaki yorumlarda açıkça "Geri aramalar başlatıldığını" söylüyor .
Batkins

@Batkins ne diyor ikinci
Raf

3
@Batkins hala doğrulama yapılmıyor - bu en önemli kısım :)
Tigraine

1
Yukarıdaki bağlantılar en azından Rails 5.1'den itibaren doğru değildir . Bu yöntemler ActiveRecord :: Persistence klasörüne taşındı. Güncellenen bilgileri burada bulabilirsiniz: update özniteliği ve burada update_attributes Not: update_attributesşimdiupdate
tgf

74

İpucu: a7f4b0a1 taahhüdü ileupdate_attribute Rails 4'te kullanımdan kaldırılıyor . Lehine kaldırır .update_attributeupdate_column


45
Bu artık doğru değil; yöntem yeniden eklendi. Bkz. Github.com/rails/rails/pull/6738#issuecomment-39584005
Dennis

20
update_attributedoğrulamayı atlar, ancak geri çağrılara saygı gösterir, update_columnhem doğrulama hem de geri çağrıları atlar ve güncelleme olmaz :updated_at, updatehem geri çağrılara hem de doğrulamaya saygı duyacak normal bir işlevdir
Mohammad AbuShady

2
zaten zihinlerini telafi edecekler mi? reset_column, update_column da kullanımdan kaldırıldı.
ahnbizcad

2
update_columnkullanımdan kaldırılmış değil update_columns(name: value), tercih ediliyor. reset_columnKaldırıldı.
onebree

15

update_attribute

Bu yöntem, modele dayalı doğrulamayı başlatmadan nesnenin tek özniteliğini güncelleştirir.

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

update_attributes

Bu yöntem, tek bir nesnenin çoklu özniteliğini günceller ve model tabanlı doğrulamayı da geçirir.

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

Umarım bu cevap ne zaman aktif kayıt yöntemini kullanacağını temizler.


12

Ayrıca , sadece belirtilen nitelikleri güncelleyecek toplu atama yönteminin aksine, güncellenmesi update_attributeistenen özniteliğin beyaz listeye alınması gerekmediğidir .attr_accessibleupdate_attributesattr_accessible


8

update_attributebir modelin yalnızca bir özelliğini günceller, ancak update_attributesyöntemde birden çok özelliği geçirebiliriz .

Misal:

user = User.last

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

Doğrulamayı geçiyor

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

doğrulama başarısız olursa güncellenmez.


Çok iyi açıkladı. Teşekkürler!
Diego Somar

6

Harika cevaplar. ruby 1.9 ve üzeri gelince update_attributes için yeni karma sözdizimini kullanabilirsiniz (ve bence gerekir):

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

6

Bir özellik veya güncelleme kaydı (Rails 4'e güncellenmiştir) atamanın tüm olası yollarıyla ilgili olarak bu blog yayınını ziyaret etmek isteyebilirsiniz update_attribute, update, update_column, update_columns etc. http://www.davidverhasselt.com/set-attributes-in-activerecord/ . Örneğin, doğrulamaların çalıştırılması, nesnenin updated_at değerine dokunulması veya geri çağrıların tetiklenmesi gibi unsurlarda farklılık gösterir.

OP sorusuna bir cevap olarak update_attributegeri aramalar geçmez.


Evet, cevabı değiştirdim. Geri dönüşünüz için teşekkür ederiz.
adamliesko

4

update_attributeve update_attributesbenzerdir, ancak büyük bir fark vardır: doğrulama update_attribute yapmaz .

Ayrıca:

  • update_attributekaydı tek özellikle güncellemek için kullanılır .

    Model.update_attribute(:column_name, column_value1)
  • update_attributeskaydı birden çok özelliğe sahip güncellemek için kullanılır .

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

Bu iki yöntemin benzer isimleri ve çalışmaları göz önüne alındığında karıştırılması gerçekten kolaydır. Bu nedenle update_attributelehine kaldırılıyor update_column.

Şimdi, Rails4'teModel.update_column(:column_name, column_value) şu yerde kullanabilirsiniz :Model.update_attribute(:column_name, column_value)

Hakkında daha fazla bilgi almak için buraya tıklayınupdate_column .


4

Sorunuzu cevaplamak için, update_attribute"doğrulamaları" önceden kaydettirir , ancak yine de after_savevb. Gibi diğer geri çağrıları çalıştırır . Dolayısıyla, gerçekten "sadece sütunu güncelleyin ve herhangi bir AR hamlesini atlayın" istiyorsanız, (görünüşte) kullanmanız gerekir.

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


2

Son zamanlarda update_attributevs. update_attributesve doğrulama sorunuyla karşılaştım, benzer isimler, çok farklı davranışlar, çok kafa karıştırıcı.

update_attributeDoğrulamayı geçmek ve doğrulamayı atlamak için şunları yapabilirsiniz:

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

1

Bence senin sorunun bir before_save bir update_attribute sahip olması ve sonsuz döngü (başlangıçta bir update_attribute çağrısı tarafından tetiklenen, önceki_save geri aramalarda update_attribute çağrıları) neden olacak olduğunu düşünüyorum

Kayıt gerçekten kaydetmediği için before_save geri aramayı atladığından eminim. Ayrıca, kullanarak onayları tetiklemeden bir kaydı da kaydedebilirsiniz

Model. Yanlış kaydet

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.