简体   繁体   中英

Multiple Types of Users on Ruby on Rails

I'm new to Ruby on Rails and have been following the tutorial. But I need more information.

I'm building an application that will allow access to various types of users, they are, students, parents, teachers and Administration (all have the same attributes) So far I have a model for User, which has fields, Email and Password, which serve as credentials to log into the site ..

Then I have a template for each type of user. Model Student Model Teacher ....

What I wanted to know was how do I register a user, referring to each type of user, and I already have a table User.

I've been searching and I realized that using 'devise' would be a viable solution, but do not quite understand how this works.

Someone explain to me the best way to do this?

There are several ways to approach this problem, as other answers indicate. First, make sure you understand the difference between authentication , (creating a user and logging in), and role-based authorization (controlling access to different parts of the web application depending on the user's role). You can implement authentication yourself but most Rails developers use the Devise gem because it is robust, full-featured, and well-tested. Authorization can be implemented with simple additions to a User model, though developers often use the CanCanCan or Pundit gems for complex applications.

For the use case you describe, I recommend implementing a very basic form of role-based authorization in your User model. First you'll have to create a User model using Devise.

A new feature of Active Record, Enum, introduced in Rails 4.1, is the simplest way to implement role-based authorization.

Create a migration:

$ rails generate migration AddRoleToUsers role:integer

The migration will look like this:

class AddRoleToUsers < ActiveRecord::Migration
  def change
    add_column :users, :role, :integer
  end
end

Add code to your User model to implement the Enum:

class User < ActiveRecord::Base
  enum role: [:student, :parent, :teacher, :admin]
  after_initialize :set_default_role, :if => :new_record?

  def set_default_role
    self.role ||= :student
  end

end

You define the names of the roles, and if necessary, can change the names as needed (the integer values stored with each user record remain unchanged). Active Record will restrict the assignment of the attribute to a collection of predefined values, so you don't have to add any code to restrict the names of the roles to a defined set. Best of all, enums come with a set of convenience methods that allow you to directly query the role without any extra code. For the enum attribute shown above, you can use these methods:

User.roles # => {"student"=>0, "parent"=>1, "teacher"=>2, "admin"=>1} # list all roles
user.student! # make a student user
user.student? # => true # query if the user is a student
user.role # => "student" # find out the user’s role
@users = User.student # obtain an array of all users who are students
user.role = 'foo' # ArgumentError: 'foo' is not a valid, we can’t set invalid roles

You can use the conditionals in a controller:

class UsersController < ApplicationController
  def index
    unless current_user.admin?
      redirect_to :back, :alert => "Access denied."
    end
    @users = User.all
  end
end

Or use it in a view:

<% if current_user.parent? %>
  <li><%= link_to 'Grade Reports', some_path %></li>
<% end %>

In general, if access control adds a lot of code to a controller, you're well-advised to use CanCanCan or Pundit , because you can move the complex authorization logic into a central location segregated from the controllers ("skinny controllers"). However, if your needs are as simple as you describe, role-based authorization in the controller is optimal.

I've written a Rails Pundit tutorial that compares both approaches and provides greater detail on simple role-based authorization as well as role-based authorization with Pundit.

Well, here is how I would implement it.

1) create Account model and add a polymorphic reference in its migration like this

  class Account < ActiveRecord:Migration
    def change
      create_table :accounts do |t|
        t.references :user, :polymorphic => true
        t.column :name, :string
      end
    end
  end

2) In each model class, for instance student class I would add the following line of code

  class Student < ActiveRecord::Base
    has_one :account, :as => :user
  end

3) In Account model class

  class Account < ActiveRecord::Base
    belongs_to :user, :polymorphic => true
  end

4) Use devise generator for Account model.

5) The big challenge is creating a new Student, basically you will be creating an Account record then assign this Account record to the newly created Student record.

a) There are 2 ways to do so: * Using nested forms. * Using a simple form and make the controller do the work.

I would encourage the second option, choose what fits you best and let me know if you have any problems.

If different app permissions is what you need, perhaps you want to assign roles to your users. This can be accomplished in many different ways. An easy one is to use Rolify gem: https://github.com/EppO/rolify

In its most simple form, you want to be able to select the type of user when registering it.

class User
  belongs_to: user_type
end

class UserType
  has_many: users
end

Based on that simple one-to-many relationship, you can pass in the user_type in the form to the controller and let the controller take care of creating/associating objects

user = User.create(params[:user])
user.user_type = UserType.find(params[:user][:user_type])

That's some very simple and quickly put together code with intention to make my point a bit clearer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM