2012-05-09 35 views
7

Tôi đang thêm pg_search vào ứng dụng Rails. Tôi không hoàn toàn hiểu cấu hình, và sẽ đánh giá cao một cú huých nhẹ nhàng đi đúng hướng.Cách định cấu hình tìm kiếm nhiều pg_search trên các mô hình được liên kết trong Rails?

Trước tiên, tôi đã có một trang web nhiều mô hình nhiều hơn hoặc ít hơn được thiết lập và chạy trên ứng dụng của mình. Nhưng tôi muốn mở rộng nó để cũng tìm kiếm trên các mô hình liên quan.

Ví dụ: tôi có các lớp Nhà sản xuất, Ô tô, Mô hình. Hiện tại nếu tôi tìm kiếm "Ford", chỉ nhà sản xuất mới được trả lại. Tôi cũng muốn trả lại tất cả các xe ô tô liên quan (thuộc về Nhà sản xuất) và Kiểu xe (thuộc về Xe hơi).

tôi có thể thấy làm thế nào để làm điều này như một tìm kiếm scoped

class Car 
    pg_search_scope :manufactured_by, :associated_against => { 
    :manufacturer => [:name] 
    } 
end 

Nhưng nếu tôi cố gắng làm điều này trên một multisearch nó không hoạt động

class Car 
    include PgSearch 
    multisearchable :against => [:name], 
    :associated_against => { 
     :manufacturer => [:name] 
     } 
end 

Nó không tạo ra một lỗi, nó chỉ đơn giản là không nhận các hồ sơ liên quan.

Tôi có cảm giác mình đang thiếu một cái gì đó cơ bản trong sự hiểu biết của tôi về cách tất cả điều này phù hợp với nhau. Tôi thực sự đánh giá cao nếu ai đó có thể giúp tôi hiểu điều này, hoặc chỉ cho tôi một nguồn thông tin tốt. Tôi đã được thông qua các thông tin về github và Railscast liên quan, nhưng tôi vẫn còn thiếu một cái gì đó.

Trả lời

12

Không thể tìm kiếm các bản ghi được liên kết với nhiều tìm kiếm, do cách các liên kết đa hình hoạt động trong Rails và SQL.

Tôi sẽ thêm lỗi giải thích tình huống để trong tương lai nó sẽ không gây nhầm lẫn.

Xin lỗi vì sự nhầm lẫn.

Điều bạn có thể làm thay vào đó là xác định phương thức trên Ô tô trả về văn bản bạn muốn tìm kiếm.

class Car < ActiveRecord::Base 
    include PgSearch 
    multisearchable :against => [:name, manufacturer_name] 
    belongs_to :manufacturer 

    def manufacturer_name 
    manufacturer.name 
    end 
end 

Hoặc là thậm chí gọn gàng hơn, bạn có thể ủy:

class Car < ActiveRecord::Base 
    include PgSearch 
    multisearchable :against => [:name, manufacturer_name] 
    belongs_to :manufacturer 
    delegate :name, :to => :manufacturer, :prefix => true 
end 

Nhưng bạn phải chắc chắn rằng các bảng pg_search_documents được cập nhật nếu bạn đã bao giờ thực hiện thay đổi tên cho một trường hợp sản xuất, vì vậy bạn nên thêm :touch => true liên kết của nó:

class Manufacturer < ActiveRecord::Base 
    has_many :cars, :touch => true 
end 

Bằng cách này nó sẽ gọi Ghi callbacks tích cực trên tất cả các hồ sơ xe khi sản xuất được cập nhật, w hich sẽ kích hoạt cuộc gọi lại pg_search để cập nhật văn bản có thể tìm kiếm được lưu trữ trong mục nhập pg_search_documents tương ứng.

+0

hi @nertzy, cảm ơn câu trả lời của bạn. Nó có ý nghĩa hơn nhiều bây giờ! Có thể ': touch' ba gọi trên một mối quan hệ': has_many'? Hay nó chỉ làm việc "lên chuỗi"? Tôi gặp sự cố khi hoàn thành chức năng này. Đánh giá cao bất kỳ ý tưởng nào bạn có thể có. –

+0

khi bạn tạo ủy quyền, bạn có nghĩa là 'delegate: manufacturer_name, ...'? – AlexBrand

+1

Theo [tài liệu cho has_many] (http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html), ': touch' không phải là một tùy chọn. Bạn sẽ cần phải viết giải pháp của riêng bạn. Ngoài ra tôi nghĩ bạn thường không muốn đi theo cách khác bởi vì bạn sẽ được gọi liên lạc trên nhiều hồ sơ nhiều hơn và nó có thể bắt đầu chạy đi, đặc biệt là nếu những hồ sơ cũng chạm vào những người khác sau khi tiết kiệm của họ.Thay vào đó, bạn có thể thiết lập một hook after_save để kiểm tra xem các cột cụ thể có thay đổi hay không, lặp qua has_many với hàm find_each và gọi update_pg_search_document trên mỗi bản ghi – nertzy

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