In a Rails 5 application, I have a shortlist
model in a HABTM relationship with a user
model, with the users controlled by Devise. This is all working as expected, where each User can see their own Shortlists (only).
class Shortlist < ApplicationRecord
has_and_belongs_to_many :users
...
class User < ApplicationRecord
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable
has_and_belongs_to_many :shortlists
...
class ShortlistsController < ApplicationController
def index
@shortlists = current_user.shortlists
...
Now I wish to allow users to "share" shortlists with other users, who will have read-only access to the shared shortlists.
I could add the second user to the shortlist (@shortlist.users << User.second
) but this would give them full read-write access.
The cancancan gem looks promising, but I'm not sure how to configure the abilities, to allow User1 full control over their shortlists, and to give User2 read-only access to shortlists that User1 shares with them.
How can I restrict the second user to having read-only access?
Your solution in adding a owner_id
column to the shortlists table is actually a good one as it lets you efficiently eager load the association and is a lot less cumbersome to deal with.
If you wanted to keep track of the user which creates the record too through a join table thats possible through a roles system but it would be a lot more clunky. The Rolify gem is one such as example of a generic roles system.
One thing you should do is use has_many through:
instead of the near useless has_and_belongs_to_many
:
class Shortlist < ApplicationRecord
belongs_to :owner,
class_name: 'User'
has_many :shares
end
# rails g model user:belongs_to shortlist:belongs_to
class Share < ApplicationRecord
belongs_to :user
belongs_to :shortlist
end
class User < ApplicationRecord
has_many :shortlists,
foreign_key: :owner_id
has_many :shares
has_many :lists_shared_with_me,
through: :shares,
source: :shortlists
end
This lets you add additional columns to the table like for example flags that will let you grant other users the rights to edit the shortlist or an automatic expiry date. You could also generate unique URLs for each share to keep track of which "share" is being used. None of that is possible with HABTM.