Như đã đề cập, các hiệp hội kỷ lục hoạt động tạo ra một buttload số liệu các phương pháp tiện lợi. Chắc chắn, bạn có thể viết các phương pháp của riêng bạn để tìm nạp mọi thứ. Nhưng đó không phải là Rails Way.
Đường ray là đỉnh cao của hai mottos. DRY (Đừng lặp lại bản thân) và "Convention over Configuration". Về cơ bản, bằng cách đặt tên mọi thứ theo cách có ý nghĩa, một số phương pháp mạnh mẽ được cung cấp bởi khung công tác có thể trừu tượng hóa tất cả các mã chung. Mã bạn đặt trong câu hỏi là ví dụ hoàn hảo về thứ gì đó có thể được thay thế bằng một cuộc gọi phương thức duy nhất.
Nơi các phương pháp tiện lợi này thực sự tỏa sáng là những tình huống phức tạp hơn. Loại câu hỏi liên quan đến các mô hình, điều kiện, xác nhận hợp lệ, v.v.
Để trả lời câu hỏi của bạn khi bạn làm một cái gì đó như @user.articles.find(:all, :conditions => ["created_at > ? ", tuesday])
, Rails chuẩn bị hai truy vấn SQL và sau đó hợp nhất chúng thành một. khi phiên bản của bạn chỉ trả về danh sách các đối tượng. Các phạm vi được đặt tên cũng thực hiện tương tự, nhưng thường không vượt qua ranh giới mô hình.
Bạn có thể xác thực bằng cách kiểm tra các truy vấn SQL trong development.log khi bạn gọi những điều này trong bảng điều khiển. Vì vậy, hãy cho phép nói về Named Scopes một chút vì chúng cung cấp một ví dụ tuyệt vời về cách các thanh điều khiển SQL, và tôi nghĩ chúng là cách đơn giản hơn để chứng minh những gì đang xảy ra phía sau hậu trường, vì chúng không cần bất kỳ mô hình liên kết để thể hiện.
Phạm vi được đặt tên có thể được sử dụng để thực hiện tìm kiếm tùy chỉnh của mô hình. Họ có thể bị xích lại với nhau hoặc thậm chí được gọi thông qua các hiệp hội. Bạn có thể dễ dàng tạo các công cụ tìm tùy chỉnh trả về các danh sách giống hệt nhau, nhưng sau đó bạn chạy vào cùng các vấn đề được đề cập trong Câu hỏi.
class Article < ActiveRecord::Base
belongs_to :user
has_many :comments
has_many :commentators, :through :comments, :class_name => "user"
named_scope :edited_scope, :conditions => {:edited => true}
named_scope :recent_scope, lambda do
{ :conditions => ["updated_at > ? ", DateTime.now - 7.days]}
def self.edited_method
self.find(:all, :conditions => {:edited => true})
end
def self.recent_method
self.find(:all, :conditions => ["updated_at > ?", DateTime.now - 7 days])
end
end
Article.edited_scope
=> # Array of articles that have been flagged as edited. 1 SQL query.
Article.edited_method
=> # Array of Articles that have been flagged as edited. 1 SQL query.
Array.edited_scope == Array.edited_method
=> true # return identical lists.
Article.recent_scope
=> # Array of articles that have been updated in the past 7 days.
1 SQL query.
Article.recent_method
=> # Array of Articles that have been updated in the past 7 days.
1 SQL query.
Array.recent_scope == Array.recent_method
=> true # return identical lists.
Đây là nơi mà mọi thứ thay đổi:
Article.edited_scope.recent_scope
=> # Array of articles that have both been edited and updated
in the past 7 days. 1 SQL query.
Article.edited_method.recent_method
=> # no method error recent_scope on Array
# Can't even mix and match.
Article.edited_scope.recent_method
=> # no method error
Article.recent_method.edited_scope
=> # no method error
# works even across associations.
@user.articles.edited.comments
=> # Array of comments belonging to Articles that are flagged as
edited and belong to @user. 1 SQL query.
Về cơ bản mỗi phạm vi tên là tạo ra một đoạn SQL. Rails sẽ khéo léo hợp nhất với mọi đoạn SQL khác trong chuỗi để tạo ra một truy vấn duy nhất, chính xác lại những gì bạn muốn. Các phương thức được thêm vào bởi các phương thức kết hợp hoạt động theo cùng một cách. Đó là lý do tại sao họ tích hợp liền mạch với named_scopes.
Lý do kết hợp kết hợp & không hoạt động giống với phương pháp of_sector được xác định trong câu hỏi không hoạt động. edit_methods trả về một mảng, trong đó như edit_scope (cũng như tìm và tất cả các phương thức tiện lợi AR khác được gọi là một phần của một chuỗi), hãy chuyển đoạn SQL của chúng sang hướng tiếp theo trong chuỗi. Nếu đó là lần cuối cùng trong chuỗi nó thực hiện truy vấn. Tương tự, điều này cũng không hoạt động.
@edited = Article.edited_scope
@edited.recent_scope
Bạn đã cố gắng sử dụng mã này.Đây là cách thích hợp để làm điều đó:
class User < ActiveRecord::Base
has_many :articles do
def of_sector(sector_id)
find(:all, :conditions => {:sector_id => sector_id})
end
end
end
Để đạt được chức năng này, bạn muốn làm điều này:
class Articles < ActiveRecord::Base
belongs_to :user
named_scope :of_sector, lambda do |*sectors|
{ :conditions => {:sector_id => sectors} }
end
end
class User < ActiveRecord::Base
has_many :articles
end
Sau đó, bạn có thể làm những việc như thế này:
@user.articles.of_sector(4)
=> # articles belonging to @user and sector of 4
@user.articles.of_sector(5,6)
=> # articles belonging to @user and either sector 4 or 5
@user.articles.of_sector([1,2,3,])
=> # articles belonging to @user and either sector 1,2, or 3
Cái này '/ (^ __ |^nil \? $ |^Gửi $ | proxy_ |^object_id $) /' rất vui nhộn Tôi không sợ regex nữa. – jibiel