2015-09-02 75 views
2

我有一個Rails應用程序有如下型號:軌道4:CanCanCan能力與的has_many:通過關聯

class User < ActiveRecord::Base 
    has_many :administrations 
    has_many :calendars, through: :administrations 
end 

class Calendar < ActiveRecord::Base 
    has_many :administrations 
    has_many :users, through: :administrations 
end 

class Administration < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :calendar 
end 

對於給定的calendar,一個userrole,這是定義在administration加盟模式。

對於每個日曆,用戶只能擁有以下三種角色之一:Owner,EditorViewer

這些角色目前沒有存儲在字典或常量中,只通過不同的方法將其分配給字符串(「Ower」,「Editor」,「Viewer」)。

User模型的驗證通過Devise進行處理,並且current_user方法正在工作。

爲了僅允許登錄用戶訪問應用內資源,我已經在calendarsadministrations控制器中添加了before_action :authenticate_user!方法。

現在,我需要實現一個基於角色的授權系統,所以我只安裝了CanCanCan寶石。

這裏是我想達到的目標:

  • 所有(登錄)user S能創造新的calendar秒。
  • 如果usercalendarowner,那麼他就可以manage屬於此calendar,包括他自己的administrationcalendar所有administration秒。
  • 如果用戶是editorcalendar,那麼他可以readupdate這個日曆,並銷燬他的administration
  • 如果usercalendarviewer,那麼他就可以read這個calendar,並且destroyadministration

爲了實現上述,我想出了以下ability.rb文件:

class Ability 
    include CanCan::Ability 

    def initialize(user, calendar) 
    user ||= User.new 
    calendar = Calendar.find(params[:id]) 
    user can :create, :calendar 
    if user.role?(:owner) 
     can :manage, :calendar, :user_id => user.id 
     can :manage, :administration, :user_id => user.id 
     can :manage, :administration, :calendar_id => calendar.id 
    elsif user.role?(:editor) 
     can [:read, :update], :calendar, :user_id => user.id 
     can :destroy, :administration, :user_id => user.id 
    elsif user.role?(:viewer) 
     can [:read], :calendar, :user_id => user.id 
     can :destroy, :administration, :user_id => user.id 
    end  
    end 
end 

因爲我不是很嘗試用Rails和這是我第一次與CanCanCan工作,我對我的代碼不太有信心,並希望得到一些驗證或改進建議。

那麼,這個代碼是否可以工作,它能讓我實現我所需要的嗎?

UPDATE:使用當前代碼,當我以用戶身份登錄並訪問另一個用戶日曆的日曆#show頁面時,我實際上可以訪問日曆,而我不應該這樣做。

所以,顯然,我的代碼不工作。

任何想法我做錯了什麼?

更新2:我想有在我的代碼中的錯誤,因爲我是用的,而不是:modelModel允許user s到給定model執行操作。

但是,代碼仍然無法正常工作。

有什麼想法可能是錯誤的嗎?

更新3:可以在問題來的事實,我用if user.role?(:owner)檢查,如果用戶的角色設置爲所有者,同時在數據庫中的角色實際上是定義爲「所有者」(字符串)引起的?

更新4:我一直在做一些研究,我意識到我犯了兩個錯誤。

  1. 我沒有添加load_and_authorize_resourcecalendarsadministrations控制器。

  2. 我已經定義了兩個屬性兩個參數 - initialize(user, calendar) - 而不是我的initialize方法中的一個。

因此,更新兩個控制器,還有ability.rb文件,如下所示:

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    user ||= User.new 
    if user.role?(:owner) 
     can :manage, Calendar, :user_id => user.id 
     can :manage, Administration, :user_id => user.id 
     can :manage, Administration, :calendar_id => calendar.id 
    elsif user.role?(:editor) 
     can [:read, :update], Calendar, :user_id => user.id 
     can :destroy, Administration, :user_id => user.id 
    elsif user.role?(:viewer) 
     can [:read], Calendar, :user_id => user.id 
     can :destroy, Administration, :user_id => user.id 
    end  
    end 
end 

現在,當我嘗試訪問不屬於current_user日曆,我拿出現以下錯誤:

NoMethodError in CalendarsController#show 
undefined method `role?' for #<User:0x007fd003dff860> 
def initialize(user) 
    user ||= User.new 
    if user.role?(:owner) 
     can :manage, Calendar, :user_id => user.id 
     can :manage, Administration, :user_id => user.id 
     can :manage, Administration, :calendar_id => calendar.id 

我該如何解決這個問題?

回答

1

用戶模型中沒有這樣的方法role?。 Cancancan文檔是錯誤的,因爲假設這些方法存在於這些示例中。

爲了解決這個問題,你應該做的,而不是:

if user.role == 'Owner' 
    ... 
elsif user.role == 'Editor' 
    ... 
elsif user.role == 'Viewer' 
    ... 
+0

這正是我終於實現了。謝謝! –