2012-02-01 8 views
9

Ví dụ, hãy xem xét đoạn mã sau (trong một mô hình):Có cách nào tốt để DÙNG lên phạm vi/vị ngữ sao chép logic?

scope :popular, where("views >= 250 OR (views >= 10 AND avg_rating >= 4.75)") 

def popular? 
    views >= 250 or views >= 10 && avg_rating >= 4.75 
end 

điều kiện đầu tiên là SQL, thứ hai là ruby, nhưng vẫn còn, có một sự trùng lặp rõ ràng. Có cách nào tốt để DRY nó lên? Thực hành tốt nhất cho những trường hợp như thế nào?

Trả lời

2

Có nhiều lý do tốt để có cả hai vì vậy tôi có thể xem xét việc này (tất cả trong mô hình):

VIEWS_QUALIFIER = 250 
RATING_VIEWS_QUALIFIER = 10 
RATING_QUALIFIER = 4.75 

scope :popular, where("views >= ? OR (views >= ? AND avg_rating >= ? ", 
       VIEWS_QUALIFIER, RATING_VIEWS_QUALIFIER, RATING_QUALIFIER) 

def popular? 
    views >= VIEWS_QUALIFIER or 
    (views >= RATING_VIEWS_QUALIFIER && avg_rating >= RATING_QUALIFIER) 
end 
+0

Hình như có một lỗi đánh máy trong định nghĩa phạm vi ... – Alexis

+0

vâng. Tôi sửa nó rồi. –

0
def popular? 
    !!self.class.popular.includes? self 
end 
+0

Sẽ tư vấn chống lại ở trên vì điều này sẽ tải lên tất cả các hồ sơ phổ biến chỉ để kiểm tra một mục là phổ biến. Có thể 'self.class.popular.exists? (Id)' có thể hoạt động –

+2

@ThongKuah cũng có một vấn đề khác với tất cả các giải pháp tương tự - phương thức này có thể trả về kết quả sai khi đối tượng nằm trong một 'bẩn' và 'xem' hoặc' avg_rating 'được thay đổi nhưng không được lưu – Alexis

+1

Luôn luôn có một nơi để học tập trong SO. TY cho ý kiến! :) – fuzzyalej