Saya ingin menentukan urutan penyortiran default dalam model saya.
Sehingga ketika saya melakukan .where()
tanpa menentukan .order()
itu menggunakan semacam default. Tetapi jika saya menentukan .order()
, itu menimpa default.
Saya ingin menentukan urutan penyortiran default dalam model saya.
Sehingga ketika saya melakukan .where()
tanpa menentukan .order()
itu menggunakan semacam default. Tetapi jika saya menentukan .order()
, itu menimpa default.
Jawaban:
default_scope
Ini berfungsi untuk Rails 4+:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
Untuk Rails 2.3, 3, Anda membutuhkan ini:
default_scope order('created_at DESC')
Untuk Rails 2.x:
default_scope :order => 'created_at DESC'
Di mana created_at
bidang yang Anda inginkan penyortiran default dilakukan.
Catatan: ASC adalah kode yang digunakan untuk Ascending dan DESC adalah untuk descending ( desc
, NOT dsc
!).
scope
Setelah terbiasa, Anda juga dapat menggunakan scope
:
class Book < ActiveRecord::Base
scope :confirmed, :conditions => { :confirmed => true }
scope :published, :conditions => { :published => true }
end
Untuk Rails 2 Anda perlu named_scope
.
:published
cakupan memberi Anda Book.published
alih-alih
Book.find(:published => true)
.
Karena Rails 3 Anda dapat 'rantai' metode-metode tersebut bersama-sama dengan menggabungkannya dengan periode di antara mereka, jadi dengan cakupan di atas sekarang Anda dapat menggunakan Book.published.confirmed
.
Dengan metode ini, permintaan tidak benar-benar dieksekusi sampai hasil aktual diperlukan (evaluasi malas), sehingga 7 cakupan dapat dirantai bersama tetapi hanya menghasilkan 1 permintaan basis data aktual, untuk menghindari masalah kinerja dari mengeksekusi 7 permintaan terpisah.
Anda dapat menggunakan parameter yang diteruskan seperti tanggal atau user_id (sesuatu yang akan berubah pada saat run-time dan akan membutuhkan 'evaluasi malas', dengan lambda, seperti ini:
scope :recent_books, lambda
{ |since_when| where("created_at >= ?", since_when) }
# Note the `where` is making use of AREL syntax added in Rails 3.
Akhirnya Anda dapat menonaktifkan ruang lingkup default dengan:
Book.with_exclusive_scope { find(:all) }
atau bahkan lebih baik:
Book.unscoped.all
yang akan menonaktifkan filter apa pun (kondisi) atau urutkan (dipesan berdasarkan).
Perhatikan bahwa versi pertama berfungsi di Rails2 + sedangkan yang kedua (tidak dicopot) hanya untuk Rails3 +
Jadi
... jika Anda berpikir, hmm, jadi ini seperti metode maka ..., ya, itulah tepatnya lingkup ini!
Mereka seperti memiliki def self.method_name ...code... end
tetapi seperti biasa dengan ruby mereka adalah cara pintas sintaksis kecil yang bagus (atau 'gula') untuk membuat segalanya lebih mudah bagi Anda!
Sebenarnya mereka adalah metode tingkat Kelas karena mereka beroperasi pada 1 set 'semua' catatan.
Namun format mereka berubah, dengan rails 4 ada peringatan penghentian ketika menggunakan #scope tanpa melewati objek yang bisa dipanggil. Misalnya cakupan: merah, di mana (warna: 'merah') harus diubah scope :red, -> { where(color: 'red') }
.
Sebagai catatan, ketika digunakan secara tidak benar, standar _scope dapat disalahgunakan / disalahgunakan.
Ini terutama tentang kapan akan digunakan untuk tindakan seperti where
membatasi (memfilter) pilihan default ( ide buruk untuk default) daripada hanya digunakan untuk memesan hasil.
Untuk where
pilihan, cukup gunakan cakupan bernama biasa. dan menambahkan lingkup itu di dalam kueri, misalnya di Book.all.published
mana published
ruang lingkup bernama.
Kesimpulannya, cakupan benar-benar hebat dan membantu Anda untuk mendorong berbagai hal ke dalam model untuk pendekatan DRYer 'pengendali model kurus'.
default_scope { order("#{table_name}.created_at DESC") }
?
default_scope { order(created_at: :desc) }
4.2.6
sepertinya urutkan berdasarkan updated_at
tidak created_at
.
updated_at
secara default? : - |
Pembaruan cepat untuk jawaban luar biasa Michael di atas.
Untuk Rails 4.0+, Anda harus meletakkan sortir di blok seperti ini:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
Perhatikan bahwa pernyataan pesanan ditempatkan di blok yang dilambangkan oleh kurung kurawal.
Mereka mengubahnya karena terlalu mudah untuk melewatkan sesuatu yang dinamis (seperti waktu sekarang). Ini menghilangkan masalah karena blok dievaluasi saat runtime. Jika Anda tidak menggunakan blok Anda akan mendapatkan kesalahan ini:
Dukungan untuk memanggil #default_scope tanpa blok dihapus. Sebagai contoh alih-alih
default_scope where(color: 'red')
, silakan gunakandefault_scope { where(color: 'red') }
. (Atau Anda dapat mendefinisikan ulang self.default_scope.)
Seperti @Dan menyebutkan dalam komentarnya di bawah ini, Anda dapat melakukan sintaksis lebih ruby seperti ini:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
atau dengan banyak kolom:
class Book < ActiveRecord::Base
default_scope { order({begin_date: :desc}, :name) }
end
Terima kasih @Dan !
default_scope { order(created_at: :desc) }
olah, seperti saya, Anda mencoba meminimalkan sintaks sql di rails. <br/> Jika Anda memiliki beberapa kolom untuk memesan oleh dan Anda ingin menggunakan sintaks baru Anda mungkin perlu membungkus desc kolom dalam kumis seperti inidefault_scope { order({begin_date: :desc}, :name) }
Anda dapat menggunakan default_scope untuk mengimplementasikan perintah pengurutan standar http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html
default_scope
di halaman itu, karena telah dire-refored dari ActiveRecord::Base
ke ActiveRecord::Scoping::Default::ClassMethods
( api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/… )