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.