title: Rails 4 + CanCanCan: "undefined method `role?' for User"
body: <p>This is a follow-up question on <em><a href="https://stackoverflow.com/questions/32342953/rails-4-cancancan-abilities-with-has-many-through-association">Rails 4: CanCanCan abilities with has_many :through association</a></em> and I am restating the problem here since I believe context has slightly changed and after 4 updates, the code from the initial question is pretty different too.</p>
  
  <p>I also checked other questions, like <em><a href="https://stackoverflow.com/questions/9773828/undefined-method-role-for-user">Undefined method &#39;role?&#39; for User</a></em>, but it did not solve my problem.</p>
  
  <p>So, here we go: I have three models:</p>
  
  <pre><code>class User &lt; ActiveRecord::Base
    has_many :administrations
    has_many :calendars, through: :administrations
  end
  
  class Calendar &lt; ActiveRecord::Base
    has_many :administrations
    has_many :users, through: :administrations
  end
  
  class Administration &lt; ActiveRecord::Base
    belongs_to :user
    belongs_to :calendar
  end
  </code></pre>
  
  <p>For a given <code>calendar</code>, a <code>user</code> has a <code>role</code>, which is defined in the <code>administration</code> join model (in a column named <code>role</code>).</p>
  
  <p>For each <code>calendar</code>, a <code>user</code> can have only one of the following three <code>role</code>s: Owner, Editor or Viewer.</p>
  
  <p>These roles are currently not stored in dictionary or a constant, and are only assigned to an <code>administration</code> as strings ("Ower", "Editor", "Viewer") through different methods.</p>
  
  <p>Authentication on the <code>User</code> model is handled through <code>Devise</code>, and the <code>current_user</code> method is working.</p>
  
  <p>In order to only allow logged-in <code>user</code>s to access in-app resources, I have already add the <code>before_action :authenticate_user!</code> method in the <code>calendars</code> and <code>administrations</code> controllers.</p>
  
  <p>Now, I need to implement a role-based authorization system, so I just installed the <code>CanCanCan</code> gem.</p>
  
  <p>Here is what I want to achieve:</p>
  
  <ul>
  <li>All (logged-in) <code>user</code>s can <code>create</code> new <code>calendar</code>s.</li>
  <li>If a <code>user</code> is the <code>owner</code> of a <code>calendar</code>, then he can <code>manage</code> the <code>calendar</code> and all the <code>administration</code>s that belong to this <code>calendar</code>, including his own <code>administration</code>.</li>
  <li>If a <code>user</code> is <code>editor</code> of a <code>calendar</code>, then he can <code>read</code> and <code>update</code> this <code>calendar</code>, and <code>destroy</code> his <code>administration</code>.</li>
  <li>If a <code>user</code> is <code>viewer</code> of a <code>calendar</code>, then he can <code>read</code> this <code>calendar</code>, and <code>destroy</code> his <code>administration</code>.</li>
  </ul>
  
  <p>To implement the above, I have come up with the following <code>ability.rb</code> file:</p>
  
  <pre><code>class Ability
    include CanCan::Ability
  
    def initialize(user)
      user ||= User.new
      if user.role?(:owner)
        can :manage, Calendar, :user_id =&gt; user.id
        can :manage, Administration, :user_id =&gt; user.id
        can :manage, Administration, :calendar_id =&gt; calendar.id
      elsif user.role?(:editor)
        can [:read, :update], Calendar, :user_id =&gt; user.id
        can :destroy, Administration, :user_id =&gt; user.id
      elsif user.role?(:viewer)
        can [:read], Calendar, :user_id =&gt; user.id
        can :destroy, Administration, :user_id =&gt; user.id
      end    
    end
  end
  </code></pre>
  
  <p>Now, when log in and try to visit any calendar page (index, show, edit), I get the following error:</p>
  
  <pre><code>NoMethodError in CalendarsController#show
  undefined method `role?' for #&lt;User:0x007fd003dff860&gt;
  def initialize(user)
      user ||= User.new
      if user.role?(:owner)
        can :manage, Calendar, :user_id =&gt; user.id
        can :manage, Administration, :user_id =&gt; user.id
        can :manage, Administration, :calendar_id =&gt; calendar.id
  </code></pre>
  
  <p>I guess the problem comes from the fact that a <code>user</code> does not have a <code>role</code> per se, but only has a <code>role</code> defined for a given <code>calendar</code>.</p>
  
  <p>Which explains why I get a <code>NoMethodError</code> for <code>role?</code> on <code>user</code>.</p>
  
  <p>So, the question would be: how to check a <code>user</code> <code>role</code> for a given <code>calendar</code>?</p>
  
  <p>Any idea how to make things work?</p>