Reputation: 135
My rails_admin
application is having two roles namely Teacher
and Student
such that every user belongs_to
a role. I am using the gem cancancan
to manage roles.
app/models
class Role < ApplicationRecord
has_many :users
end
class User < ApplicationRecord
belongs_to :role
has_many :projects
end
class Project < ApplicationRecord
belongs_to :user
end
Project
schema
create_table "projects", force: :cascade do |t|
t.string "name"
t.string "description"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_projects_on_user_id", using: :btree
end
Now, I want the project list to show all the data when role
is Teacher
but it should only show those projects where project.user_id == user.id
when the role
is Student
.
That is, the final aim is to allow the role
Student
to see only his/her own projects thereby restricting the role
Student
to see all the projects where as the role
Teacher
should be able to see all the projects.
Upvotes: 0
Views: 1231
Reputation: 135
To get data based on current user
role I made the following changes to models/ability.rb
.
Under the case when user role
is Student
can :read, Project, ["user_id = ?", user.id] do |project|
project.present?
end
It will compare the user_id
in projects
table with the user.id
so, in case of role
Student
it will only fetch the projects created by that student.
Upvotes: 2
Reputation: 4619
The answers provided asume the controllers can be changed and as the questioner points he does not have access to them.
Not sure if cancancan will handle the filtering of records based on view(read) permission on the index views of rails admin with a rule like this:
can :read, Project, user_id: user.id
But on the edit view i know you can configure a has many field to scope it based on the current user like this:
edit do
field :projects do
associated_collection_scope do
current_user = bindings[:controller].current_user
proc { |scope| scope.where(user: current_user) }
end
end
end
Upvotes: 0
Reputation: 1
class User < ApplicationRecord
belongs_to :role
has_many :projects
def projects
if self.role.to_s == "student"
super projects
else
Project.all
end
end
end
Upvotes: 0
Reputation: 1202
There is also another approach to achieve the functionality
create a new column called role in users table
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "role"
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
And in the user model
class User < ApplicationRecord
enum role: [:student, :teacher, ]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :student
end
end
This creates a default role as student when a new user signs up.you can change the role of the user to teacher by simply doing
go to rails console in the terminal using rails c
u = User.find_by_id(1)
# you can change value '1' depending upon your user_id
u.role = "teacher"
u.save
Now the role of the user is teacher.
class ProjectsController < ApplicationController
if current_user.teacher?
@projects = Project.all
else
@project = current_user.projects
end
Upvotes: 0
Reputation: 1
Your controller will have an action to list projects.
Just use a before_action
filter to load projects based on role.
Assuming, you are setting current_user in application's base controller and have association b/w student and project - student has_many projects.
ProjectController
before_action :load_projects, only: [:index]
def index
@projects
end
private
def load_projects
if current_user.role == "Teacher"
@projects = Project.all
elsif current_user.role == "Student"
@projects = current_user.projects
end
end
end
You can also add association between projects and teacher. And user teacher.projects
if you need.
Upvotes: 0