2008-09-26 28 views
9

Tôi đã tự hỏi nếu có một cách để sử dụng "find_by_sql" trong một named_scope. Tôi muốn xử lý sql tùy chỉnh như named_scope để tôi có thể kết nối nó với các tên miền hiện có của mình. Nó cũng sẽ là tốt cho việc tối ưu hóa một đoạn mã sql tôi sử dụng thường xuyên.Đóng gói SQL trong một named_scope

Trả lời

10

Trong khi bạn có thể đặt bất kỳ SQL mà bạn thích trong các điều kiện của một phạm vi được đặt tên, nếu bạn sau đó gọi find_by_sql sau đó là 'phạm vi 'vứt bỏ.

Given:

class Item 
    # Anything you can put in an sql WHERE you can put here 
    named_scope :mine, :conditions=>'user_id = 12345 and IS_A_NINJA() = 1' 
end 

này hoạt động (nó chỉ dính chuỗi SQL trong đó - nếu bạn có nhiều hơn một họ nhận được liên kết bằng)

Item.mine.find :all 
=> SELECT * FROM items WHERE ('user_id' = 887 and IS_A_NINJA() = 1) 

Tuy nhiên, điều này không

Items.mine.find_by_sql 'select * from items limit 1' 
=> select * from items limit 1 

Vì vậy, câu trả lời là "Không". Nếu bạn nghĩ về những gì đã xảy ra đằng sau hậu trường thì điều này có ý nghĩa rất nhiều. Để xây dựng các đường ray SQL phải biết làm thế nào nó phù hợp với nhau.
Khi bạn tạo các truy vấn thông thường, select, joins, conditions, v.v ... đều được chia thành các phần riêng biệt. Rails biết rằng nó có thể thêm mọi thứ vào các điều kiện mà không ảnh hưởng đến mọi thứ khác (đó là cách hoạt động của with_scopenamed_scope).

Tuy nhiên, với find_by_sql, bạn chỉ cần cung cấp cho đường ray một chuỗi lớn. Nó không biết điều gì xảy ra ở đâu, vì vậy nó không an toàn cho nó để đi vào và thêm những điều nó sẽ cần phải thêm cho các phạm vi để làm việc.

0

chắc chắn tại sao không

: named_scope: conditions => [sql của bạn]

1

Điều này không giải quyết chính xác những gì bạn đã hỏi, nhưng bạn có thể điều tra 'contruct_finder_sql'. Nó cho phép bạn có thể nhận được SQL của một phạm vi được đặt tên.

named_scope :mine, :conditions=>'user_id = 12345 and IS_A_NINJA() = 1' 
named_scope :additional { 
    :condtions => mine.send(:construct_finder_sql,{}) + " additional = 'foo'" 
} 
Các vấn đề liên quan