Rails: update_attribute vs update_attributes

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

Kedua hal ini akan memperbarui objek tanpa harus secara eksplisit memberi tahu AR untuk memperbarui.

API Rails mengatakan:

untuk update_attribute

Memperbarui atribut tunggal dan menyimpan catatan tanpa melalui prosedur validasi normal. Ini sangat berguna untuk bendera boolean pada catatan yang ada. Metode update_attribute reguler di Base diganti dengan ini ketika modul validasi dicampur, yang secara default.

untuk update_attributes

Memperbarui semua atribut dari Hash yang dilewatkan dan menyimpan catatan. Jika objek tidak valid, penyimpanan akan gagal dan false akan dikembalikan.

Jadi jika saya tidak ingin objek divalidasi saya harus menggunakan update_attribute. Bagaimana jika saya memiliki pembaruan ini pada before_save, apakah itu stackoverflow?

Pertanyaan saya adalah apakah update_attribute juga memotong sebelum menyimpan atau hanya validasi.

Juga, apa sintaks yang benar untuk mengirimkan hash ke update_attributes ... lihat contoh saya di atas.

thenengah
sumber
Mengapa Anda ingin memasukkan update_attributepernyataan ke dalam before_savecallback? Saya tidak bisa memikirkan alasan yang bagus untuk ini.
Daniel Pietzsch
1
Saya memiliki objek yang perlu diperbarui berdasarkan jumlah objek yang diperbarui. Apa cara yang lebih baik?
thenengah
Apakah saya benar, bahwa objek yang Anda perlu perbarui adalah atribut dari objek yang Anda simpan? Jika ya, maka Anda bisa mengaturnya, dan mereka akan diperbarui bersama dengan objek yang disimpan (karena mereka diatur dalam before_savepanggilan balik). Fe bukannya update_attribute(:discount, 0.1) if amount > 100Anda bisa lakukan discount = 0.1 if amount > 100. update_attributepanggilan savepada objek, yang tidak perlu dalam kasus ini, karena pernyataan itu ada di dalam before_savepanggilan balik dan akan tetap disimpan. Saya harap itu masuk akal.
Daniel Pietzsch
Iya dan tidak. Namun, status objek yang Anda maksud bergantung pada kondisi lain yang tidak dapat diproses sebelum penyimpanan.
thenengah
3
sebagai catatan, metode ini melewatkan validasi tetapi masih akan melakukan panggilan balik, seperti after_save ...
rogerdpack

Jawaban:

328

Silakan merujuk update_attribute. Pada mengklik sumber acara Anda akan mendapatkan kode berikut

      # 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

dan sekarang merujuk update_attributesdan melihat kodenya yang Anda dapatkan

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

perbedaan antara keduanya adalah update_attributekegunaan save(false)sedangkan update_attributeskegunaan saveatau bisa dikatakan save(true).

Maaf untuk deskripsi panjang tapi yang ingin saya katakan adalah penting. save(perform_validation = true), jika perform_validationsalah ia mem-bypass (melompati akan menjadi kata yang tepat) semua validasi yang terkait dengannya save.

Untuk pertanyaan kedua

Juga, apa sintaks yang benar untuk mengirimkan hash ke update_attributes ... lihat contoh saya di atas.

Contoh Anda benar.

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

atau

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

atau jika Anda mendapatkan semua data bidang & nama dalam hash katakan di params[:user]sini gunakan saja

Object.update_attributes(params[:user])
Salil
sumber
7
Pernyataan Anda tentang panggilan balik salah, setidaknya dalam Rails 3. Ia mengatakan dengan sangat jelas di komentar di sumber bahwa "Callback dipanggil".
Batkins
Saya kedua apa yang @Batkins katakan
Raf
3
@Batkins masih validasi tidak berjalan - itu bagian paling penting :)
Tigraine
1
Tautan di atas tidak lagi akurat setidaknya pada Rails 5.1 . Metode-metode ini dipindahkan ke ActiveRecord :: Persistence. Anda dapat menemukan info yang diperbarui di sini: atribut pembaruan dan di sini update_attributes Catatan: update_attributessekarang adalah alias untukupdate
tgf
74

Kiat: update_attribute sedang tidak digunakan lagi dalam Rails 4 melalui Commit a7f4b0a1 . Itu menghapus update_attributemendukung update_column.

