Ruby on rails 员工和用户的CanCan

Ruby on rails 员工和用户的CanCan,ruby-on-rails,ruby-on-rails-3,ruby-on-rails-3.2,cancan,Ruby On Rails,Ruby On Rails 3,Ruby On Rails 3.2,Cancan,我有一个票证模型、一个员工模型和一个用户模型 用户和员工可以创建票证,但员工也可以为其分配票证。因此,user\u id是指票据的创建者,employee\u id是指指定的员工(我不确定这是否是最佳方式) 票.rb class Ticket < ActiveRecord::Base before_save :default_values after_commit :close_solved after_commit :close_canceled before_creat

我有一个
票证
模型、一个
员工
模型和一个
用户
模型

用户和员工可以创建票证,但员工也可以为其分配票证。因此,
user\u id
是指票据的创建者,
employee\u id
是指指定的员工(我不确定这是否是最佳方式)

票.rb

class Ticket < ActiveRecord::Base
  before_save :default_values
  after_commit :close_solved
  after_commit :close_canceled
  before_create :assign_state

  attr_accessible :description, :title, :employee_department_id, :user_id, :first_name, :last_name , :email, :state_id, :employee_id, :ticket_state, :assign_state

  belongs_to :employee_department
  belongs_to :user
  belongs_to :state
  belongs_to :employee
  has_many :replies

  def default_values
    self.state_id = 3 if self.state_id.nil?
  end

  def to_label
    ticket_state.to_s
  end

  def close_solved
    if self.ticket_state == "solved"
      self.update_column(:ticket_state, "closed (solved)")
      self.save!
    end
  end

  def close_canceled
    if self.ticket_state == "canceled"
      self.update_column(:ticket_state, "closed (canceled)")
      self.save!
    end
  end

  def assign_state
    if self.employee_id.nil?
      self.assign_state = "un-assigned"
    else
      self.assign_state = "assigned"
    end
  end

  Ticket.all.each do |ticket|
    if ticket.ticket_state.blank?
      ticket.ticket_state = 'open'
    end
    ticket.save
  end

end
票务控制员.rb

class TicketsController < ApplicationController
  load_and_authorize_resource

  def index
    @tickets = Ticket.all
    @tickets_grid = initialize_grid(Ticket, :include => [{:user => :user_type}, :employee_department, :state])
  end

  def show
    @ticket = Ticket.find(params[:id])
    @reply = @ticket.replies.build # this for comments on ticket
    @state = State.all # this for a model called State which describe the priority of the ticket (Emergency / High / Normal )
  end

  def new
    @ticket = Ticket.new
  end

  def create
    @ticket = Ticket.new(params[:ticket])
    if @ticket.save
      flash[:notice] = 'Support ticket request created.'
      redirect_to @ticket
    else
      flash[:error] = 'An error occurred please try again!'
      redirect_to '/dashboard'
    end
  end

  def edit
    @ticket = Ticket.find(params[:id])
  end

  def update
    @ticket = Ticket.find(params[:id])
    if @ticket.update_attributes(params[:ticket])
      flash[:notice] = 'Successfuly updated.'
      redirect_to tickets_path
    else
      flash[:error] = 'An error occurred please try again!'
      render @ticket
    end
  end

end
class ticketcontroller[{:用户=>:user\u type},:员工\u部门,:状态])
结束
def秀
@ticket=ticket.find(参数[:id])
@reply=@ticket.replays.build#这是关于ticket的评论
@state=state.all#这适用于描述票据优先级(紧急/高/正常)的称为state的模型
结束
def新
@票子
结束
def创建
@票证=票证。新(参数[:票证])
如果@ticket.save
flash[:notice]=“已创建支持票证请求。”
将_重定向到@ticket
其他的
flash[:error]=“出现错误,请重试!”
将_重定向到“/dashboard”
结束
结束
定义编辑
@ticket=ticket.find(参数[:id])
结束
def更新
@ticket=ticket.find(参数[:id])
if@ticket.update_属性(参数[:ticket])
flash[:notice]=“已成功更新。”
将\u重定向到票证\u路径
其他的
flash[:error]=“出现错误,请重试!”
提交@ticket
结束
结束
结束
我需要允许
员工
能够管理他们分配的票据,并且我需要票据的创建者只查看他创建的票据


