Một phần lý do tại sao tôi yêu Rails là tôi ghét SQL - tôi nghĩ nó giống như một ngôn ngữ lắp ráp nên được thao tác với các công cụ cấp cao hơn như ActiveRecord. Tôi dường như đã đạt đến giới hạn của cách tiếp cận này, tuy nhiên, và tôi ra khỏi chiều sâu của tôi với SQL.Truy vấn đường ray phức tạp - công đoàn? chọn phụ? Tôi vẫn có thể sử dụng named_scope?
Tôi có một mô hình phức tạp với nhiều hồ sơ phụ. Tôi cũng có một bộ 30-40 tên_scopes thực hiện logic nghiệp vụ từ khách hàng. Những phạm vi này bị xích lại với nhau theo điều kiện, đó là lý do tại sao tôi có những phạm vi joins_
để các kết nối không bị che khuất.
Tôi có một vài trong số chúng không hoạt động đúng hoặc ít nhất là cách khách hàng muốn chúng hoạt động. Đây là một ý tưởng sơ bộ về cấu trúc mô hình, với một vài phạm vi được đặt tên (không phải tất cả những gì cần thiết cho ví dụ) minh họa cách tiếp cận của tôi và chỉ ra các vấn đề của tôi. (xin vui lòng tha thứ cho bất kỳ lỗi cú pháp)
class Man < ActiveRecord::Base
has_many :wives
named_scope :has_wife_named lambda { |n| { :conditions => { :wives => {:name => n}}}}
named_scope :has_young_wife_named lambda { |n| { :conditions => { :wives => {:name => n, :age => 0..30}}}}
named_scope :has_yw_named_v2 lambda { |n| { :conditions => ["wives.name = ? AND wives.age <= 30", n]}}
named_scope :joins_wives :joins => :wives
named_scope :has_red_cat :conditions => { :cats => {:color => 'red'}}
named_scope :has_cat_of_color lambda { |c| { :conditions => { :cats => {:color => c}}}}
named_scope :has_7yo_cat :conditions => { :cats => {:age => 7}}
named_scope :has_cat_of_age lambda { |a| { :conditions => { :cats => {:age => a}}}}
named_scope :has_cat_older_than lambda { |a| { :conditions => ["cats.age > ?", a] }}
named_scope :has_cat_younger_than lambda { |a| { :conditions => ["cats.age < ?", a] }}
named_scope :has_cat_fatter_than lambda { |w| { :conditions => ["cats.weight > ?", w] } }
named_scope :joins_wives_cats :joins => {:wives => :cats}
end
class Wife < ActiveRecord::Base
belongs_to :man
has_many :cats
end
class Cat < ActiveRecord::Base
belongs_to :wife
end
Tôi có thể tìm thấy những người đàn ông có vợ có con mèo mà có màu đỏ VÀ bảy tuổi
@men = Man.has_red_cat.has_7yo_cat.joins_wives_cats.scoped({:select => 'DISTINCT men'})
Và tôi thậm chí có thể tìm thấy những người đàn ông có vợ có mèo có trọng lượng trên 20 kg và trên 6 tuổi
@men = Man.has_cat_fatter_than(20).has_cat_older_than(5).joins_wives_cats.scoped({:select => 'DISTINCT men'})
Nhưng đó không phải những gì tôi muốn. Tôi muốn tìm những người đàn ông có vợ có ít nhất một con mèo màu đỏ và một con mèo bảy tuổi, không cần phải là cùng một con mèo, hoặc để tìm những người đàn ông có vợ có ít nhất một con mèo trên một trọng lượng nhất định và một con mèo lớn hơn một độ tuổi nhất định.
(trong ví dụ tiếp theo, xin vui lòng chịu sự hiện diện của các hợpjoins_
vàDISTINCT
)Tôi có thể tìm thấy những người đàn ông với người vợ tên là Esther
@men = Man.has_wife_named('Esther')
Tôi thậm chí có thể tìm thấy những người đàn ông với người vợ tên là Esther, Ruth HOẶC Ada (ngọt!)
@men = Man.has_wife_named(['Esther', 'Ruth', 'Ada'])
nhưng tôi muốn tìm người đàn ông có vợ tên Esther AND Ruth AND Ada.
Ha ha, chỉ đùa thôi, trên thực tế, tôi cần điều này: Tôi có thể tìm thấy những người đàn ông với vợ dưới 30 tuổi tên là Esther
@men = Man.has_young_wife_named('Esther')
tìm người đàn ông với người vợ trẻ tên là Esther, Ruth hoặc Ada
@men = Man.has_young_wife_named(['Esther', 'Ruth', 'Ada'])
nhưng như trên tôi muốn tìm người đàn ông có vợ nhỏ tên là Esther AND Ruth AND Ada. May mắn thay, mức tối thiểu là cố định trong trường hợp này, nhưng nó sẽ là tốt đẹp để xác định tuổi tối thiểu là tốt.
là có một cách để kiểm tra sự bất bình đẳng với một cú pháp băm, hay bạn luôn luôn phải trở lại
:conditions => ["", n]
- lưu ý sự khác biệt giữahas_young_wife_named
vàhas_yw_named_v2
- Tôi thích là người đầu tiên tốt hơn, nhưng phạm vi chỉ hoạt động cho hữu hạn giá trị. Nếu bạn đang tìm kiếm một người vợ cũ, tôi đoán bạn có thể sử dụnga..100
nhưng sau đó khi một người vợ bước sang tuổi 101, cô ấy bỏ tìm kiếm. (hmm.cô ấy có thể nấu ăn không? j/k)có cách nào để sử dụng phạm vi trong phạm vi không? Tôi rất thích nếu
:has_red_cat
có thể sử dụng:has_cat_of_color
bằng cách nào đó hoặc nếu có cách nào đó để sử dụng phạm vi từ bản ghi con trong phụ huynh, vì vậy tôi có thể đặt phạm vi liên quan đến mèo vào mô hìnhWife
.
tôi thực sự không muốn làm điều này trong SQL thẳng mà không sử dụng named_scope
, trừ khi có cái gì khác thực sự đẹp hơn - gợi ý cho các plugins và không có điều gì đánh giá rất cao, hoặc hướng vào các loại SQL tôi sẽ cần phải học hỏi. Một người bạn đã đề xuất rằng UNION hoặc các tìm kiếm phụ sẽ hoạt động ở đây, nhưng những người này dường như không được thảo luận nhiều trong bối cảnh của Rails. Tôi chưa biết gì về quan điểm - liệu chúng có hữu ích không? Có cách nào để làm cho họ vui vẻ không?
Cảm ơn bạn!
Như tôi đã đi đến St Ives
tôi gặp một người đàn ông với bảy vợ
Mỗi vợ đã bảy bao tải
Mỗi bao có bảy mèo
Mỗi mèo có bảy bộ dụng cụ
Kits, mèo, bao tải, vợ
Bao nhiêu người sẽ đến St Ives?
Đó là câu hỏi thực sự thú vị trong tóm tắt. Và tôi hiểu rằng mô hình của bạn và tên phạm vi có nguồn gốc từ một vần điệu trẻ. Nhưng nó cho phép. Vợ: thuộc về Man? Nghiêm túc? –
vâng, tôi đã nghĩ về điều đó khi tôi viết nó, nhưng bài thơ đã xuất hiện trong đầu tôi và tôi không thể loại bỏ nó. –
Tôi muốn tìm một cách tốt để làm 'UNION' trong phạm vi được đặt tên trong AR. Tôi biết bạn có thể làm chúng trong SQLAlchemy. – mikelikespie