Mel Mel - 1 month ago 16
Ruby Question

Rails 5, Rolify - Role Assignment Strategy

I am not very good at learning how to code. I've been trying for 4 years and still struggling to figure out basic concepts.

I haven't found the right starting point so, I'm constantly gap filling for things that might be foundations and I don't know them yet.

I have a Rails 5 app. It has models for user, roles, app_roles and assign_roles.

The associations are:

User

rolify strict: true # strict means you get true only on a role that you manually add
attr_accessor :current_role
belongs_to :organisation


Role

has_and_belongs_to_many :users, :join_table => :users_roles

belongs_to :resource,
:polymorphic => true,
:optional => true


AppRole

[no associations]
Note: this is the resource I'm using to have a CRUD to define roles that the app can use to assign roles to users.

Assign Role

[no associations]
Note: this is the resource I'm using to allow some users to assign roles to some other users.

Organisation

has_many :users


I'm using rolify gem.

My user model has:

class User < ApplicationRecord
rolify strict: true # strict means you get true only on a role that you manually add
attr_accessor :current_role


My Roles table has:

class Role < ApplicationRecord
has_and_belongs_to_many :users, :join_table => :users_roles

belongs_to :resource,
:polymorphic => true,
:optional => true

validates :resource_type,
:inclusion => { :in => Rolify.resource_types },
:allow_nil => true

scopify
end


In my assign_roles controller, I have:

class Users::AssignRolesController < ApplicationController

before_action :authenticate_user!

def index
# if @current_user.is_admin?
@app_roles = AppRole.all
# else
# @app_roles = AppRole.where(category: relevant_category)
# end

# if @current_user.is_admin?
@users = User.all
# else
# @users = current_user.organisation.users.select { |u| u.id != current_user.organisation.owner_id }
# end
end


def create
user = User.find(params[:users])
role = AppRole.find(params[:roles])
# organisation = Organisation.first
# @organisation = Organisation.find(@current_user.organisation)
# byebug

user.add_role role.display_name, @current_user.organisation

flash[:notice] = "Successfully created"
redirect_to action: :index
end

def show
# @users = User.joins(:profiles).where('profiles.organisation_id = ?' @current_user.organisation.id)
# @users = User.all
@current_user.organisation.users
end

def update
end

def destroy

user = User.find(params[:users])
# role = AppRole.find(params[:roles])
assigned_role = user.roles
# user_roles = user.roles
# organisation = Organisation.first
# byebug

user.remove_role assigned_role.name, @current_user.organisation

flash[:notice] = "Successfully created"
redirect_to action: :index
end

end


In my routes file, i have:

resources :users, shallow: true do
scope module: :users do
resources :assign_roles
resources :identities
end
end


In my views/users/assign_roles/index file, I have:

<%= form_tag(url: '/assign_roles', method: :post ) do |f| %>
<div class="row" style="margin-top:50px; margin-bottom: 150px">
<div class="col-md-3 col-md-offset-1">
<%= select_tag "users", options_from_collection_for_select(@users, "id", "full_name"), { class: "chosen-select form-control" } %>
</div>

<!-- # roles -->

<div class="col-md-3 col-md-offset-1">
<%= select_tag "roles", options_from_collection_for_select(@app_roles, "id", "display_name"), :class => 'chosen-select form-control' %>
</div>

<div class="col-md-3 col-md-offset-1">
<div class="form-actions">
<%= submit_tag(value = "Submit") %>
</div>
</div>
</div>
<% end %>


So far, that all looks OK. Im' getting stuck at the next part.

In my views/users/assign_roles/show.html.er

I'm trying to show each user's roles on a view. I want the user that assigned any existing roles to be able to delete them.

I have:

<% @users.each do |user| %>

<td><%= user.roles.count %></td>
<% user.roles.each do |role| %>
<td><%= role.name.titleize %></td>
<td><%= link_to 'Destroy', role, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
<% end %>


My controller for assign_roles is saved in app/controllers/users folder. My views folder for assign roles is saved inside app/views/users/assign_roles

When I try to use the app/users/4/assign_roles form, I get the form to render with the list of AppRoles that are available to be assigned. I don't get any error message. Instead, I get the notice on successful creation. However, when I try to check if a user has a role, I get false.

I can see the server log reads as follows:

Started POST "/users/4/assign_roles?method=post&url=%2Fassign_roles" for ::1 at 2016-10-23 11:50:11 +1100
Processing by Users::AssignRolesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"U80gMQd01SaTcHHnnSFxvRc2u9JvJMFB+5smS9SaN8ZRixQvJRTMbutG0KkoqXL+oMU1aOxX8AURBtuy2Rm5yA==", "users"=>"4", "roles"=>"3", "commit"=>"Submit", "method"=>"post", "url"=>"/assign_roles", "user_id"=>"4"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 4], ["LIMIT", 1]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 4], ["LIMIT", 1]]
AppRole Load (0.2ms) SELECT "app_roles".* FROM "app_roles" WHERE "app_roles"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
Organisation Load (0.4ms) SELECT "organisations".* FROM "organisations" ORDER BY "organisations"."id" ASC LIMIT $1 [["LIMIT", 1]]
Role Load (1.1ms) SELECT "roles".* FROM "roles" WHERE "roles"."name" = $1 AND "roles"."resource_type" = $2 AND "roles"."resource_id" = $3 ORDER BY "roles"."id" ASC LIMIT $4 [["name", "sdfddd"], ["resource_type", "Organisation"], ["resource_id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
(0.1ms) ROLLBACK
HABTM_Roles Load (0.4ms) SELECT "users_roles".* FROM "users_roles" WHERE "users_roles"."user_id" = $1 [["user_id", 4]]
Role Load (0.3ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.5ms) SELECT "roles".id FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 [["user_id", 4]]
Role Load (0.3ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = 1
Role Load (0.4ms) SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 [["user_id", 4]]
Redirected to http://localhost:3000/users/4/assign_roles
Completed 302 Found in 33ms (ActiveRecord: 6.5ms)


I don't know what the ROLLBACK line means but I don't think that usually appears in these log messages when things are working correctly.

Can anyone see what I need to do to get the role assignment working correctly?

organisation model

class Organisation < ApplicationRecord

include LogoUploader[:logo]
include BannerUploader[:banner]


# --------------- associations

has_many :users

# --------------- scopes




# --------------- validations


# --------------- class methods

enum org_type: {
University: 1,
Publicly_Funded_Research_Organisation: 2,
Industry: 3,
Grantor: 4,
Investor: 5,
Policy: 6,

}



# --------------- callbacks

# --------------- instance methods

# --------------- private methods



end

Answer

add resourcify to your organisation model and then try.