如何使用
CanCan
?我愿意接受其他建议,如果不能用
CanCan

实现,那么使用CanCan就相当简单了。下面是一个使用您包含的能力文件的修改部分的快速示例:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new

    # Full access if you're the assigned employee
    if user.has_role? :support_manager
      can :manage, Ticket do |ticket|
        ticket.try(employee) == user
      end
    end

    # Read access only if you created the ticket
    can :read, Ticket do |ticket|
      ticket.try(user) == user
    end

  end
end

使用CanCan实现这一点相当简单。下面是一个使用您包含的能力文件的修改部分的快速示例:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new

    # Full access if you're the assigned employee
    if user.has_role? :support_manager
      can :manage, Ticket do |ticket|
        ticket.try(employee) == user
      end
    end

    # Read access only if you created the ticket
    can :read, Ticket do |ticket|
      ticket.try(user) == user
    end

  end
end

您将看到所有票据,因为在控制器内的索引操作中,您调用:

@tickets = Ticket.all
您可以尝试以下方法:

@tickets = Ticket.accessible_by(current_ability)
通过使用此方法,当前\u用户将看到当前\u用户有权访问的所有票证

更新

您可以在accessible_方法中定义特定访问权限

@tickets = Ticket.accessible_by(current_ability, :manage)
剩下的就是如何定义访问权限

定义访问权限的示例:

if user.has_role? :ticket_manager
  can :manage, Ticket, employee: {:user_id => user.id}
end

您将看到所有票据,因为在控制器内的索引操作中,您调用:

@tickets = Ticket.all
您可以尝试以下方法:

@tickets = Ticket.accessible_by(current_ability)
通过使用此方法,当前\u用户将看到当前\u用户有权访问的所有票证

更新

您可以在accessible_方法中定义特定访问权限

@tickets = Ticket.accessible_by(current_ability, :manage)
剩下的就是如何定义访问权限

定义访问权限的示例:

if user.has_role? :ticket_manager
  can :manage, Ticket, employee: {:user_id => user.id}
end

为了让用户能够阅读他们创建的票据,您只需要在该功能上添加一个条件(见下文)。您可以在
:create
功能上使用相同的条件,当cancan为
#new
#create
操作构建新对象时,它将为您预填充这些属性

# app/models/ticket.rb
class Ticket < ActiveRecord::Base
  # <snip>
  belongs_to :user
  belongs_to :employee
  # <snip>
end


# app/models/user.rb
class User < ActiveRecord::Base
  has_one :employee
end


# app/models/ability.rb
class Ability
  # <snip>
  if user.has_role? :ticket_viewer
    can :create, Ticket
    can :read, Ticket, :user_id => user.id
  end
  if user.employee # && any other necessary conditions
    can :create, Ticket
    can :read, Ticket, :employee_id => user.employee.id
  end
end


# app/controllers/tickets_controller.rb
controller TicketsController < ApplicationController
  load_and_authorize_resource

  def index
    # @tickets = Ticket.accessible_by(current_ability) # cancan's
    # load_and_authorize resource will take care of loading ticket(s) for
    # all controller actions, so I've commented them out
    @tickets_grid = initialize_grid(@tickets, :include => [{:user => :user_type}, :employee_department, :state])
  end

  def show
    # @ticket = Ticket.find(params[:id])
    @reply = @ticket.replies.build # this for comments on ticket
    @state = State.all # this for a model called State which describe the priority of the ticket (Emergency / High / Normal )
  end

  def new
    # @ticket = Ticket.new
  end

  def create
    # @ticket = Ticket.new(params[:ticket])
    if @ticket.save
      flash[:notice] = 'Support ticket request created.'
      redirect_to @ticket
    else
      flash[:error] = 'An error occurred please try again!'
      redirect_to '/dashboard'
    end
  end

  def edit
    # @ticket = Ticket.find(params[:id])
  end

  def update
    # @ticket = Ticket.find(params[:id])
    if @ticket.update_attributes(params[:ticket])
      flash[:notice] = 'Successfuly updated.'
      redirect_to tickets_path
    else
      flash[:error] = 'An error occurred please try again!'
      render @ticket
    end
  end
