How to get devise to work with multiple models or

2020-04-17 04:40发布

问题:

Using devise, what is the best way to have multiple models or roles? Here are the models or roles I need in my app:

-Author: can upload content to the site
-Customer: pays a monthly fee to access the content

A user can be both an Author and a Customer. I think they can share the same login form because they will both log in with their email address.

I have tried using CanCan and rolify, but couldn't figure out how to add different roles during registration. When a user registers as an Author, he should be given the "author" role and when a user registers by paying the monthly fee, he should be given the "customer" role. I don't want to use a checkbox for the roles either.

There is a nav link called "Authors" that will allow authors to register and then there is a link for users to register by going through the payment and billing form. Based on which link is clicked, should determine which role is given. Should I pass in a role parameter in the url during registration like "user/sign_up/index?role=customer"? If so, how do I get devise to use this in the registration process?

Using devise, CanCan, and rolify, how can I solve this? I thought it might be better to have a User class and then have Customer and Author extend from User, but from reading many similar questions on StackOverflow it seems rolify is easier.

I know what I am trying to do is very basic, I just haven't figured it out yet. I have been trying to find a solution for this all day.

Update: Danny's answer below pushed me in the right direction and I have managed to get the roles added properly during registration by passing in a parameter in the URL "users/sign_up?role=customer" or "users/sign_up?role=author". I don't know if this is the best way, but that's what I have so far.

One question I have though is how will my has_many relations work now? Here is what I have:

class User < ActiveRecord::Base
    rolify
    devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

    has_one :plan
    has_many :files

end

has_one :plan is for the customer's subscription plan and has_many :files is for the author who can upload many files that the customer can download

The problem is that I would also like to keep track of the user's file downloads so I would like to put has_many :downloads or probably has_many :files, :through => :downloads

Does it matter if I put these in the User model knowing that an author who is not a customer is not allowed to download files and that a customer who is not an author cannot upload files?

回答1:

From your question, I understand you've already "dived" into rolify and cancan, so I'll focus on assigning roles.

You typically create different roles in your seeds.rb file, with something like

[:admin, :author, :customer].each do |role|
  Role.find_or_create_by_name({ name: role }, without_protection: true)
end

You assign the :admin role immediately when you create yourself as administrator, also in the seeds.rb file, using

user.add_role :admin

For your other roles, you assign them "when it's appropriate", exactly as you describe. When a user clicks the Authors link, and proceeds, this triggers some action in some controller. It is there that you assign this role to that user, by using the same

user.add_role :author

You can also assign roles, connected to certain objects only. E.g. an author is author for only the documents he creates himself. In that case you don't want to assign a "general" author role, but you will assign it like

user.add_role :author, document

in the controller's create action, together with saving the created document. Alternative for this kind of assignment is to do it in a callback from your model.

More questions? Just ask!