Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 213
telma Avatar asked Jun 29 '14 20:06

telma


People also ask

Why is Ruby on Rails not scalable?

RoR is being used with lots of huge websites, but as with any language or framework, it takes a good architecture (db scaling, caching, tuning, etc) to scale to large numbers of users. There's been a few minor changes to RoR to make it easier to scale, but don't expect it to scale magically for you.

Does Ruby on Rails scale?

Horizontal Scalability with Ruby on Rails. We can scale a Rails application horizontally similarly to how we scale with many other frameworks.

How is Ruby and rails connected with each other?

Rails is a framework for writing applications and it uses the Ruby language - hence the term "Ruby on Rails". Show activity on this post. Rails' ActiveSupport module also enhances Ruby in certain ways by adding capabilities to some of Ruby's built-in classes.

Can Rails scale?

Like stated above, a traditional crud-style app on Rails can be made to scale very well by just adding app server instances, cores, and finally physical app servers serving the app. This is what is meant by scaling out 2.

How do I declare a many-to-many relationship in Ruby on rails?

Rails offers two different ways to declare a many-to-many relationship between models. The first way is to use has_and_belongs_to_many, which allows you to make the association directly: The second way to declare a many-to-many relationship is to use has_many :through.

What is an example of a model in a Rails application?

For example, consider a simple Rails application that includes a model for authors and a model for books. Each author can have many books. Without associations, the model declarations would look like this:

What is the latest version of Ruby on rails for tenants?

They represent a different approach to deal with numerous tenants, but the configuration phase is the same. Ruby’s latest version is 2.7.2 and 6.1 RC1 of Ruby on Rails gem as of writing this article. Make sure you have the right version of Ruby installed in your system and attempt to install the correct version of the framework:

How to set the primary key of an association in rails?

By convention, Rails assumes that the column used to hold the primary key of the association is id. You can override this and explicitly specify the primary key with the :primary_key option. Let's say the users table has id as the primary_key but it also has a guid column.


3 Answers

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.

like image 141
Daniel Kehoe Avatar answered Oct 17 '22 02:10

Daniel Kehoe


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.

like image 4
ysholqamy Avatar answered Oct 17 '22 02:10

ysholqamy


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

like image 1
CV-Gate Avatar answered Oct 17 '22 01:10

CV-Gate