Saya baru memulai dengan aplikasi web Ruby on Rails pertama saya. Saya punya banyak model, tampilan, pengontrol, dan sebagainya yang berbeda.
Saya ingin menemukan tempat yang baik untuk tetap definisi konstan konstanta global, yang berlaku di seluruh aplikasi saya. Secara khusus, mereka berlaku baik dalam logika model saya, dan dalam keputusan yang diambil dalam pandangan saya. Saya tidak dapat menemukan tempat KERING untuk meletakkan definisi ini di mana mereka tersedia baik untuk semua model saya dan juga dalam semua pandangan saya.
Untuk mengambil contoh spesifik, saya ingin sebuah konstanta COLOURS = ['white', 'blue', 'black', 'red', 'green']
. Ini digunakan di semua tempat, baik dalam model maupun tampilan. Di mana saya dapat mendefinisikannya hanya di satu tempat sehingga dapat diakses?
Apa yang saya coba:
- Variabel kelas konstan dalam file model.rb yang paling sering dikaitkan dengan mereka, seperti
@@COLOURS = [...]
. Tapi saya tidak bisa menemukan cara yang waras untuk mendefinisikannya sehingga saya bisa menulis dalam pandangan sayaCard.COLOURS
daripada sesuatu yang suka kludgyCard.first.COLOURS
. - Metode pada model, sesuatu seperti
def colours ['white',...] end
- masalah yang sama. - Metode di application_helper.rb - inilah yang saya lakukan sejauh ini, tetapi pembantu hanya dapat diakses dalam tampilan, bukan dalam model
- Saya pikir saya mungkin telah mencoba sesuatu di application.rb atau environment.rb, tetapi itu sepertinya tidak benar (dan mereka juga tidak berfungsi)
Apakah tidak ada cara untuk mendefinisikan sesuatu yang dapat diakses baik dari model maupun dari tampilan? Maksud saya, saya tahu model dan tampilan harus terpisah, tetapi pasti di beberapa domain akan ada saatnya mereka perlu merujuk ke pengetahuan khusus domain yang sama?
sumber
Jawaban:
Jika model Anda benar-benar "bertanggung jawab" untuk konstanta, Anda harus menempelkannya di sana. Anda bisa membuat metode kelas untuk mengaksesnya tanpa membuat instance objek baru:
Atau, Anda bisa membuat variabel kelas dan accessor. Namun ini tidak dianjurkan karena variabel kelas mungkin bertindak agak mengejutkan dengan pewarisan dan dalam lingkungan multi-utas.
Dua opsi di atas memungkinkan Anda untuk mengubah array yang dikembalikan pada setiap pemanggilan metode accessor jika diperlukan. Jika Anda memiliki konstanta yang benar-benar tidak dapat diubah, Anda juga dapat mendefinisikannya pada kelas model:
Anda juga bisa membuat konstanta global yang dapat diakses dari mana saja di penginisialisasi seperti pada contoh berikut. Ini mungkin tempat terbaik, jika warna Anda benar-benar global dan digunakan dalam lebih dari satu konteks model.
Catatan: ketika kita mendefinisikan konstanta di atas, seringkali kita ingin
freeze
array. Itu mencegah kode lain dari nanti (secara tidak sengaja) memodifikasi array dengan misalnya menambahkan elemen baru. Setelah suatu objek dibekukan, itu tidak dapat diubah lagi.sumber
config/initializers/my_constants.rb
rute, ingatlah untuk me-restart server:touch tmp/restart.txt
def self.colours
contoh adalah tidak ideal. Setiap kali Anda menelepondef self.colours
, instance array baru akan dikembalikan .#freeze
tidak akan membantu dalam hal ini. Praktik terbaik adalah mendeklarasikannya sebagai konstanta Ruby, dalam hal ini Anda akan selalu mendapatkan kembali objek yang sama.class Card; COLOURS = ['white', 'blue'].freeze; def self.colours; COLOURS; end; end
Yang mengatakan, mengalokasikan array dalam bahasa apa pun berpotensi bermasalah; untuk satu, itu menggunakan memori tanpa alasan (baik). Jika memuat dari DB, dan ingin men-cache nilai, kita juga bisa menggunakan variabel instance kelas, yang dapat dimuat dengan malas menggunakandef self.colours
metode. Setuju tentang aspek imutabilitas.Beberapa opsi:
Menggunakan konstanta:
Malas dimuat menggunakan variabel instance kelas:
Jika itu adalah konstanta yang benar-benar global ( hindari konstanta global seperti ini ), Anda juga dapat mempertimbangkan untuk memasukkan konstanta tingkat
config/initializers/my_constants.rb
atas sebagai contoh.sumber
extend
modul di kelas sehingga akan tersediaCard.COLOURS
.extend
itu tidak bekerja untuk saya. Saat menggunakaninclude
saya dapat mengakses seperti:Card::COLOURS
/models
. Jauh lebih baik jika Anda membuat penginisialisasi./models
, tetapi hanya jika itu di dalam modul, misalnyamodule Constants; COLOURS = ...; end
dalam file yang disebutmodels/constants.rb
.Pada Rails 4.2, Anda dapat menggunakan
config.x
properti:Yang akan tersedia sebagai:
Metode lain pemuatan konfigurasi khusus:
Dalam Rails 5 & 6 , Anda dapat menggunakan
configuration
objek langsung untuk konfigurasi kustom, selainconfig.x
. Namun, itu hanya dapat digunakan untuk konfigurasi non-bersarang:Ini akan tersedia sebagai:
sumber
Rails.configuration.colours
terbaik (meskipun saya berharap itu tidak begitu lama)config
baiknyaconfiguration
. Kami mungkin berharap untuk mendapatkan jalan pintas di beberapa titik :)ApplicationController
jika tidak ada yang lain di antara keduanya. Jika konstanta tidak terkait langsung dengan pengontrol, saya masih akan mempertimbangkan konfigurasi global, dll.Jika sebuah konstanta diperlukan di lebih dari satu kelas, saya memasukkannya ke config / initializers / contant.rb selalu dalam semua huruf besar (daftar negara di bawah ini terpotong).
Mereka tersedia di seluruh aplikasi kecuali dalam kode model seperti:
Untuk menggunakan konstanta dalam model, gunakan attr_accessor untuk membuat konstanta tersedia.
sumber
config/initializers/constants.rb
mungkin akan menjadi pilihan yang lebih baikUntuk pengaturan di seluruh aplikasi dan untuk konstanta global, saya sarankan untuk menggunakan Settingslogic . Pengaturan ini disimpan dalam file YML dan dapat diakses dari model, tampilan, dan pengontrol. Selain itu, Anda dapat membuat pengaturan berbeda untuk semua lingkungan Anda:
Di suatu tempat dalam pandangan (saya lebih suka metode pembantu untuk hal-hal semacam itu) atau dalam model Anda bisa mendapatkan, misalnya, berbagai warna
Settings.colors.split(/\s/)
. Ini sangat fleksibel. Dan Anda tidak perlu menciptakan sepeda.sumber
Gunakan metode kelas:
Kemudian
Model.colours
akan mengembalikan array itu. Atau, buat penginisialisasi dan bungkus konstanta dalam modul untuk menghindari konflik namespace.sumber
Cobalah untuk menjaga semua konstan di satu tempat, Dalam aplikasi saya, saya telah membuat folder konstanta di dalam inisialisasi sebagai berikut:
dan saya biasanya menjaga semua konstan dalam file ini.
Dalam kasus Anda, Anda dapat membuat file di bawah folder konstanta sebagai
colors_constant.rb
colors_constant.rb
Jangan lupa me-restart server
sumber
Opsi lain, jika Anda ingin mendefinisikan konstanta di satu tempat:
Tetapi tetap membuatnya terlihat secara global tanpa harus mengaksesnya dengan cara yang sepenuhnya memenuhi syarat:
sumber
Tempat umum untuk meletakkan konstanta global aplikasi-lebar ada di dalamnya
config/application
.sumber
Saya biasanya memiliki model / tabel 'pencarian' dalam program rel saya dan menggunakannya untuk konstanta. Ini sangat berguna jika konstanta akan berbeda untuk lingkungan yang berbeda. Selain itu, jika Anda memiliki rencana untuk memperpanjangnya, katakan Anda ingin menambahkan 'kuning' di kemudian hari, Anda bisa menambahkan baris baru ke tabel pencarian dan selesai dengan itu.
Jika Anda memberikan izin admin untuk memodifikasi tabel ini, mereka tidak akan datang kepada Anda untuk pemeliharaan. :) KERING.
Begini tampilannya kode migrasi saya:
Saya menggunakan seed.rb untuk mengisinya terlebih dahulu.
sumber
Variabel global harus dinyatakan dalam
config/initializers
direktorisumber
Menurut kondisi Anda, Anda juga dapat mendefinisikan beberapa variabel lingkungan, dan mengambilnya melalui
ENV['some-var']
kode ruby, solusi ini mungkin tidak cocok untuk Anda, tetapi saya harap ini dapat membantu orang lain.Contoh: Anda dapat membuat file yang berbeda
.development_env
,.production_env
,.test_env
dan beban itu sesuai lingkungan aplikasi Anda, periksa ini gen dotenv-rel yang mengotomatisasi ini untuk Anda.sumber