关于ruby on rails:使用has_many定义能力(CanCan):通过关联

defining abilities (CanCan) with has_many :through association

我是铁杆的初学者,一直在搜寻有关此问题的许多建议答案。我已经看过我的情况了,我似乎无法翻译答案。我希望有人能对她有所帮助。
我关注的2个模型是User和Project。每个用户都可以创建一个项目,但是每个用户也可以管理一个项目。为此,我使用管理模型将两个模型连接起来,在User和Project之间创建了has_many:through关系。

user.rb

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

managing.rb

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

project.rb

1
2
3
4
has_one :reverse_managing, foreign_key:"managed_project_id",
                                class_name: "Managing",
                                dependent:   :destroy
has_one :manager, through: :reverse_managing, source: :manager

因此,我有一个名为"初学者"的角色。初学者只能阅读项目,但那些选择担任项目经理的人除外。还应该允许管理人员编辑和更新他们正在管理的项目。

以下是我在能力.rb

中对此的尝试

1
2
3
4
5
6
7
8
9
10
11
12
 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

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

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

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

这就是在projects_controller

中出现的内容

1
2
3
4
def edit
  @project = Project.find(params[:id])
  authorize! :edit, @project
end

如果有人可以帮助我,我将睡个快乐的人

更新

这是什么角色? User.rb

中的方法

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

更新

我为用户分配了错误的role_id。更正此错误后,当我尝试打开包含编辑链接的项目视图时,收到一条错误消息。

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


问题在这里:

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

康康能力条件只能使用数据库列(根据康康维基)。在这里可以期望manager_id是Project模型中的一列,实际上并非如此。您的模型如下所示:

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

manager_id是"管理"中的字段,而不是Project中的字段。

解决方法是使用另一个Wiki页中所述的阻止条件。我没有测试过,但是我认为以下方法可以工作-

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