Tôi muốn chỉ định một thứ tự sắp xếp mặc định trong mô hình của tôi.
Vì vậy, khi tôi làm .where()
mà không chỉ định, .order()
nó sử dụng sắp xếp mặc định. Nhưng nếu tôi chỉ định một .order()
, nó sẽ ghi đè mặc định.
Tôi muốn chỉ định một thứ tự sắp xếp mặc định trong mô hình của tôi.
Vì vậy, khi tôi làm .where()
mà không chỉ định, .order()
nó sử dụng sắp xếp mặc định. Nhưng nếu tôi chỉ định một .order()
, nó sẽ ghi đè mặc định.
Câu trả lời:
default_scope
Điều này hoạt động cho Rails 4+:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
Đối với Rails 2.3, 3, bạn cần điều này thay thế:
default_scope order('created_at DESC')
Đối với đường ray 2.x:
default_scope :order => 'created_at DESC'
Trường created_at
bạn muốn sắp xếp mặc định được thực hiện ở đâu.
Lưu ý: ASC là mã để sử dụng cho Tăng dần và DESC là giảm dần ( desc
, KHÔNG dsc
!).
scope
Khi bạn đã quen với điều đó, bạn cũng có thể sử dụng scope
:
class Book < ActiveRecord::Base
scope :confirmed, :conditions => { :confirmed => true }
scope :published, :conditions => { :published => true }
end
Đối với Rails 2 bạn cần named_scope
.
:published
phạm vi cung cấp cho bạn Book.published
thay vì
Book.find(:published => true)
.
Vì Rails 3, bạn có thể 'xâu chuỗi' các phương thức đó lại với nhau bằng cách nối chúng với các khoảng thời gian giữa chúng, do đó, với các phạm vi trên, giờ đây bạn có thể sử dụng Book.published.confirmed
.
Với phương pháp này, truy vấn không thực sự được thực hiện cho đến khi cần kết quả thực tế (đánh giá lười biếng), do đó, 7 phạm vi có thể được kết nối với nhau nhưng chỉ dẫn đến 1 truy vấn cơ sở dữ liệu thực tế, để tránh các vấn đề về hiệu năng khi thực hiện 7 truy vấn riêng biệt.
Bạn có thể sử dụng một tham số được truyền vào như ngày hoặc user_id (thứ gì đó sẽ thay đổi vào thời gian chạy và do đó sẽ cần 'đánh giá lười biếng', với lambda, như thế này:
scope :recent_books, lambda
{ |since_when| where("created_at >= ?", since_when) }
# Note the `where` is making use of AREL syntax added in Rails 3.
Cuối cùng, bạn có thể tắt phạm vi mặc định với:
Book.with_exclusive_scope { find(:all) }
hoặc thậm chí tốt hơn:
Book.unscoped.all
sẽ vô hiệu hóa bất kỳ bộ lọc (điều kiện) hoặc sắp xếp (thứ tự theo).
Lưu ý rằng phiên bản đầu tiên hoạt động trong Rails2 + trong khi phiên bản thứ hai (không có tỷ lệ) chỉ dành cho Rails3 +
Vì vậy,
... nếu bạn đang nghĩ, hmm, vậy thì đây cũng giống như các phương thức thì ..., yup, đó chính xác là những phạm vi này!
Chúng giống như có def self.method_name ...code... end
nhưng như mọi khi với ruby, chúng là những phím tắt cú pháp nhỏ (hay 'đường') để làm mọi thứ dễ dàng hơn cho bạn!
Trong thực tế, chúng là các phương thức cấp Lớp khi chúng hoạt động trên 1 bộ hồ sơ 'tất cả'.
Tuy nhiên, định dạng của chúng đang thay đổi, với đường ray 4 có cảnh báo không dùng nữa khi sử dụng #scope mà không truyền đối tượng có thể gọi được. Ví dụ: phạm vi: đỏ, trong đó (màu: 'đỏ') nên được thay đổi thànhscope :red, -> { where(color: 'red') }
.
Là một lưu ý phụ, khi được sử dụng không chính xác, _scope mặc định có thể bị lạm dụng / lạm dụng.
Điều này chủ yếu là khi nó được sử dụng cho các hành động như where
giới hạn (lọc) lựa chọn mặc định (một ý tưởng tồi cho mặc định) thay vì chỉ được sử dụng để đặt hàng kết quả.
Đối với các where
lựa chọn, chỉ cần sử dụng phạm vi được đặt tên thông thường. và thêm phạm vi mà vào trong truy vấn, ví dụ như Book.all.published
nơi published
là một phạm vi được đặt tên.
Tóm lại, phạm vi thực sự tuyệt vời và giúp bạn đẩy mọi thứ vào mô hình cho phương pháp DRYer của bộ điều khiển mô hình béo '.
default_scope { order("#{table_name}.created_at DESC") }
?
default_scope { order(created_at: :desc) }
4.2.6
dường như sắp xếp theo updated_at
không created_at
.
updated_at
theo mặc định? : - |
Một bản cập nhật nhanh chóng cho câu trả lời tuyệt vời của Michael ở trên.
Đối với Rails 4.0+, bạn cần đặt sắp xếp của mình vào một khối như thế này:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
Lưu ý rằng câu lệnh được đặt trong một khối được biểu thị bằng dấu ngoặc nhọn.
Họ đã thay đổi nó vì nó quá dễ dàng để vượt qua trong một cái gì đó năng động (như thời điểm hiện tại). Điều này loại bỏ vấn đề vì khối được đánh giá trong thời gian chạy. Nếu bạn không sử dụng một khối, bạn sẽ gặp lỗi này:
Hỗ trợ gọi #default_scope mà không bị chặn. Ví dụ thay vì
default_scope where(color: 'red')
, vui lòng sử dụngdefault_scope { where(color: 'red') }
. (Ngoài ra, bạn chỉ có thể xác định lại self.default_scope.)
Như @Dan đề cập trong bình luận của anh ấy bên dưới, bạn có thể thực hiện cú pháp rubyish như thế này:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
hoặc có nhiều cột:
class Book < ActiveRecord::Base
default_scope { order({begin_date: :desc}, :name) }
end
Cảm ơn @Dan !
default_scope { order(created_at: :desc) }
thể, giống như tôi, bạn cố gắng giảm thiểu cú pháp sql trong rails. <br/> Nếu bạn có nhiều cột để đặt hàng và bạn muốn sử dụng cú pháp mới, bạn có thể cần phải bọc desc các cột trong ria mép như thế nàydefault_scope { order({begin_date: :desc}, :name) }
Bạn có thể sử dụng default_scope để triển khai thứ tự sắp xếp mặc định http://api.rubyonrails.org/groupes/ActiveRecord/Scoping/Default/ClassMethods.html
default_scope
trên trang đó, vì nó đã được refactored từ ActiveRecord::Base
vào ActiveRecord::Scoping::Default::ClassMethods
( api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/... )