21

Tôi có nguồn cấp dữ liệu thẻ và nguồn cấp dữ liệu của bạn bè. Tôi muốn kết hợp cả hai và xây dựng nguồn cấp dữ liệu "tất cả" cuối cùng.Cách kết hợp hai phạm vi với OR

Đối với người bạn nuôi:

class Post < ActiveRecord::Base 
    scope :friendfeed, lambda{|x| followed_by} 

    def self.followed_by(user) 
    where("user_id IN (?) OR user_id = ?", user.watched_ids, user.id) 
    end 
end 

Đối với thức ăn chăn nuôi tag:

class Post < ActiveRecord::Base 
    scope :tagfeed, lambda{|x| infatuated_with} 

    def self.infatuated_with(user) 
    joins(:attachments).where("attachments.tag_id IN (?)", user.tags).select("DISTINCT pages.*") 
    end 
end 

Và tôi sẽ gọi một cái gì đó như thế này từ bộ điều khiển (Tôi đang sử dụng Kaminari đá quý cho pagination):

@tag_feed = Post.tagfeed(current_user).page(params[:page]).per(21) 
@friend_feed = Post.friendfeed(current_user).page(params[:page]).per(21) 

Bây giờ tôi muốn có một nguồn cấp dữ liệu phổ dụng, nhưng tôi bị mất. Phạm vi có nghĩa là để thu hẹp, nhưng trong trường hợp này tôi đang cố gắng để làm một hoạt động OR. Thực hiện các công cụ như

@mother_of_all_feed = @tag_feed + @friend_feed 

sẽ không cần thiết và tôi sẽ không thể kiểm soát số lượng bài đăng xuất hiện trên một trang. Làm thế nào tôi có thể đi về việc này? Cảm ơn!

Bằng cách này, cho thẻ tôi có hiệp hội được thành lập như thế này:

class Post < ActiveRecord::Base 
    has_many :attachments 
    has_many :tags, :through => :attachments 
end 

class Tag < ActiveRecord::Base 
    has_many :attachments 
    has_many :posts, :through => :attachments 
end 

class Attachment < ActiveRecord::Base 
    belongs_to :tag 
    belongs_to :post 
end 

Trả lời

4

Trả lời câu hỏi của riêng tôi. Tôi nghĩ tôi đã tìm ra cách.

where("pages.id IN (?) OR pages.id IN (?)", 
    Page.where(
     "user_id IN (?) OR user_id = ?", 
     user.watched_ids, user.id 
), 
    Page 
    .joins(:attachments) 
    .where("attachments.tag_id IN (?)", user.tags) 
    .select("DISTINCT pages.*") 
) 

Có vẻ như bạn đang làm việc cho đến nay, hy vọng đây là điều đó!

+6

Bạn có hài lòng với hiệu suất của nó không? Có vẻ như bạn nhận được 4-5 truy vấn ở đây. Có vẻ như bạn có hai lựa chọn: viết truy vấn SQL thô hoặc sử dụng đá quý yêu thích của tôi. Nó cho phép thực hiện OR và hỗ trợ tính năng 'in' dẫn đến truy vấn SQL lồng nhau. Hãy xem: https://github.com/ernie/squeel. Tôi đã cố gắng "quảng cáo" nó vài lần, như ở đây: http://stackoverflow.com/a/10551561/1322562, nhưng chỉ có ít người thích nó. Tôi tự hỏi tại sao. Với squeel bạn có thể tái sử dụng phạm vi của bạn và xây dựng truy vấn phức tạp trong Ruby thuần túy, như: 'Product.where {(id.in Product.ruby) | (id.in Product.rails)}' thông qua truy vấn SQL đơn (!!!) ! – jdoe

+0

Không hài lòng, nhưng tôi chỉ đang tạo mẫu để nó ổn. Tôi sẽ xem xét squeel. Cảm ơn! – Vlad

17

Có yêu cầu kéo đường ray cho tính năng này (https://github.com/rails/rails/pull/9052), nhưng trong thời gian chờ đợi, một số đã tạo bản vá khỉ mà bạn có thể đưa vào trình khởi tạo cho phép bạn hoặc phạm vi và điều khoản trong một truy vấn và cung cấp cho bạn một ActiveRecord::Relation:

https://gist.github.com/j-mcnally/250eaaceef234dd8971b

với điều đó, bạn sẽ có thể hOẶC phạm vi của bạn như thế này

Post.tagfeed(current_user).or.friendfeed(current_user) 

hoặc viết một phạm vi mới

scope :mother_of_all_feed, lambda{|user| tagfeed(user).or.friendfeed(user)} 
+3

Một số lời chỉ trích mang tính xây dựng sẽ được đánh giá cao từ bất kỳ ai đã từ chối điều này. Nó giải quyết vấn đề, và không tạo ra các truy vấn lồng nhau. – keithepley

+3

HOẶC sẽ được thêm vào Rails 5.0: https://github.com/rails/rails/pull/16052 –

+1

Có, 'OR' đã được thêm vào' ActiveRecord :: Relation # hoặc' trong Rails 5 - http://nithinbekal.com/posts/rails-5-features/ – leviathan

Các vấn đề liên quan