0

I want different types of wikis to appear on the index view depending on the role of the user. The policy for admin and standard / guest users work as it should but when it comes to premium users and collaborations it gets a little messy. In my app i have the ability to add Collaborators to private Wikis . So a premium User i should be able to see My private wikis, public wikis and private wikis im a collaborating to, but the private wikis where im a collaborator arent showing up for me . Could it have to do with my Policy or my model associations ? please help me out

wiki#index

  def index
    @wikis = Kaminari.paginate_array(policy_scope(Wiki)).page(params[:page]).per(10)
  end

user model

class User < ActiveRecord::Base
  has_many :wikis
  has_many :collaborators
  belongs_to :collaborators
....

Wiki model

    class Wiki < ActiveRecord::Base
      belongs_to :user
      has_many :collaborators
      has_many :users, through: :collaborators
....

collaborator model

class Collaborator < ActiveRecord::Base
  belongs_to :user
  belongs_to :wiki
end

Wiki_policy

   class Scope
     attr_reader :user, :scope

     def initialize(user, scope)
       @user = user
       @scope = scope
     end

     def resolve
       wikis = []
       if user.role == 'admin'
         wikis = scope.all # if the user is an admin, show them all the wikis
       elsif user.role == 'premium'
         all_wikis = scope.all
         all_wikis.each do |wiki|
           if wiki.private == false || wiki.owner == user || wiki.collaborators.include?(user)
             wikis << wiki # if the user is premium, only show them public wikis, or that private wikis they created, or private wikis they are a collaborator on
           end
         end
       else # this is the lowly standard user
         all_wikis = scope.all
         wikis = []
         all_wikis.each do |wiki|
           if wiki.private == false || wiki.collaborators.include?(user)
             wikis << wiki # only show standard users public wikis and private wikis they are a collaborator on
           end
         end
       end
       wikis # return the wikis array we've built up
     end
   end

when i go into the console

last = Wiki.last 
last.collaborators 

i get this :

   => #<ActiveRecord::Associations::CollectionProxy [#<Collaborator id: 7, user_id: 8, wiki_id: 104, created_at: "2016-04-24 08:07:20", updated_at: "2016-04-24 08:07:20">]>
Miguel Angel Quintana
  • 1,371
  • 2
  • 9
  • 12
  • try testing the code manually in the console. I suspect you haven't actually assigned the wiki to the collaborator you are using because it's working when you are logged in as a standard user. The code doesn't look like it should fail – joewoodward Apr 24 '16 at 09:28
  • I tested it out on the console i used : `last = Wiki.last , last.collaborators ` and got `#]>` – Miguel Angel Quintana Apr 26 '16 at 08:19

1 Answers1

1

Ah, I see the issue. Your join table is malformed which is probably because you are using both belongs_to and has_many through for the same class so you were confused on naming. i.e. belongs_to :user and has_many :users

You need to take advantage of the class_name in the through definition

i.e.

Wiki
  # the owner
  belongs_to :user

  # the collaborators join table
  has_many :wiki_collaborators

  # this is the object you will call from wiki.collaborators
  has_many :collaborators, through: :wiki_collaborators, class_name: 'User'
end

User
  # the wikis owned by this user
  has_many :wikis

  # the join table
  has_many :wiki_collaborators

  # this is the object you can call from user.wiki_collaborations or something else that maybe fits better
  has_many :wiki_collaborations, through: :wiki_collaborators, class_name: 'Wiki'
end

WikiCollaborator
  belongs_to :user
  belongs_to :wiki
end

You issue is that when you are calling wiki.collaborator you are actually returning the join model not the user model.

You could actually call wiki.users (notice plural) to get the wiki collaborators in the code you currently have. You would still need to fix the User belongs_to :collaborators line though. I think dropping the Collaborator join table and regenerating it as WikiCollaborator would make more sense and then implement is as I've described

Hope this helps

joewoodward
  • 263
  • 4
  • 10