2012-01-25 3 views
14

Dựa trên API Rails 3, sự khác biệt giữa phạm vi và phương thức lớp gần như không tồn tại.Phạm vi so với Phương pháp Lớp trong Rails 3

class Shipment < ActiveRecord::Base 
    def self.unshipped 
    where(:shipped => false) 
    end 
end 

cũng giống như

scope :unshipped, where(:shipped => false) 

Tuy nhiên, tôi thấy rằng tôi là đôi khi nhận được kết quả khác nhau sử dụng chúng.

Trong khi cả hai đều tạo cùng một truy vấn SQL chính xác, phạm vi không phải lúc nào cũng trả về giá trị chính xác khi được gọi. Dường như vấn đề này chỉ xảy ra khi nó được gọi là cùng một cách hai lần, mặc dù trên một lô hàng khác nhau, trong phương pháp. Lần thứ hai nó được gọi, khi sử dụng phạm vi nó trả về cùng một điều nó đã làm lần đầu tiên. Trong khi đó, nếu tôi sử dụng phương thức lớp, nó hoạt động chính xác.

Có một số loại bộ đệm truy vấn xảy ra khi sử dụng phạm vi không?

Edit:

order.line_items.unshipped 

Dòng trên là như thế nào phạm vi đã được gọi. Đơn đặt hàng có nhiều line_items.

Phương thức generate_multiple_shipments đang được gọi hai lần vì thử nghiệm tạo một đơn hàng và tạo các lô hàng để xem có bao nhiêu lô hàng. Sau đó, nó thay đổi thứ tự và tái tạo các lô hàng. Tuy nhiên, group_by_ship_date trả về cùng một kết quả mà nó đã thực hiện từ lần lặp đầu tiên của thứ tự.

def generate_multiple_shipments(order) 
    line_items_by_date = group_by_ship_date(order.line_items.unshipped) 

    line_items_by_date.keys.sort.map do |date| 
    shipment = clone_from_order(order) 
    shipment.ship_date = date 
    line_items_by_date[date].each { |line_item| shipment.line_items << line_item } 
    shipment 
    end 
end 

def group_by_ship_date(line_items)  
    hash = {} 
    line_items.each do |line_item| 
    hash[line_item.ship_date] ||= [] 
    hash[line_item.ship_date] << line_item 
    end 
    hash 
end 
+2

Bạn có thể vui lòng cung cấp một ví dụ (đoạn mã), nơi bạn tin truy vấn được lưu trữ khi được gọi là hai lần. –

+0

Tôi đã thêm thông tin khác vào bài đăng gốc. – blim8183

+0

Kiểm tra nhật ký Rails sẽ cho bạn biết liệu kết quả có được lưu trong bộ nhớ cache hay không. – Sasha

Trả lời

1

Tôi nghĩ lời gọi của bạn không chính xác. Bạn nên thêm phương pháp truy vấn cái gọi là để thực hiện phạm vi, chẳng hạn như all, first, last, tức là .:

order.line_items.unshipped.all 

Tôi đã quan sát thấy một số mâu thuẫn, đặc biệt là trong rspec, được tránh bằng cách thêm các phương pháp truy vấn.

Bạn không đăng mã thử nghiệm, vì vậy thật khó để nói chính xác, nhưng sự tuyệt vời của tôi là sau khi bạn sửa đổi các bản ghi liên quan, bạn phải bắt buộc tải lại vì bộ nhớ truy vấn không phải lúc nào cũng đủ thông minh để phát hiện thay đổi. Bằng cách vượt qua true để hiệp hội, bạn có thể buộc hiệp hội để tải lại và truy vấn để chạy lại:

order.line_items(true).unshipped.all 
+0

Buộc liên kết tải lại dường như đã thực hiện thủ thuật. Tôi vẫn chưa hoàn toàn rõ ràng về cách bộ nhớ cache truy vấn xác định liệu có thay đổi hay không nhưng ít nhất nó đang hoạt động ngay bây giờ. Cảm ơn! – blim8183

+0

@ blim8183 Tôi không biết câu trả lời cho điều này, nhưng tôi nghi ngờ rằng điều này có thể là một thiết kế thương mại-off. Vui mừng việc tải lại làm việc cho bạn. –

1

Giả sử bạn đang tham chiếu Rails 3.1, phạm vi có thể bị ảnh hưởng bởi phạm vi mặc định có thể được xác định trên mô hình của bạn trong khi phương thức lớp sẽ không.