Search code examples
ruby-on-railsruby-on-rails-4enumsrolespundit

Rails Enum issue on Has_many, through...method cannot be called from my controller


I have a Relationship model in which i establish a following relationship between users and projects. In this relationship model i use enum to distinguish the type of relationship the user has with the project (basically establishing a "role").

Now in my Projects Controller I am trying to call the projectadmins action

def projectadmins
    @title = "Project Admins"
    @project = Project.find(params[:id])
    authorize @project, :visit?
    @projects = @project.followers
    render 'show_projectadmin_project'
  rescue Pundit::NotAuthorizedError
    flash[:danger] = "You are not authorized to access this page."
    redirect_to projects_path || root_path
  end

My Relationships model is:

class Relationship < ActiveRecord::Base
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "Project"
  validates :follower_id, presence: true
  validates :followed_id, presence: true

  enum role: [:admin, :collaborator, :visitor]
end

User & Projects Models:

class User < ActiveRecord::Base
  has_many :own_projects, :class_name=>'Project'
  has_many :projects
  has_many :relationships, foreign_key: "follower_id", dependent: :destroy 
  has_many :followed_projects, through: :relationships, source: :followed
end

class Project < ActiveRecord::Base
      belongs_to :owner, :foreign_key=>'user_id', :class_name=>'User'
      has_many :reverse_relationships, foreign_key: "followed_id",
                                       class_name: "Relationship",
                                       dependent: :destroy
      has_many :followers, through: :reverse_relationships, source: :follower
end

'show_projectadmin_project' view:

<h3>Project Administrators</h3>
      <% if @project.projectadmins.any? %>
        <% @project.projectadmins.each do |user| %>
          <div class="no-pad col-md-3">
            <div class="inner-border">
              <h5><%= link_to user.email, user %></h5>
            </div>
          </div>
        <% end %>
      <% end %>

As is, my code in the controller method is setup to return all following relationships ("@projects = @project.followers")...my question is how can i change this line of code to return all following relationships that have an enum role type of :admin?

I assume something like "@projects = @project.followers where (etc, etc)" but I can't seem to find anything that has worked for me.

UPDATE: I didn't want to have to do this because I thought adding the enum role types would prevent me from having to setup different has_many's in the model. I wanted to just using the followers relationship and be able to distinguish enum type somehow, but...

I have tried adding the following to my Projects Model:

has_many :projectadmins, -> { where role: :admin}, class_name: 'Relationship', through: :reverse_relationships, source: :follower

and calling the following line in my controller instead of the '.followers'

@projects = @project.projectadmins

Now the action 'projectadmins' works and i arrive at the correct view (a good sign i guess)...but the project admins are not being listed as they should be.


Solution

  • just to follow up on this... I just had to change the line in the model to:

    has_many :projectadmins, -> { where("relationships.role = ?", Relationship.roles[:admin]) }, through: :reverse_relationships, source: :follower
    

    and it worked...just in case that helps anyone else.