0

Users belong to an organization. Users can view all organizations, but can only view users within their organization. When a user views the organization, I have to add filter logic to the view, so @organizations.users becomes @organizations.users.select{|u| can?(:read, u)}.

Is there a way to manage this more transparently or elegantly? Is there a way to get rid of select{|u| can?(:read, u)} or move it to a DRY place?

Relevant code:

class Organization < ActiveRecord::Base
  has_many :users
  ...
end

class Ability
  ...
  can :read, User, :organization => @user.organization
end

organizations/show.html.erb: (current, sucky version)

<% if @organization.users.select{|u| can?(:read, u)}.any? %>
  <h4>Contacts</h4>
  <ul class="unstyled">
    <% for user in @organization.users.select{|u| can?(:read, u)} %>
      <li>
        <%= link_to user, user, class: "user" %>
      </li>
    <% end %>
  </ul>
<% end %>

I want something closer to this view instead:

organizations/show.html.erb:

<% if @organization.users.any? %>
  <h4>Contacts</h4>
  <ul class="unstyled">
    <% for user in @organization.users %>
      <li>
        <%= link_to user, user, class: "user" %>
      </li>
    <% end %>
  </ul>
<% end %>

Update:

I'm avoiding accessible_by because I have an ability definition that uses a block.

class Ability
  ...
  can :read, User, :organization => @user.organization
  can :read, User do |user|
    user.is? :technical_contact
  end
end

I know that accessible_by can work with blocks, but only if a SQL fragment is provided. Since my users have many roles and are stored as a bitmask, I don't have a SQL fragment.

Anson
  • 6,575
  • 2
  • 39
  • 33

1 Answers1

0

CanCan has built in support for this with the accessible_by method that is available on your active record models.

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

Tomdarkness
  • 3,800
  • 2
  • 21
  • 26
  • This is a good suggestion, but I'm avoiding `accessible_by` because I have an ability definition that uses a block. I updated the question to clarify, but will accept your answer or at least vote it up if there is a better way for my scenario. – Anson Nov 06 '12 at 16:45