我认为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 参数传递给搜索调用。
我能想到两种更好的解决方法 - 或者有一个相当于 accessible_by 的 Sphinx,将相关信息作为属性添加到您的索引中 - 或者,如果不是很理想,更简单,只是让公司在我上面的 sn-p 的第一行中返回的 ids 没有将每个公司加载为 ActiveRecord 对象。两者都可能意味着绕过和/或复制 Cancan 的助手。
虽然...也许这可以解决问题,采用后一种方法:
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}
避免加载不必要的 Company 对象,使用 Cancan 帮助程序(前提是它是/返回一个范围),并与 Sphinx/Thinking Sphinx 所期望的完美配合。不过我没用过Cancan,所以这有点猜测。