如何在rails中的scoped类上使用分页?

时间:2016-08-27 18:18:08

标签: ruby-on-rails pagination

我正在创建一个带有很长维基列表的应用程序(它们就像帖子一样)。我在应用程序中使用Pundit。我找到了两个用于分页的宝石,will_paginatekaminari

这就是WikiController的样子:

class WikisController < ApplicationController
  def index
    if current_user == nil
      @wikis = Wiki.visible_to_all
    else
      @wikis = policy_scope(Wiki) #pundit
    end

visible_to_all是一个自制范围,可向非管理员用户显示所有非私人Wiki。

#on Wiki.rb (model)
scope :visible_to_all, -> {where(private: [false, nil])}

无论如何,现在我有了大量的维基,并希望对它们进行分页。 will_paginate说要在相关控制器上执行此操作:

 class UserController

  def index
    @users = User.paginate(:page => params[:page], :per_page => 5)
  end

Kaminari说要在控制器上执行此操作:

@users = User.order(:name).page params[:page]

在我的情况下,@users将是@wikis,因为我的范围是Wikis;但@wikis已用于范围界定。如何维护我的范围并对我的Wiki进行分页?

编辑:wiki_policy.rb:

 def resolve
     wikis = []
     if user.role == 'admin'
       wikis = scope.all # if the user is an admin, show them all the wikis
     elsif user.role == 'premium'
       all_wikis = scope.all
       all_wikis.each do |wiki|
         if wiki.private == false || wiki.private == nil || wiki.user == user || wiki.users.include?(user)
           wikis << wiki # if the user is premium, only show them public wikis, or that private wikis they created, or private wikis they are a collaborator on
         end
       end
     else # this is the lowly standard user
       all_wikis = scope.all
       wikis = []
       all_wikis.each do |wiki|
         if wiki.private == false || wiki.users.include?(user)
           wikis << wiki # only show standard users public wikis and private wikis they are a collaborator on
         end
       end
     end
     wikis # return the wikis array we've built up
   end

1 个答案:

答案 0 :(得分:0)

Wiki.visible_to_allpolicy_scope(Wiki)都会返回ActiveRecord::Relation,这可以通过链接其他函数来扩展范围。

要从特定范围(或关系)获取页面,您需要做的就是将.paginate附加到它,如下所示:

@wikis = policy_scope(Wiki).paginate(:page => params[:page], :per_page => 5)

编辑:至于将visible_to_all - 范围集成到Pundit范围,您可以这样做:

def resolve
  if user.present?
    # current_user is present, get the normal scope here
  else
    scope.where(private: [false, nil])
  end
end