Dengan Pengamat secara resmi dihapus dari Rails 4.0 , saya ingin tahu apa yang pengembang lain gunakan di tempat mereka. (Selain menggunakan permata yang diekstraksi.) Sementara Pengamat tentu saja dilecehkan dan dapat dengan mudah menjadi susah di kali, ada banyak kasus penggunaan di luar hanya cache-kliring di mana mereka menguntungkan.
Ambil, misalnya, aplikasi yang perlu melacak perubahan ke model. Pengamat dapat dengan mudah melihat perubahan pada Model A dan mencatat perubahan tersebut dengan Model B dalam database. Jika Anda ingin melihat perubahan di beberapa model, maka satu pengamat dapat mengatasinya.
Di Rails 4, saya ingin tahu strategi apa yang digunakan pengembang lain sebagai pengganti Pengamat untuk menciptakan kembali fungsionalitas itu.
Secara pribadi, saya condong ke arah semacam implementasi "pengendali lemak", di mana perubahan ini dilacak di setiap metode membuat / memperbarui / menghapus pengontrol model. Meskipun sedikit membesarkan perilaku masing-masing pengontrol, itu membantu dalam keterbacaan dan pemahaman karena semua kode berada di satu tempat. The downside adalah bahwa sekarang ada kode yang sangat mirip tersebar di beberapa pengontrol. Mengekstrak kode itu ke metode pembantu adalah sebuah opsi, tetapi Anda masih memiliki panggilan untuk metode-metode yang berserakan di mana-mana. Bukan akhir dunia, tetapi tidak cukup dalam semangat "pengendali kurus" juga.
Callback ActiveRecord adalah pilihan lain yang mungkin, meskipun yang saya pribadi tidak suka karena cenderung menyandingkan dua model yang berbeda terlalu dekat menurut pendapat saya.
Jadi di dunia Rails 4, dunia tanpa Pengamat, jika Anda harus membuat catatan baru setelah catatan lain dibuat / diperbarui / dihancurkan, pola desain apa yang akan Anda gunakan? Pengontrol gemuk, panggilan balik ActiveRecord, atau yang lainnya?
Terima kasih.
sumber
Jawaban:
Lihatlah Kekhawatiran
Buat folder di direktori model Anda yang disebut kekhawatiran. Tambahkan modul di sana:
Selanjutnya, sertakan dalam model yang Anda ingin jalankan after_save di:
Tergantung pada apa yang Anda lakukan, ini mungkin membuat Anda dekat tanpa pengamat.
sumber
Mereka ada di plugin sekarang.
Dapatkah saya juga merekomendasikan alternatif yang akan memberi Anda pengendali seperti:
sumber
ActiveSupport::Notifications
diarahkan pada instrumentasi, bukan sub / pub generik.ActiveSupport::Notifications
?Notifications
banyak menggunakan tetapi saya katakanWisper
memiliki API yang lebih bagus dan fitur seperti 'pelanggan global', 'awalan' dan 'pemetaan acara' yangNotifications
tidak. Rilis di masa depanWisper
juga akan memungkinkan penerbitan async melalui SideKiq / Resque / Celluloid. Juga, berpotensi, dalam rilis Rails di masa depan, API untukNotifications
dapat berubah menjadi lebih terfokus pada instrumentasi.Saran saya adalah membaca posting blog James Golick di http://jamesgolick.com/2010/3/14/crazy-heretical-and-awesome-the-way-i-write-rails-apps.html (coba abaikan caranya judul tidak sopan terdengar).
Kembali pada hari itu semua "model gemuk, pengontrol kurus". Kemudian model gemuk menjadi sakit kepala raksasa, terutama saat pengujian. Baru-baru ini dorongan untuk model kurus - gagasan bahwa setiap kelas harus menangani satu tanggung jawab dan tugas model adalah untuk mempertahankan data Anda ke database. Jadi, di mana semua logika bisnis kompleks saya berakhir? Dalam kelas logika bisnis - kelas yang mewakili transaksi.
Pendekatan ini dapat berubah menjadi quagmire (giggity) ketika logika mulai rumit. Konsepnya masuk akal - alih-alih memicu hal-hal secara implisit dengan panggilan balik atau pengamat yang sulit untuk diuji dan didebug, memicu hal-hal secara eksplisit dalam kelas yang melapisi logika di atas model Anda.
sumber
Menggunakan panggilan balik rekaman aktif hanya membalik ketergantungan kopling Anda. Misalnya, jika Anda memiliki
modelA
danCacheObserver
mengamatimodelA
gaya 3 rails, Anda dapat menghapusCacheObserver
tanpa masalah. Sekarang, alih-alih katakanA
harus secara manual memanggilCacheObserver
after save, yang akan menjadi rail 4. Anda cukup memindahkan dependensi Anda sehingga Anda dapat menghapus dengan amanA
tetapi tidakCacheObserver
.Sekarang, dari menara gading saya, saya lebih suka pengamat bergantung pada model yang diamati. Apakah saya cukup peduli untuk mengacaukan pengendali saya? Bagi saya, jawabannya adalah tidak.
Mungkin Anda telah memikirkan mengapa Anda ingin / membutuhkan pengamat, dan dengan demikian menciptakan model yang bergantung pada pengamatnya bukanlah tragedi yang mengerikan.
Saya juga memiliki rasa (cukup beralasan, saya pikir) untuk segala jenis pengamat yang bergantung pada tindakan pengontrol. Tiba-tiba Anda harus menyuntikkan pengamat Anda dalam tindakan pengontrol apa pun (atau model lain) yang dapat memperbarui model yang ingin Anda amati. Jika Anda dapat menjamin aplikasi Anda hanya akan memodifikasi instance melalui buat / perbarui tindakan pengontrol, lebih banyak kekuatan untuk Anda, tapi itu bukan asumsi saya akan membuat tentang aplikasi rel (pertimbangkan bentuk bersarang, asosiasi pembaruan logika model bisnis, dll.)
sumber
Wisper adalah solusi hebat. Preferensi pribadi saya untuk callback adalah bahwa mereka dipecat oleh model tetapi acara hanya didengarkan ketika permintaan masuk yaitu saya tidak ingin callback dipecat saat saya sedang menyiapkan model dalam tes dll. Tapi saya ingin mereka dipecat setiap kali pengendali terlibat. Ini sangat mudah diseting dengan Wisper karena Anda bisa mengatakannya hanya mendengarkan acara di dalam blok.
sumber
Dalam beberapa kasus saya cukup menggunakan Instrumentasi Dukungan Aktif
sumber
Alternatif saya untuk Rails 3 Observers adalah implementasi manual yang memanfaatkan callback yang didefinisikan dalam model namun berhasil (seperti yang dinyatakan agmin dalam jawaban di atas) "flip the dependency ... coupling".
Objek saya mewarisi dari kelas dasar yang menyediakan untuk mendaftar pengamat:
(Memang, dalam semangat komposisi atas warisan, kode di atas dapat ditempatkan dalam modul dan dicampur dalam masing-masing model.)
Penginisialisasi mendaftar pengamat:
Setiap model kemudian dapat menentukan peristiwa yang dapat diamati sendiri, di luar panggilan balik ActiveRecord dasar. Misalnya, model Pengguna saya memaparkan 2 peristiwa:
Setiap pengamat yang ingin menerima pemberitahuan untuk acara-acara tersebut hanya perlu (1) mendaftar dengan model yang memaparkan acara dan (2) memiliki metode yang namanya cocok dengan acara tersebut. Seperti yang diduga, beberapa pengamat dapat mendaftar untuk acara yang sama, dan (mengacu pada paragraf 2 dari pertanyaan awal) pengamat dapat menonton acara di beberapa model.
Kelas pengamat NotificationSender dan ProfilePictureCreator di bawah ini menetapkan metode untuk peristiwa yang diungkapkan oleh berbagai model:
Satu peringatan adalah bahwa nama-nama semua peristiwa yang terungkap di semua model harus unik.
sumber
Saya pikir masalah dengan Pengamat yang ditinggalkan bukanlah bahwa pengamat buruk dalam diri mereka sendiri tetapi bahwa mereka dilecehkan.
Saya akan berhati-hati agar tidak menambahkan terlalu banyak logika di callback Anda atau hanya memindahkan kode untuk mensimulasikan perilaku pengamat ketika sudah ada solusi yang bagus untuk masalah ini, pola Observer.
Jika masuk akal untuk menggunakan pengamat maka tentu saja gunakan pengamat. Hanya mengerti bahwa Anda perlu memastikan bahwa logika pengamat Anda mengikuti praktik pengkodean suara misalnya SOLID.
Permata pengamat tersedia di rubygems jika Anda ingin menambahkannya kembali ke proyek Anda https://github.com/rails/rails-observers
lihat utas singkat ini, sementara tidak diskusi lengkap yang lengkap saya pikir argumen dasarnya valid. https://github.com/rails/rails-observers/issues/2
sumber
Anda dapat mencoba https://github.com/TiagoCardoso1983/association_observers . Itu belum diuji untuk rails 4 (yang belum diluncurkan), dan perlu kolaborasi lagi, tetapi Anda dapat memeriksa apakah itu berhasil untuk Anda.
sumber
Bagaimana kalau menggunakan PORO saja?
Logika di balik ini adalah bahwa 'tindakan ekstra menghemat' Anda kemungkinan akan menjadi logika bisnis. Ini saya ingin tetap terpisah dari kedua model AR (yang seharusnya sesederhana mungkin) dan pengontrol (yang merepotkan untuk diuji dengan benar)
Dan cukup sebut saja:
Anda bahkan dapat mengembangkannya, dengan menyuntikkan objek tindakan pasca-simpan ekstra
Dan untuk memberi contoh 'ekstra'. Anda mungkin ingin sedikit mempercantik mereka:
Jika Anda menyukai pendekatan ini, saya sarankan membaca posting blog Bryan Helmkamps 7 Patterns .
EDIT: Saya juga harus menyebutkan bahwa solusi di atas memungkinkan untuk menambahkan logika transaksi juga saat diperlukan. Misalnya dengan ActiveRecord dan database yang didukung:
sumber
Perlu disebutkan bahwa
Observable
modul dari pustaka standar Ruby tidak dapat digunakan dalam objek seperti-catatan aktif karena metode instanchanged?
danchanged
akan berbenturan dengan yang dariActiveModel::Dirty
.Laporan bug untuk Rails 2.3.2
sumber
Saya memiliki masalah yang sama! Saya menemukan solusi ActiveModel :: Kotor sehingga Anda dapat melacak perubahan model Anda!
http://api.rubyonrails.org/classes/ActiveModel/Dirty.html
sumber