Saya memiliki beberapa model yang memiliki panggilan balik after_save. Biasanya itu bagus, tetapi dalam beberapa situasi, seperti ketika membuat data pengembangan, saya ingin menyimpan model tanpa menjalankan callback. Apakah ada cara sederhana untuk melakukan itu? Sesuatu yang mirip ...
Person#save( :run_callbacks => false )
atau
Person#save_without_callbacks
Saya mencari di Rails docs dan tidak menemukan apa pun. Namun dalam pengalaman saya Rails docs tidak selalu menceritakan keseluruhan cerita.
MEMPERBARUI
Saya menemukan posting blog yang menjelaskan bagaimana Anda dapat menghapus callback dari model seperti ini:
Foo.after_save.clear
Saya tidak dapat menemukan di mana metode itu didokumentasikan tetapi tampaknya berhasil.
Foo.after_save.clear
menghapus callback untuk seluruh model? Lalu bagaimana Anda mengusulkan untuk mengembalikannya?Jawaban:
Solusi ini hanya untuk Rails 2.
Saya baru saja menyelidiki ini dan saya pikir saya punya solusi. Ada dua metode pribadi ActiveRecord yang dapat Anda gunakan:
Anda harus menggunakan kirim untuk memanggil metode ini. contoh:
Ini jelas sesuatu yang hanya ingin Anda gunakan di konsol atau saat melakukan beberapa tes acak. Semoga ini membantu!
sumber
Gunakan
update_column
(Rails> = v3.1) atauupdate_columns
(Rails> = 4.0) untuk melewati panggilan balik dan validasi. Juga dengan metode ini,updated_at
adalah tidak diperbarui.http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column
# 2: Melewati panggilan balik yang juga berfungsi saat membuat objek
sumber
:create_without_callbacks
:( Bagaimana saya bisa menjalankan sesuatu yang mirip dengan itu? (Bekerja di Rails2, dihapus di@person
adalah variabel di controller di suatu tempat, solusi ini berarti bahwa orang yang membaca kelas model Anda tidak akan dapat memahami callback. Mereka akan melihatafter_create :something_cool
dan akan berpikir "hebat, sesuatu yang keren terjadi setelah membuat!". Untuk benar-benar memahami kelas model Anda, mereka harus memeriksa semua pengontrol Anda, mencari semua tempat kecil di mana Anda telah memutuskan untuk menyuntikkan logika. Saya tidak suka> o <;;skip_callback ..., if: :skip_some_callbacks
denganafter_create ..., unless: :skip_some_callbacks
untuk menjalankan ini dengan benar dengan after_create.Diperbarui:
Solusi @ Vikrant Chaudhary tampaknya lebih baik:
Jawaban asli saya:
lihat tautan ini: Bagaimana cara melewatkan callback ActiveRecord?
dalam Rails3,
anggap kita memiliki definisi kelas:
Pendekatan1:
Approach2: Ketika Anda ingin melewatkannya di file rspec Anda atau apa pun, coba ini:
CATATAN: setelah ini selesai, jika Anda tidak berada di lingkungan rspec, Anda harus mengatur ulang panggilan balik:
berfungsi dengan baik untuk saya di rel 3.0.5
sumber
rel 3:
sumber
reset_callbacks
bukan:after_save
, melainkan:save
. apidock.com/rails/v3.0.9/ActiveSupport/Callbacks/ClassMethods/…Jika tujuannya adalah hanya menyisipkan catatan tanpa panggilan balik atau validasi, dan Anda ingin melakukannya tanpa menggunakan permata tambahan, menambahkan cek bersyarat, menggunakan RAW SQL, atau menghapus kode yang keluar dengan cara apa pun, pertimbangkan untuk menggunakan bayangan "menunjuk ke tabel db yang ada. Seperti itu:
Ini berfungsi dengan setiap versi Rails, aman untuk threads, dan sepenuhnya menghilangkan semua validasi dan panggilan balik tanpa modifikasi pada kode Anda yang ada. Anda bisa melempar deklarasi kelas itu tepat sebelum impor Anda yang sebenarnya, dan Anda harus melakukannya dengan baik. Ingatlah untuk menggunakan kelas baru Anda untuk menyisipkan objek, seperti:
sumber
Anda dapat mencoba sesuatu seperti ini di model Person Anda:
EDIT: after_save bukan simbol, tapi setidaknya 1.000 kali saya mencoba membuatnya.
sumber
send
. KOODOSAnda bisa menggunakan
update_columns
:sumber
Satu-satunya cara untuk mencegah semua panggilan balik after_save adalah membuat yang pertama mengembalikan false.
Mungkin Anda bisa mencoba sesuatu seperti (belum diuji):
sumber
Sepertinya satu cara untuk menangani hal ini di Rails 2.3 (karena update_without_callbacks tidak ada, dll.), Adalah dengan menggunakan update_all, yang merupakan salah satu metode yang melewatkan callback sesuai dengan bagian 12 dari Panduan Rails untuk validasi dan callback .
Juga, perhatikan bahwa jika Anda melakukan sesuatu di callback after_ Anda, yang melakukan perhitungan berdasarkan banyak asosiasi (mis. Asosiasi has_many, di mana Anda juga melakukan accepts_nested_attributes_for), Anda perlu memuat ulang asosiasi, jika-kalau sebagai bagian dari save , salah satu anggotanya telah dihapus.
sumber
https://gist.github.com/576546
cukup buang monyet-patch ini ke config / initializers / skip_callbacks.rb
kemudian
Project.skip_callbacks { @project.save }
atau sejenisnya.
semua kredit kepada penulis
sumber
up-voted
Jawaban yang paling mungkin tampak membingungkan dalam beberapa kasus.Anda dapat menggunakan hanya
if
cek sederhana jika Anda ingin melewatkan panggilan balik, seperti ini:sumber
Solusi yang harus bekerja di semua versi Rails tanpa menggunakan permata atau plugin adalah dengan mengeluarkan pernyataan pembaruan secara langsung. misalnya
Ini mungkin (atau mungkin tidak) menjadi opsi tergantung pada seberapa kompleksnya pembaruan Anda. Ini bekerja dengan baik untuk misalnya memperbarui bendera pada catatan dari dalam panggilan balik after_save (tanpa retrigger panggilan balik).
sumber
#{...}
.sumber
Tak satu pun dari poin ini ke
without_callbacks
plugin yang hanya melakukan apa yang Anda butuhkan ...http://github.com/cjbottaro/without_callbacks berfungsi dengan Rails 2.x
sumber
Saya menulis sebuah plugin yang mengimplementasikan update_without_callbacks di Rails 3:
http://github.com/dball/skip_activerecord_callbacks
Solusi yang tepat, saya pikir, adalah menulis ulang model Anda untuk menghindari panggilan balik di tempat pertama, tetapi jika itu tidak praktis dalam waktu dekat, plugin ini dapat membantu.
sumber
Jika Anda menggunakan Rails 2. Anda bisa menggunakan query SQL untuk memperbarui kolom Anda tanpa menjalankan panggilan balik dan validasi.
Saya pikir itu harus bekerja di versi rel.
sumber
Ketika saya membutuhkan kontrol penuh atas panggilan balik, saya membuat atribut lain yang digunakan sebagai saklar. Sederhana dan efektif:
Model:
Uji:
sumber
Untuk membuat data uji di Rails Anda menggunakan peretasan ini:
https://coderwall.com/p/y3yp2q/edit
sumber
Anda dapat menggunakan permata licik-simpan: https://rubygems.org/gems/sneaky-save .
Perhatikan ini tidak dapat membantu dalam menyimpan asosiasi tanpa validasi. Itu melempar kesalahan 'Created_at tidak boleh nol' karena langsung memasukkan permintaan sql tidak seperti model. Untuk mengimplementasikan ini, kita perlu memperbarui semua kolom db yang dihasilkan secara otomatis.
sumber
Saya membutuhkan solusi untuk Rails 4, jadi saya datang dengan ini:
app / model / concern / save_without_callbacks.rb
dalam model apa pun:
maka kamu bisa:
atau
sumber
Mengapa Anda ingin dapat melakukan ini dalam pengembangan? Tentunya ini berarti Anda sedang membangun aplikasi Anda dengan data yang tidak valid dan karena itu akan berperilaku aneh dan tidak seperti yang Anda harapkan dalam produksi.
Jika Anda ingin mengisi dev db Anda dengan data, pendekatan yang lebih baik adalah membangun tugas menyapu yang menggunakan permata faker untuk membangun data yang valid dan mengimpornya ke db membuat sebanyak atau beberapa catatan yang Anda inginkan, tetapi jika Anda lemah membungkuk dan memiliki alasan yang baik saya kira pembaruan_without_callbacks dan create_without_callbacks tidak akan berfungsi dengan baik, tetapi ketika Anda mencoba membengkokkan rel ke kehendak Anda, tanyakan pada diri sendiri Anda memiliki alasan yang baik dan jika apa yang Anda lakukan benar-benar ide yang bagus.
sumber
Salah satu opsi adalah memiliki model terpisah untuk manipulasi seperti itu, menggunakan tabel yang sama:
(Pendekatan yang sama mungkin membuat segalanya lebih mudah untuk melewati validasi)
Stephan
sumber
Cara lain adalah dengan menggunakan kait validasi alih-alih callback. Sebagai contoh:
Dengan begitu Anda bisa mendapatkan do_something secara default, tetapi Anda dapat dengan mudah menimpanya dengan:
sumber
Sesuatu yang seharusnya bekerja dengan semua versi
ActiveRecord
tanpa tergantung pada opsi atau metode activerecord yang mungkin ada atau tidak ada.TLDR: gunakan "model activerecord yang berbeda" di atas tabel yang sama
sumber
Untuk panggilan balik khusus, gunakan a
attr_accessor
dan aunless
di dalam panggilan balik.Tentukan model Anda sebagai berikut:
Dan kemudian jika Anda perlu menyimpan catatan tanpa menekan
after_save
callback yang Anda tetapkan, aturskip_after_save_callbacks
atribut virtual ketrue
.sumber
Bukan cara terbersih, tetapi Anda bisa membungkus kode panggilan balik dalam kondisi yang memeriksa lingkungan Rails.
sumber