Я думаю, что более того, accessible_by
, вероятно, является областью действия - которая управляется базой данных / SQL. Sphinx имеет собственный интерфейс запросов, поэтому области ActiveRecord не применяются.
Неэффективный обходной путь (сначала получают все компании):
company_ids = Company.accessible_by(current_ability).collect &:id
@companies = Company.search params[:search],
:include => :order,
:match_mode => :extended,
:page => params[:page],
:with => {:sphinx_internal_id => company_ids}
Обратите внимание на пару вещей: sphinx_internal_id - это первичный ключ индексированной модели - у Sphinx есть собственный уникальный идентификатор с именем id, отсюда и различие. Кроме того: Вы не хотите вызывать paginate
в поисковой коллекции - Sphinx всегда разбивает на страницы, поэтому просто передайте параметр :page
поисковому вызову.
Было бы два лучших обходных пути, о которых я мог бы подумать - либо иметь эквивалент Sphinx accessible_by
, с соответствующей информацией, добавляемой к вашим индексам в качестве атрибутов, либо, проще, если не совсем идеально, просто получить компанию Идентификаторы возвращены в первой строке моего приведенного выше фрагмента без загрузки каждой компании как объекта ActiveRecord. И то и другое, вероятно, будет означать обход и / или дублирование помощников Канкан.
Хотя ... может быть, это поможет, выбрав последний подход:
sql = Company.accessible_by(current_ability).select(:id).to_sql
company_ids = Company.connection.select_values sql
@companies = Company.search params[:search],
:include => :order,
:match_mode => :extended,
:page => params[:page],
:with => {:sphinx_internal_id => company_ids}
Предотвращает загрузку ненужных объектов Компании, использует помощника Cancan (при условии, что он / возвращает область) и аккуратно работает с тем, что ожидает Sphinx / Thinking Sphinx. Хотя я не использовал Cancan, так что это немного догадок.