简体   繁体   中英

Rails 5 with CanCanCan - How to filter list for an index action

I'm making a system for study purposes.

This system controls the hospital shifts for the user. An user should only see his shifts.

I'm using CanCanCan for the authorization control.

So for the index page the controller action I have:

class UsersController < ApplicationController
    def index
        @users = User.all
    end
end

In the index.html.erb

<% @shifts.each do |shift| %>
    <% if can? :read, shift %>
      <tr>
          <td><%= shift.date %></td>
      </tr>
    <% end %>
<% end %>

In the ability I have:

class Ability
    include CanCan::Ability

    def initialize(user)
        if user
            can :manage, Shift, user_id: user.id
        end
    end
end

I want to show a message to the user if he doesn't have any shifts.

But using the can method in index html page because if the list is not empty but there is no shift the current user can see I can't use an empty method direct in the @shift.

Is it possible to filter the list in the index action in user controller?

You're asking a few different questions here, and it's hard to answer them individually, so I'm going to take a more broad approach in hopes of answering some of the underlying questions I believe you're having.

First thing's first: Cancancan does not do anything that relates to querying your database. Cancancan leaves that up to you.

I'm not seeing where @shifts is defined, so I'm going to assume it's in your ShiftsController — whereas the index action is supposed to show a given user's shifts.

A given user is usually the current_user in Rails applications — this authentication is done by something such as Devise. If your associations are setup correctly, you're able to do @shifts = current_user.shifts

But in the case that you want to, say, filter the shifts by user — such as having a RESTful route of /users/:id/shifts — you would have routes that look like this:

resources :users do 
  member do
    get :shifts => 'users#shifts'
  end
end

which would map to your UsersController with a method shifts .

Inside that method you'd have an :id param with the value that you'd expect from your show action.

@shifts = Shift.where(:user_id => params[:id])

Now, if you wanted to filter shifts on your ShiftsController#index method, you could have something like this:

@shifts = Shift.where(:user_id => params[:user_id])

and your URL would look like, presumably, /shifts?user_id=1

Now, if a user doesn't have any shifts, @shifts will return an empty array — indicative of no rows that match your database query. Therefore, you can do some simple logic in your view,

<% if @shifts.empty? %> No shifts. <% else %> ... things to list shifts <% end %>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM