使用has_many定义能力(CanCan):通过关联

时间:2013-06-18 17:50:50

标签: ruby-on-rails cancan

我是rails的初学者,并且一直在搜索这个问题的许多建议答案。我似乎无法翻译答案,我已经看到了我的情况。我希望有人能够对此有所了解。 我关心的两个模型是用户和项目。每个用户都可以创建一个项目,但每个用户也可以管理一个项目。为此,我在用户项目之间创建了一个has_many:through关系,使用管理模型连接这两个模型。

user.rb

 has_many :managings, foreign_key: "manager_id", dependent: :destroy
 has_many :managed_projects, through: :managings

managing.rb

belongs_to :manager, class_name: "User"
belongs_to :managed_project, class_name: "Project"

project.rb

has_one :reverse_managing, foreign_key: "managed_project_id",
                                class_name:  "Managing",
                                dependent:   :destroy
has_one :manager, through: :reverse_managing, source: :manager

所以,我有一个名为'初学者'的角色。初学者只能阅读项目,但选择成为项目经理的人除外。还应允许经理编辑和更新他们正在管理的项目。

以下是我在ability.rb中的尝试

 user ||= User.new # guest user (not logged in)
  if user.role? :Admin
    can :manage, :all
  elsif user.role? :Author
    can :read, :all
    can [:create], [Project]
    can [:edit, :update], Project, :user_id => user.id
  elsif user.role? :Beginner
   can :read, :all

   can [:edit, :update], Project, :manager_id => user.id
  end

最后一行似乎不起作用,因为当我查看管理该项目的初学者的项目视图时,我没有看到编辑链接。

以下是我在视图中使用的代码:

<% if can? :update, project  %>
<%= link_to 'Edit', edit_project_path(project) %>
<% end %>

这就是projects_controller

中出现的内容
def edit
  @project = Project.find(params[:id])
  authorize! :edit, @project
end
如果有人可以帮助我,我会睡一个快乐的人

更新

这是角色吗? User.rb中的方法

def role?(role)
  return !!self.roles.find_by_name(role.to_s.camelize)
end

更新

我将错误的role_id分配给用户。在更正此问题后,当我尝试打开包含编辑链接的项目视图时,收到错误消息。

undefined method `manager_id' for #<Project:0xb387f0b0>

1 个答案:

答案 0 :(得分:8)

问题在于:

can [:edit, :update], Project, :manager_id => user.id

cancan能力条件必须仅使用数据库列(根据cancan wiki)。这里可以预期manager_id是Project模型中的一列,实际情况并非如此。你的模型看起来有点像这样:

用户[id,...]
项目[id,...]
管理[manager_id,managed_project_id,...]

manager_id是Managings中的一个字段,而不是Project。

修复是使用另一个wiki page中描述的阻止条件。我没有对它进行测试,但我认为以下内容可行 -

can [:edit, :update], Project do |p|
 p.manager == user
end