I am trying to build a blog where there will be 2 users admin and normal user.Admin can view every post and comment .Whereas normal user can view his only post and comment .I have applied my logic but it is not working .In my code every user can view each other post and comment which I don't want .I have uploaded my code at github
link
[ability.rb]
class Ability
include CanCan::Ability
def initialize(user)
unless user
else
case user.roles
when 'admin'
can :manage, Post
can :manage, Comment
when 'user'
can :manage, Post, user_id: user.id
can :manage, Comment, user_id: user.id
end
end
class PostsController < ApplicationController
before_action :authenticate_user!
authorize_resource
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def show
#post = Post.find(params[:id])
end
def create
#post = Post.new(post_params)
#post.user = current_user
if #post.save
redirect_to #post
else
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :body))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
[comment_controller]
class CommentsController < ApplicationController
authorize_resource
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment].permit(:name, :body))
#comment.user = current_user
#comment.save
redirect_to post_path(#post)
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
end
[user.rb]
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts
has_many :comments
end
[post.rb]
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true
belongs_to :user
end
[comment.rb]
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
Firstly...
CanCan is no longer maintained; CanCanCan should be added to your Gemfile:
#Gemfile
gem "cancancan"
--
You'll be able to use the following:
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
case user.roles
when "admin" #-> use double quotes for evaluating strings
can :manage, [Post, Comment]
when "user"
can :manage, [Post, Comment], user_id: user.id
end
end
end
--
You also need to make sure you're calling authorize!.
Although authorize_resource is good, in your case, you need to make sure you're sticking to convention...
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
authorize_resource :post
authorize_resource :comment
def create
#post = Post.find params[:post_id]
#comment = #post.comments.new comment_params
#comment.user = current_user
#comment.save
redirect_to #post
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find params[:id]
#comment.destroy
redirect_to #post
end
private
def comment_params
params.require(:comment).permit(:name, :body)
end
end
Most likely you just need to add :read instruction along with :manage to disallow user to view other users posts.
Like this:
class Ability
include CanCan::Ability
def initialize(user)
unless user
else
case user.roles
when 'admin'
can :manage, Post
can :manage, Comment
when 'user'
can :manage, Post, user_id: user.id
can :manage, Comment, user_id: user.id
can :read, Post, user_id: user.id
can :read, Comment, user_id: user.id
end
end
end
end
please refer to this page: https://github.com/ryanb/cancan/wiki/defining-abilities
Hope you have maintain the roles for each users as admin or normal.
you can try this
in ability.rb
include CanCan::Ability
def initialize(user)
case user.role
when User::Roles::ADMIN
can :manage, :all
end
when User::Roles::USER
can :create, Comment, :user_id => user.id
end
end
Hope this will help
Related
I made a app for managing personal library (books and comics) and it was working well but all of the suddent it started to show to all users (new or existing) all the books that were introduced by a given user (it seems to display the entire db); but i have devise and pundit implemented and it was protecting the user information until now.... Need some help solving this issue.
Code follows but if needed some more, please shout.
Thanks in advance.
Book_controller.rb
class BooksController < ApplicationController
before_action :authenticate_user!
def index
unless params[:term].present?
#books = policy_scope(Book)
else
#books = policy_scope(Book)
#books = Book.search_by_full_name(params[:term])
end
#books = Book.order(:title)
respond_to do |format|
format.html
format.csv { send_data #books.to_csv }
format.xls # { send_data #products.to_csv(col_sep: "\t") }
end
#books = Book.paginate(page: params[:page])
end
def show
#book = Book.find(params[:id])
authorize #book
end
def new
#user = User.find(params[:user_id])
#book = Book.new
authorize #book
end
def create
#user = User.find(params[:user_id])
#book = Book.new(book_params)
#book.user = #user
authorize #book
if #book.save
redirect_to user_books_path
flash[:notice] = 'Success. Your book was added to the Library'
else
render "new"
flash[:notice] = 'Book not created. Please try again'
end
end
def edit
#user = User.find(params[:user_id])
#book = Book.find(params[:id])
authorize #book
end
def update
#book = Book.find(params[:id])
#book.update(book_params)
authorize #book
redirect_to user_book_path
end
def destroy
#book = Book.find(params[:id])
#book.destroy
authorize #book
redirect_to user_books_path
end
private
def book_params
params.require(:book).permit(:title, :author, :photo, :comments)
end
end
book_policy.rb
class BookPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.where(user: user)
end
def index?
record.user == user
end
def show?
true
end
def new?
true
end
def create?
true
end
def edit?
true
end
def update?
true
end
def destroy?
record.user == user
end
end
end
application_policy.rb
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
#user = user
#record = record
end
def index?
false
end
def show?
true
end
def create?
true
end
def new?
create?
end
def update?
true
end
def edit?
update?
end
def destroy?
true
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
#user = user
#scope = scope
end
def resolve
scope.all
end
end
end
book.rb
class Book < ApplicationRecord
belongs_to :user
has_many :loans
has_one_attached :photo
validates :title, presence: true
validates :author, presence: true
include PgSearch::Model
pg_search_scope :search_by_full_name, against: [:title, :author],
using: {
tsearch: {
prefix: true
}
}
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |book|
csv << book.attributes.values_at(*column_names)
end
end
end
self.per_page = 12
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
after_create :send_welcome_email
has_many :books
has_many :comics
has_many :wishlists
has_many :loans, through: :books
has_one_attached :photo
private
def send_welcome_email
UserMailer.with(user: self).welcome.deliver_now
end
end
When you reassign the #books instance variable, the previous scope is lost. Try sth like this:
#books = policy_scope(Book).order(:title)
#books = #books.search_by_full_name(params[:term]) if params[:term].present?
respond_to do |format|
format.html { #books = #books.paginate(page: params[:page]) }
format.csv { send_data #books.to_csv }
end
You are overwriting the #books variable many times instead of doing some chaining.
#books = policy_scope(Book)
#books = #books.search_by_full_name(params[:term]) if params[:term].present?
#books = #books.order(:title)
respond_to ...
end
Solved it... I wasn't applying current_user on each book, in views/index... That way, each user had their own books db but when rendering index, it was showing everyone's books, no matter which user created it... It's the simple things, most of the times:P
I am following this tutorial
I am trying to authorize user only If user is admin he should be able to see all post and comments otherwise the normal user can see its own post only .I have read github page but was quite confusing
[post_controller.rb]
class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def show
#post = Post.find(params[:id])
end
def create
#post = Post.new(post_params)
#post.user = current_user
if #post.save
redirect_to #post
else
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :body))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
[comments_controller]
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment].permit(:name, :body))
#comment.user = current_user
redirect_to post_path(#post)
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
end
[ability.rb]
class Ability
include CanCan::Ability
def initialize(user)
unless user
else
case user.roles
when 'admin'
can :manage, Post
can :manage, Comment
when 'user' # or whatever role you assigned to a normal logged in user
can :manage, Post, user_id: user.id
can :manage, Comment, user_id: user.id
end
end
[comment.rb]
class Comment < ActiveRecord::Base
belongs_to :post
end
[post.rb]
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true
end
[user.rb]
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
[migration]
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
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.timestamps
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
end
end
[migration]
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :name
t.text :body
t.references :post, index: true
t.timestamps
end
end
end
[migration]
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
It seems you do not yet have a user relationship to post and comment in which you need in order to identify if the user owns/created the comment/post
Run:
rails generate migration AddUserToPost user:belongs_to
rails generate migration AddUserToComment user:belongs_to
bundle exec rake db:migrate
Then add the association relationships:
post.rb
class Post < ActiveRecord::Base
belongs_to :user
# ..
end
comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
# ..
end
user.rb
class User < ActiveRecord::Base
has_many :posts
has_many :comments
# ..
end
Now you can identify who owns the post/comment, and what posts/comments a user owned/created with something like the following pseudo-code:
# rails console
post = Post.find(1)
post_owner = post.user
comment = Comment.find(1)
comment_owner = comment.user
user = User.find(1)
user_comments = user.comments
user_posts = user.posts
Now, the next step is to auto-associate the logged-in user to newly created posts/comments. This is done through the controllers:
posts_controller.rb
class PostsController < ApplicationController
authorize_resource
# ..
def create
#post = Post.new(post_params)
#post.user = current_user # I assume you have a variable current_user, or if you are using Devise current_user is already accessible
if #post.save
redirect_to #post
else
render :new
end
end
end
comments_controller.rb
class CommentsController < Application
authorize_resource
# ..
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment].permit(:name, :body))
#puts "hhhhhhhhhh#{#comment}"
#comment.user = current_user # I assume you have a variable current_user, or if you are using Devise current_user is already accessible
#comment.save
redirect_to post_path(#post)
end
end
Now, at this point. Whenever a post/comment gets created, the logged-in user is automatically associated to it (as the owner).
Finally, we could just update the Ability class to only authorize users to :edit, :update, :show, and :destroy actions, if the user_id: current_user (logged-in user).
ability.rb
class Ability
include CanCan::Ability
def initialize(user)
# if not logged in (Guest)
unless user
# cant do anything unless you add more `can` here
# else if logged in
else
case user.role
when 'admin'
can :manage, Post
can :manage, Comment
when 'normal' # or whatever role you assigned to a normal logged in user
can :manage, Post, user_id: user.id
can :manage, Comment, user_id: user.id
# If you don't have a role name for a normal user, then use the else condition like Rich Peck's answer. Uncomment the following instead, and then comment the `when 'normal' block of code just above
# else
# can :manage, Post, user_id: user.id
# can :manage, Comment, user_id: user.id
end
end
end
end
Just a final helpful information to the Ability above:
can :manage, Post, user_id: user.id
This is just a shorthand equal to:
can [:show, :edit, :update, :destroy], Post, user_id: user.id
can [:index, :new, :create], Post
You will notice that user_id: user.id is not taken into consideration for :index, :new, and :create because these are :collection methods, and not :member methods. More info here
If you want readability and customizability, you may opt to use the longer one above instead of the shorthand :manage.
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
case user.role
when "admin"
can :manage, :all
else
can :read, Post #-> cannot read comments
end
end
end
The above is how the ability class should look. You can replace the switch/case with if/else.
--
You're missing the evaluation of your objects, specifically with the can? & authorize methods:
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
#post = Post.find params[:post_id]
#comment = #post.comments.new comment_params
#comment.save if authorize! :create, #comment
redirect_to #post
end
def destroy
#post = Post.find params[:post_id]
#comment = #post.comments.find params[:id]
#comment.destroy if authorize! :destroy, #comment
redirect_to #post
end
private
def comment_params
params.require(:comment).permit(:name, :body)
end
end
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def show
#post = Post.find params[:id]
end
end
#app/views/posts/show.html.erb
<%= #post.title %>
<%= render #post.comments if can? :read, #post.comments %>
1) Change this line in PostsController, delete this condition: except [index, show]. Or user could see pages without authorization.
before_action :authenticate_user!
2) Change index action and other with this style. Use - current_user.
def index
if current_user.has_role? :admin
#posts = Post.all.order('created_at DESC')
else
#posts = current_user.posts.order('created_at DESC')
end
end
You can write you abilities in this way
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
case user.role
when "admin"
can :manage, :all
else
can :read, Post, :user_id => user.id
end
end
end
And just load resources of post using ability resource so that it only load post of current user if other than admin
class CommentsController < Application
load_and_authorize_resource
def index
#posts = #posts
end
end
I am getting the following error while trying to delete a user in my Rails 4 App.
Pundit::NotAuthorizedError in UsersController#destroy
not allowed to destroy? this #<User:0x005595f691bd10>
Extracted source (around line #30):
#user = User.find(params[:id])
# debugger
authorize current_user
#user.destroy
redirect_to users_path, :notice => "User deleted."
end
I am giving the User Controller bellow :
class UsersController < ApplicationController
before_filter :authenticate_user!
before_action :set_menu
def index
#users = User.all.page(params[:page]).per(8)
authorize #users
end
def show
#user = User.find(params[:id])
authorize #user
end
def update
#user = User.find(params[:id])
#authorize #user
if #user.update_attributes(secure_params)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
#user = User.find(params[:id])
authorize #user
#user.destroy
redirect_to users_path, :notice => "User deleted."
end
private
def secure_params
params.require(:user).permit(:role)
end
def set_menu
store_menu("User")
end
end
The bellow is my User Model Code
class User < ActiveRecord::Base
enum role: [:admin,:user]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :customer
# has_one :customer, dependent: :destroy
end
The bellow is my User policy file
class UserPolicy < ApplicationPolicy
attr_reader :user, :model
def initialize(user, model)
#user = user
#model = model
end
def index?
#user.admin?
end
class Scope < Scope
def resolve
scope
end
end
end
How to resolve the error on delete or destroy action of a particular user ?
You should be adding a method for delete in the user_policy.rb like below
def destroy?
current_user = #user
end
to get the destroy working.
I am having challenges assigning a current user a role in a team the user is creating. I want to assign the user that creates the team the role of the captain which could be changed later.
I'm currently using the create_asociation method that comes with has_one relationship, as this instantiates the values of the associated model, which i want to be instantiated with the current user but get the error Can't mass assign protected attribute: captain. Captain is a self join model with user as i will like to use captain.teammates and team.captain.
Below are the models involved.
User and Captain Model
class User < ActiveRecord::Base
has_one :profile
has_many :teammates, :class_name => "User", :foreign_key => "captain_id"
belongs_to :captain, :class_name => "User"
belongs_to :team
# before_create :build_profile
after_create :build_default_profile
accepts_nested_attributes_for :profile
attr_accessible :email, :password, :password_confirmation, :profile_attributes, :captain_id
def build_default_profile
Profile.create(user_id: self.id)
end
has_secure_password
before_save { email.downcase! }
before_save :create_remember_token
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
Team Model
class Team < ActiveRecord::Base
has_many :profiles, through: :users
has_one :captain, :class_name => "User", foreign_key: :captain_id
has_one :result, as: :result_table
attr_accessible :teamname, :color, :result_attributes, :captain_attributes
after_create :build_result_table
after_create :build_default_captain
accepts_nested_attributes_for :profiles
accepts_nested_attributes_for :captain
accepts_nested_attributes_for :result
def build_result_table
Result.create(result_table_id: self.id, result_table_type: self.class.name)
end
def build_default_captain
# Team.captain = User
# Captain.create(team_id: self.id, captain_id: user.id)
end
end
User Controller
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update, :destroy]
before_filter :correct_user, only: [:edit, :update]
before_filter :admin_user, only: :destroy
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save!
sign_in #user
flash[:success] = "Welcome to the JHDC Mini Olympics Web Application; Thanks for singing Up"
redirect_to user_profile_path(#user, #profile)
else
flash[:error_messages]
render 'new'
end
end
def show
#user = User.find(params[:id])
end
def index
#users = User.paginate(page: params[:page])
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:success] = "Profile Updated"
redirect_to user_profile_path(#user, #profile)
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted."
redirect_to users_url
end
private
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
end
Team Controller
class TeamsController < ApplicationController
def new
#team = Team.new
end
def create
#team = Team.new(params[:team])
#captain = #team.create_captain(captain: current_user)
if current_user.admin?
if #team.save!
flash[:success] = "Team created."
redirect_to #team
else
flash[:error_messages]
render 'new'
end
else
flash[:error] = "Sorry, you don't have the authority to create a Team"
redirect_to current_user
end
end
def index
#teams = Team.paginate(page: params[:page])
end
def show
#team = Team.find(params[:id])
end
def edit
if current_user.admin?
#team = Team.find(params[:id])
else
flash[:error] = "Sorry you dont have the authourity to edit a Team"
redirect_to current_user
end
end
def update
#team = Team.find(params[:id])
if #team.update_attributes(params[:team])
flash[:success] = "Team Updated"
redirect_to #team
else
render 'edit'
end
end
def destroy
Team.find(params[:id]).destroy
flash[:success] = "Team is deleted."
redirect_to teams_url
end
private
def team_params
params.require(:team).permit(:teamname, :color)
end
end
The admin is currently a way i'm using to restrict the user that can create a team but i plan to use gems like declarative authorization to create role based authorization. Thanks
The error you are getting is because the attribute :captain is not declared as attr_accessible
Either set the attribute :captain in your list of attr_accessible for the User model, or change the code form
Captain.create(team_id: self.id, captain_id: user.id)
to
captain = Captain.new
captain.team_id = self.id
captain.captain_id = user.id
captain.create
in this way, the attribute won't be set by mass-assignment and won't raise the error
Edited
After checking your code twice, just realized that you don't have a Captain model, actually :captain is a relation for the user and a relation from the Team to the User.
So on Team model, take off the build_default_captain stuff and the after_create :build_default_captain, I would say to replace with something like
after_save :set_default_captain
def set_default_captain
if captain_id_changed?
profiles.each do |user|
user.captain = captain
user.save
end
end
end
so every time the captain_id change for the model, you change the captain_id of all its profiles (users)
Then on the Team controller, on the action create, instead of
#team = Team.new(params[:team])
#captain = #team.create_captain(captain: current_user)
do something like
#team = Team.new(params[:team])
#team.captain = current_user
if current_user.admin?
if #team.save!
current_user.update_attribute(:team_id, #team.id)
flash[:success] = "Team created."
redirect_to #team
else
flash[:error_messages]
render 'new'
end
else
flash[:error] = "Sorry, you don't have the authority to create a Team"
redirect_to current_user
end
so on the last part of the code, you set the captain of the team to the current user and set the user team to the current team once its saved, you can also improve the code with current_user.build_team to avoid saving current_user.update_attribute
I have 2 controllers User and Rota. I want the user to be able to create their own Rota but only be able to edit, show and destroy their own. I need to be able to code so that my rotum object belongs to the user object.
ROTA CONTROLLER:
class RotaController < ApplicationController
respond_to :html, :xml, :json
before_action :set_rotum, only: [:show, :edit, :update, :destroy]
def edit
#rotum = #user.rota.find params[:id]
end
def index
#rota = Rotum.all
respond_with(#rota)
end
def show
respond_with(#rotum)
end
def new
#rotum = Rotum.new
respond_with(#rotum)
end
def edit
end
def create
#rotum = Rotum.new(rotum_params)
#rotum.save
respond_with(#rotum)
end
def update
#rotum.update(rotum_params)
respond_with(#rotum)
end
def destroy
#rotum.destroy
respond_with(#rotum)
end
private
def set_rotum
#rotum = current_user.rotums.find(params[:id])
if #rotum.nil?
render :html => "Not authorized", :status => 401
end
end
def rotum_params
params.require(:rotum).permit(:name, :email, :mobile, :category)
end
end
USER CONTROLLER
class UsersController < ApplicationController
before_filter :authenticate_user!
after_action :verify_authorized
def index
#users = User.all
authorize User
end
def show
#user = User.find(params[:id])
authorize #user
end
def update
#user = User.find(params[:id])
authorize #user
if #user.update_attributes(secure_params)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
user = User.find(params[:id])
authorize user
user.destroy
redirect_to users_path, :notice => "User deleted."
end
def edit
#rotum = #user.rota.find params[:id]
end
private
def secure_params
params.require(:user).permit(:role)
end
end
So far my rota allows anyone to create, show, edit and destroy the rota on the rotas page. I only want the user to be able to edit only THEIR OWN rota that they created. For that I have been told tell the rota object to belong to the user object. How can I do this in my controllers or models.
USER MODEL
class User < ActiveRecord::Base
has_many :rota, dependent: :destroy
enum role: [:user, :vip, :admin]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
ROTUM MODEL
class Rotum < ActiveRecord::Base
belongs_to :user
end
I get the error:
NoMethodError at /rota/15
undefined method `rotums' for #
You are not showing your models, so I'm assuming that you have a has_many relationship
class User < ActiveRecord::Base
has_many :rota, dependent: :destroy
end
class Rotum < ActiveRecord::Base
belongs_to :user
end
then in your controller you can use the following:
class UsersController < ApplicationController
....
def edit
#rotum = #user.rota.find params[:id]
end
Note that this will raise an ActiveRecord::RecordNotFound exception if a user is triying to edit a rotum that does not belong to him.
You can avoid that problem with the following:
class UsersController < ApplicationController
....
def edit
#rotum = #user.rota.find_by id: params[:id] # returns nil in case the record does not exist or does not belong to #user
redirect_to "somewhere", alert: 'You cannot edit this element' if #rotum.blank?
end