end
#app/models/ticket.rb
类票证user.id
结束
如果user.employee#&满足任何其他必要条件
can:创建,记录
can:read,Ticket,:employee\u id=>user.employee.id
结束
结束
#app/controllers/tickets\u controller.rb
控制器票证控制器<应用程序控制器
加载和授权资源
def索引
#@tickets=Ticket.accessible_by(当前能力)#cancan's
#加载和授权资源将负责加载的票证
#所有控制器操作,因此我已将其注释掉
@票证网格=初始化网格(@tickets,:include=>[{:user=>:user\u type},:employee\u department,:state])
结束
def秀
#@ticket=ticket.find(参数[:id])
@reply=@ticket.replays.build#这是关于ticket的评论
@state=state.all#这适用于描述票据优先级(紧急/高/正常)的称为state的模型
结束
def新
#@ticket=ticket.new
结束
def创建
#@ticket=ticket.new(参数[:ticket])
如果@ticket.save
flash[:notice]=“已创建支持票证请求。”
将_重定向到@ticket
其他的
flash[:error]=“出现错误,请重试!”
将_重定向到“/dashboard”
结束
结束
定义编辑
#@ticket=ticket.find(参数[:id])
结束
def更新
#@ticket=ticket.find(参数[:id])
if@ticket.update_属性(参数[:ticket])
flash[:notice]=“已成功更新。”
将\u重定向到票证\u路径
其他的
flash[:error]=“出现错误,请重试!”
提交@ticket
结束
结束
结束

为了让用户能够阅读他们创建的票据,您只需要在该功能上添加一个条件(见下文)。您可以在
:create
功能上使用相同的条件,当cancan为
#new
#create
操作构建新对象时,它将为您预填充这些属性

# app/models/ticket.rb
class Ticket < ActiveRecord::Base
  # <snip>
  belongs_to :user
  belongs_to :employee
  # <snip>
end


# app/models/user.rb
class User < ActiveRecord::Base
  has_one :employee
end


# app/models/ability.rb
class Ability
  # <snip>
  if user.has_role? :ticket_viewer
    can :create, Ticket
    can :read, Ticket, :user_id => user.id
  end
  if user.employee # && any other necessary conditions
    can :create, Ticket
    can :read, Ticket, :employee_id => user.employee.id
  end
end


# app/controllers/tickets_controller.rb
controller TicketsController < ApplicationController
  load_and_authorize_resource

  def index
    # @tickets = Ticket.accessible_by(current_ability) # cancan's
    # load_and_authorize resource will take care of loading ticket(s) for
    # all controller actions, so I've commented them out
    @tickets_grid = initialize_grid(@tickets, :include => [{:user => :user_type}, :employee_department, :state])
  end

  def show
    # @ticket = Ticket.find(params[:id])
    @reply = @ticket.replies.build # this for comments on ticket
    @state = State.all # this for a model called State which describe the priority of the ticket (Emergency / High / Normal )
  end

  def new
    # @ticket = Ticket.new
  end

  def create
    # @ticket = Ticket.new(params[:ticket])
    if @ticket.save
      flash[:notice] = 'Support ticket request created.'
      redirect_to @ticket
    else
      flash[:error] = 'An error occurred please try again!'
      redirect_to '/dashboard'
    end
  end

  def edit
    # @ticket = Ticket.find(params[:id])
  end

  def update
    # @ticket = Ticket.find(params[:id])
    if @ticket.update_attributes(params[:ticket])
      flash[:notice] = 'Successfuly updated.'
      redirect_to tickets_path
    else
      flash[:error] = 'An error occurred please try again!'
      render @ticket
    end
  end
end
#app/models/ticket.rb
类票证user.id
结束
如果user.employee#&满足任何其他必要条件
can:创建,记录
can:read,Ticket,:employee\u id=>user.employee.id
结束
结束
#应用程序/控制器/票据