7

Tôi có hai kiểu ContentContentType. Trong Mô hình nội dung tôi có thể làm:"Không bằng" tên phạm vi trong đường ray với Mongoid

def get_all_content_except_poking_message 
    Content.all.where(:name.ne => "no forking, just poking") 
end 

Bây giờ, tôi đang cố gắng áp dụng phạm vi trên ContentType. Trong mô hình Nội dung một lần nữa:

# Associations 
belongs_to :content_type 

def get_all_content_except_certain_content_type(content_type) 
    Content.all.where(:content_type.name.ne => content_type) 
end 

nhưng lỗi cho thấy cú pháp sai của việc áp dụng phạm vi trên trường của hiệp hội.

Cách đúng để áp dụng phạm vi cho các trường của hiệp hội trong mô hình là gì?

Ngoài ra tôi đang sử dụng đá quý has_scope. Tôi có thể áp dụng cùng một bộ lọc trong bộ điều khiển không? Một cái gì đó như:

@contents = apply_scopes(
    if params[:type] 
    @content_type = ContentType.find_by_slug(params[:type]) 
    @content_type.contents.all 
    else 
    Content.all.where (:content_type.name.ne => "blogs") 
    end 
) 

Cập nhật

Để làm rõ, đây là sản phẩm IRB:

irb(main):020:0> ContentType.all(:name=>"blogs").count 
=> 1 

irb(main):023:0> Content.last.content_type.name 
=> "blogs" 

irb(main):024:0> Content.all.where(:content_type => {:name => {'$ne' => "blogs"}}).count 
=> 0 

irb(main):026:0> Content.all.count 
=> 4 

Trả lời

5

Câu trả lời nhanh chóng là một truy vấn máy chủ MongoDB hoạt động chỉ trên một bộ sưu tập duy nhất. Không có sự tham gia nào vượt qua các bộ sưu tập. Bạn đang truy vấn vào bộ sưu tập nội dung, nhưng chỉ định một trường trong bộ sưu tập content_types.

Bạn có thể sử dụng nhúng để đưa hai mô hình vào một bộ sưu tập và sau đó truy vấn của bạn có thể hoạt động với trường tài liệu được nhúng (phụ).

Tôi có thể cung cấp thêm chi tiết nếu bạn muốn, nhưng hy vọng điều này sẽ giúp bạn vượt qua sự ngạc nhiên hiện tại.

Phụ lục theo yêu cầu mà không cần nhúng:

Lưu ý quan trọng: truy cập dữ liệu từ nhiều bộ sưu tập sẽ đòi hỏi nhiều truy vấn, ít nhất một truy vấn mỗi bộ sưu tập.

Ví dụ sau dựa trên những gì tôi có thể trích xuất từ ​​bài đăng của bạn, với các sửa đổi để hoạt động như bạn muốn cho các phương pháp của mình. Truy vấn "không bằng" làm cho việc sử dụng kiến ​​thức về triển khai liên kết chỉ là câu trả lời nhanh cho bây giờ, nhưng cấu trúc liên kết khá rõ ràng từ việc kiểm tra. Cũng lưu ý rằng các truy vấn Moped thực tế để MongoDB hiển thị trong nhật ký Rails thích hợp.

Tôi không quen thuộc với các thông tin cụ thể về plataformatec/has_scope. Mongoid có phạm vi riêng mà bạn nên điều tra, tôi sẵn sàng trợ giúp khi bạn đến đó.

app/models/content_type.rb

class ContentType 
    include Mongoid::Document 
    field :name, type: String 
    has_many :contents 
end 

app/models/content.rb

class Content 
    include Mongoid::Document 
    field :name, type: String 
    belongs_to :content_type 

    def self.get_all_content_except_poking_message 
    Content.where(:name.ne => "no forking, just poking") 
    end 

    def self.get_all_content_except_certain_content_type(content_type_name) # 2 queries - one each for ContentType and Content 
    content_type = ContentType.where(:name => content_type_name).first 
    Content.where(:content_type_id.ne => content_type.id) 
    end 
end 

test/unit/content_test.RB

require 'test_helper'

class ContentTest < ActiveSupport::TestCase 
    def setup 
    Content.delete_all 
    ContentType.delete_all 
    end 

    test "not equal blogs" do 
    blogs = ContentType.create(:name => "blogs") 
    tweets = ContentType.create(:name => "tweets") 
    blogs.contents << Content.create(:name => "no forking, just poking") 
    tweets.contents << Content.create(:name => "Kilroy was here") 
    assert_equal 2, ContentType.count 
    assert_equal 2, Content.count 
    puts "all content_types: #{ContentType.all.to_a.inspect}" 
    puts "all contents: #{Content.all.to_a.inspect}" 
    puts "get_all_content_except_poking_message: #{Content.get_all_content_except_poking_message.to_a.inspect}" 
    puts "get_all_content_except_certain_content_type(\"blogs\"): #{Content.get_all_content_except_certain_content_type("blogs").to_a.inspect}" 
    end 
end 

cào thử nghiệm

Run options: 

# Running tests: 

[1/1] ContentTest#test_not_equal_blogsall content_types: [#<ContentType _id: 51ded9d47f11ba4ec1000001, name: "blogs">, #<ContentType _id: 51ded9d47f11ba4ec1000002, name: "tweets">] 
all contents: [#<Content _id: 51ded9d47f11ba4ec1000003, name: "no forking, just poking", content_type_id: "51ded9d47f11ba4ec1000001">, #<Content _id: 51ded9d47f11ba4ec1000004, name: "Kilroy was here", content_type_id: "51ded9d47f11ba4ec1000002">] 
get_all_content_except_poking_message: [#<Content _id: 51ded9d47f11ba4ec1000004, name: "Kilroy was here", content_type_id: "51ded9d47f11ba4ec1000002">] 
get_all_content_except_certain_content_type("blogs"): [#<Content _id: 51ded9d47f11ba4ec1000004, name: "Kilroy was here", content_type_id: "51ded9d47f11ba4ec1000002">] 
Finished tests in 0.046370s, 21.5657 tests/s, 43.1313 assertions/s. 
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips 

Đối với trường hợp đơn giản này, bạn có thể "đơn giản hóa" bởi xuất phát từ bình thường hóa quan hệ chặt chẽ, ví dụ, chỉ cần thêm một "content_type_name" trường thành Nội dung có các giá trị chuỗi như "blog".

Nhưng để tận dụng lợi thế của MongoDB, bạn không nên ngần ngại nhúng.

Hy vọng điều này sẽ hữu ích.

+0

Gary, cảm ơn câu trả lời của bạn. Nếu liên kết được nhúng không phải là một tùy chọn, có cách nào khác để giả lập liên kết không? Sẽ thực sự đánh giá cao nếu bạn cung cấp một số mã nhắm mục tiêu kịch bản của tôi làm ví dụ. :) – Annie

+0

Annie, ví dụ trong câu trả lời ở trên nhắm mục tiêu kịch bản của bạn bằng cách sử dụng tham chiếu/liên kết và không nhúng. Vui lòng kiểm tra mã cho Nội dung :: get_all_content_except_certain_content_type trả lời chính xác câu hỏi của bạn với tìm nạp hai giai đoạn cần thiết. –