Mat
sumber
45
Ini tidak lagi benar; metode telah ditambahkan kembali. Lihat github.com/rails/rails/pull/6738#issuecomment-39584005
Dennis
20
update_attributemelompati validasi, tetapi menghormati callback, update_columnakan melewati validasi dan callback dan tidak memperbarui :updated_at, updateadalah fungsi normal yang akan menghormati callback dan validasi
Mohammad AbuShady
2
apakah mereka sudah mengambil keputusan? reset_column, perbarui_column juga ditinggalkan.
ahnbizcad
2
update_columntidak ditinggalkan, tetapi update_columns(name: value)disukai. reset_columntelah dihapus.
onebree
15

update_attribute

Metode ini memperbarui atribut objek tunggal tanpa memohon validasi berbasis model.

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

update_attributes

Metode ini memperbarui beberapa atribut objek tunggal dan juga lulus validasi berbasis model.

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

Semoga jawaban ini akan menjelaskan kapan harus menggunakan metode rekaman aktif apa.

Balachandar1887229
sumber
12

Yang juga perlu diperhatikan adalah bahwa dengan update_attribute, atribut yang diinginkan untuk diperbarui tidak perlu dicantumkan dengan putih attr_accessibleuntuk memperbaruinya sebagai lawan dari metode penugasan massal update_attributesyang hanya akan memperbarui attr_accessibleatribut yang ditentukan.

Kibet Yegon
sumber
8

update_attributecukup hanya memperbarui satu atribut dari suatu model, tetapi kita dapat melewatkan beberapa atribut dalam update_attributesmetode.

Contoh:

user = User.last

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

Itu lulus validasi

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

itu tidak diperbarui jika validasi gagal.

Shoaib Malik
sumber
Sangat dijelaskan. Terima kasih!
Diego Somar
6

Jawaban yang bagus perhatikan bahwa untuk ruby ​​1.9 dan di atas Anda bisa (dan saya pikir harus) menggunakan sintaks hash baru untuk update_attributes:

Model.update_attributes(column1: "data", column2: "data")
Ziv Galili
sumber
6

Anda mungkin tertarik mengunjungi posting blog ini mengenai semua cara yang memungkinkan untuk menetapkan atribut atau memperbarui catatan (diperbarui ke Rails 4) update_attribute, update, update_column, update_columns etc. http://www.davidverhasselt.com/set-attributes-in-activerecord/ . Misalnya itu berbeda dalam aspek seperti menjalankan validasi, menyentuh updated_at objek atau memicu panggilan balik.

Sebagai jawaban untuk pertanyaan OP update_attributetidak melalui panggilan balik.

adamliesko
sumber
Ya, saya memodifikasi jawabannya. Terima kasih untuk umpan baliknya.
adamliesko
4

update_attributedan update_attributesserupa, tetapi dengan satu perbedaan besar: update_attribute tidak menjalankan validasi.

Juga:

  • update_attributedigunakan untuk memperbarui catatan dengan atribut tunggal .

    Model.update_attribute(:column_name, column_value1)
  • update_attributes digunakan untuk memperbarui catatan dengan banyak atribut.

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

Kedua metode ini sangat mudah membingungkan mengingat nama dan karya mereka yang serupa. Oleh karena itu, update_attributesedang dihapus demi update_column.

Sekarang di Rails4 Anda dapat menggunakannya Model.update_column(:column_name, column_value)di tempatModel.update_attribute(:column_name, column_value)

Klik di sini untuk mendapatkan info lebih lanjut tentang update_column.

uma
sumber
4

Untuk menjawab pertanyaan Anda, update_attributelewati pra simpan "validasi" tetapi masih menjalankan panggilan balik lainnya sepertiafter_save dll. Jadi, jika Anda benar-benar ingin "perbarui kolom dan lewati saja pengarsipan AR" maka Anda perlu menggunakan (tampaknya)

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

rogerdpack
sumber
2

Baru-baru ini saya bertemu update_attributevsupdate_attributes dan validasi, nama yang sangat mirip, perilaku yang berbeda, sangat membingungkan.

Untuk lulus update_attributevalidasi hash ke dan memotong, Anda dapat melakukan:

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

Saya pikir pertanyaan Anda adalah apakah memiliki update_attribute di before_save akan mengarah ke dan loop tanpa akhir (dari panggilan update_attribute di before_save panggilan balik, awalnya dipicu oleh panggilan update_attribute)

Saya cukup yakin itu memotong callback before_save karena tidak benar-benar menyimpan catatan. Anda juga dapat menyimpan catatan tanpa memicu validasi dengan menggunakan

Model.save false

concept47
sumber