Função de Rails, Devise, CanCan, Rolify e User Company

Durante o desenvolvimento de um aplicativo da web, me deparei com um problema com os usuários tendo uma função por empresa.

Por exemplo, você tem um usuário que pode gerenciar duas empresas. Ele criou a primeira empresa e, portanto, é o proprietário e administrador dessa empresa, mas foi convidado para uma segunda empresa, onde tem acesso limitado de conteúdo, então é o moderador dessa empresa.

No nível dos dados, tenho uma tabela User criada pelo Devise, uma tabela Companies e um Role que o Rolify criou para mim.

Porque eu quero saber qual usuário tem qual função em uma empresa; Preciso de uma tabela para armazenar seus IDs, então criei uma tabela de unidades.

create_table :unities do |t|
t
.integer :role_id
t
.integer :user_id
t
.integer :company_id

t
.timestamps
end

Depois disso, criei um modelo chamado Unity, que usarei para facilitar a manipulação de funções.

unit.rb

class Unity < ActiveRecord::Base

attr_accessible
:role_id, :user_id, :company_id

belongs_to
:role
belongs_to
:company
belongs_to
:user

end

e também adicionei associações a modelos de empresa, função e usuário.

user.rb

class User < ActiveRecord::Base
rolify


cattr_accessor
:current_role

has_many
:unities
has_many
:roles, through: :unities
has_many
:companies, through: :unities

end

Eu adicionei current_role para que eu possa verificar qual função o usuário possui em uma empresa em que ele está, mas eu irei falar sobre isso mais tarde

role.rb

class Role < ActiveRecord::Base

has_many
:unities
has_many
:users, through: :unities
has_many
:companies, through: :unities

end

company.rb

class Company < ActiveRecord::Base

cattr_accessor
:current

has_many
:unities
has_many
:users, through: :unities
has_many
:roles, through: :unities


end

Aqui adicionei uma empresa atual, para poder verificar em qual empresa está ativa irei utilizá-la mais tarde.

O que é cattr_accestor?

http://www.cowboycoded.com/2010/04/20/ruby-cattr_accessor-vs-attr_accessor/

Depois de definir associações entre essas três tabelas, podemos agora definir funções e habilidades em Ability.rb que é usado por CanCan

Mas antes disso, precisamos encontrar uma função de usuário atual.

Como um usuário pode gerenciar várias empresas, mas em níveis diferentes, primeiro precisamos encontrar em qual empresa ele está atualmente, e podemos obter isso nos parâmetros.

Portanto, em um ApplicationController, adicione dois métodos.

class ApplicationController < ActionController::Base

before_filter
:initialize_company, :initialize_user_role


def initialize_company
if params.has_key?(:company_id)
Company.current = Company.find(params[:company_id])
end
end

def initialize_user_role
unless Company.current.nil?
User.current_role = Unity.where(company_id: Company.current.id, user_id: current_user.id).first.role.name
end
end
end

E agora estamos prontos para criarability.rb

class Ability
include
CanCan::Ability

def initialize(user)

user
||= User.new

if User.current_role == 'admin'
can
:manage, :all
else
if User.current_role == 'moderator'
can
:read, Products
can
:update, Products
cannot
:destroy, Products
cannot
:create, Products

cannot
:manage, Client
end

can
:read, :all
end
end
end

Em ApplicationController, podemos obter current_role e compará-lo com a função que desejamos.

if User.current_role == 'admin'

Neste artigo, expliquei como as coisas devem funcionar e o princípio básico da criação de uma função por empresa e usuário. No próximo artigo, descreverei como alterar as permissões do usuário e como adicionar funções aos usuários.

E aqui está a essência para uma melhor visualização

https://gist.github.com/vmarcetic/6049929

Esta é apenas minha maneira de fazer as coisas. Se você tem alguma sugestão, ou sabe como fazer melhor, escreva um comentário.