Вопрос

I have a groups page, where a list of all of its members is displayed. The Code of the GroupsController#show looks something like this

  def show
    if @group
      @members = @group.members.order(:last_name, :first_name)
      @members = @members.page(params[:page]).per_page(25) # pagination
    end
    respond_with @group
  end

We use authorization with CanCan in our application, and I would like to restrict the displayed members to those, that the user can actually :read

Something like this works:

      @members = @group.members.order(:last_name, :first_name).select{|member| can? :read, member}
      @members = @members.paginate(params[:page], per_page: 25)

But as I understand it would destroy the performance advantages of pagination, that is it would first load all the members from the database and then select the visible ones. Swapping it around like

      @members = @group.members.order(:last_name, :first_name)
      @members = @members.page(params[:page]).per_page(25).select{|member| can? :read, member}

won't do either, since the view needs a specific WillPaginate::Collection with meta information like the number of pages, current page etc. - and not a simple Array.

Is there a correct way of doing this like chaining a Proc between the Relation and the Pagination? My google fu is failing me.

The full code can be seen on github

Это было полезно?

Решение

You can use accessible_by first to limit your results to those the current user can view:

@members = @group.members.accessible_by(current_ability).order(:last_name, :first_name
@members = @members.page(params[:page]).per_page(25) # pagination

See https://github.com/ryanb/cancan/wiki/Fetching-Records for more details.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top