rails cancancan has_many through ability

时间:2016-06-05 11:49:48

标签: ruby-on-rails cancancan

company.rb:

class Company < ActiveRecord::Base
  has_many :companies_admins, dependent: :destroy
  has_many :supervisors, through: :companies_admins
end

companies_admin.rb:

class CompaniesAdmin < ActiveRecord::Base
    belongs_to :company
    belongs_to :supervisor, foreign_key: "admin_id"
end

supervisor.rb:

class Supervisor < Admin
    has_many :companies_admins, foreign_key: "admin_id"
    has_many :companies, through: :companies_admins, foreign_key: "admin_id"
end

我使用cancancan gem。我的能力.rb:

    class Ability
      include CanCan::Ability

      def initialize(user)
        user ||= Admin.new # guest user (not logged in)
        if user.type == "Administrator"
            can :manage, :all
        elsif user.type == "Supervisor"
            can :manage, Company, companies_admins: {supervisor: { :id => user.id } }
        end
  end
end

companies_controller.rb:

class CompaniesController < ApplicationController
    load_and_authorize_resource only: [:new, :create, :edit, :update, :index, :show, :destroy]
    load_and_authorize_resource :supervisor
    load_and_authorize_resource through: :supervisor
...
end

我只需要监督那些能够管理的公司,与他有关系。例: supervisor

companies_admins

当我打开公司id = 10的页面时,访问被拒绝。

Started GET "/companies/10" for 127.0.0.1 at 2016-06-05 14:23:01 +0300
Processing by CompaniesController#show as HTML
  Parameters: {"id"=>"10"}
  Company Load (0.4ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT 1  [["id", 10]]
  Admin Load (0.3ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT 1  [["id", 4]]
  CompaniesAdmin Load (0.4ms)  SELECT "companies_admins".* FROM "companies_admins" WHERE "companies_admins"."company_id" = $1  [["company_id", 10]]
  Supervisor Load (0.4ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."type" IN ('Supervisor') AND "admins"."id" = $1 LIMIT 1  [["id", 2]]
  Supervisor Load (0.4ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."type" IN ('Supervisor') AND "admins"."id" = $1 LIMIT 1  [["id", 4]]
Redirected to http://localhost:3000/
Completed 302 Found in 20ms (ActiveRecord: 1.9ms)

问题是为什么?如何识别表达式&#34;包括&#34;?

编辑: 非常奇怪,即使是管理员,我也会在更换时拒绝访问:所有公司。为什么呢?

def initialize(user)
    user ||= Admin.new # guest user (not logged in)
    puts user.type
    if user.type == "Administrator"
        can :manage, Company
    elsif user.type == "Supervisor"
        can :show, :all 
    end
end

Started GET "/companies/10" for 127.0.0.1 at 2016-06-05 22:55:49 +0300
Processing by CompaniesController#show as HTML
  Parameters: {"id"=>"10"}
  Admin Load (0.3ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT 1  [["id", 1]]
Administrator
Redirected to http://localhost:3000/
Completed 302 Found in 42ms (ActiveRecord: 2.5ms)
在rails console中

irb(main):005:0> mi = Admin.find(1)
  Admin Load (0.7ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT 1  [["id", 1]]
=> #<Administrator id: 1, type: "Administrator", login: "mars", crypted_password: "8d6ff3f5b32b22726a45b1f8fa69519debf9ec8157d78f8e41...", password_salt: "2oMqwXKIukbKpdEXip", persistence_token: "37127e1f262d4efb44bc458df76e110a6ee78969c94c84a43c...", created_at: "2016-06-04 21:11:18", updated_at: "2016-06-05 09:06:15">
irb(main):006:0> comp = Company.find(10)
  Company Load (0.9ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT 1  [["id", 10]]
=> #<Company id: 10, parent_id: nil, address_id: 6, name: "test_address"...>
irb(main):007:0> ability = Ability.new(mi)
Administrator
=> #<Ability:0x007f09513a0938 @rules=[#<CanCan::Rule:0x007f09513a0898 @match_all=false, @base_behavior=true, @actions=[:manage], @subjects=[Company(id: integer, parent_id: integer, address_id: integer, name: string, info: string, created_at: datetime, updated_at: datetime, site_link: string, vk_link: string, raiting: float, city_id: integer, paid: integer)], @conditions={}, @block=nil>], @rules_index={Company(id: integer, parent_id: integer, address_id: integer, name: string, info: string, created_at: datetime, updated_at: datetime, site_link: string, vk_link: string, raiting: float, city_id: integer, paid: integer)=>[0]}>
irb(main):008:0> ability.can?(:manage, comp)
=> true

我做错了什么?

1 个答案:

答案 0 :(得分:1)

嗯,这是有效的:

class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= Admin.new # guest user (not logged in)
    if user.type == "Administrator"
        can :manage, Company
    elsif user.type == "Supervisor"
        can :manage, Company do |comp|
            comp.supervisor_ids.include?(user.id)
        end
    end
  end
end

companies_controller.rb:

class CompaniesController < ApplicationController
    load_and_authorize_resource only: [:new, :create, :edit, :update, :index, :show, :destroy]
....