Rails Model Structure for Users

I am new to rails and I am working on my second rail application.

The application will have different roles for users, but some users will have several roles.

Each user of the site will be an artist. Some users will act as moderators.

How would I structure it? In some PHP applications that I used, there is only one user, and then a database column for is_admin, etc. But I looked at the source for rails applications and saw separate models for users and administrators, etc. Although I don’t know why.

So, should I have one user model with the role attribute, which can be a Moderator, and then just call the artists artists in my views, routes, etc.?

Or should I have a user model, a Moderator model that inherits from her, and an artist model that belongs to the user?

I'm really confused.

+6
source share
6 answers

You can search for Devise and CanCan gems. This pair is really a powerful combination. This makes the two models User and Role. In a role, you can create new roles without creating new models for them. Although he creates Model Ability, here you can define access rules for roles.

Manual: http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/

Here you can find Devise and CanCan sources and greetings:

https://github.com/plataformatec/devise

https://github.com/ryanb/cancan

My models look like this:

Role.rb

class Role < ActiveRecord::Base has_and_belongs_to_many :users end 

User.rb

 class User < ActiveRecord::Base has_many :accounts has_and_belongs_to_many :roles # Include default devise modules. Others available are: # :token_authenticatable, :confirmable, :lockable and :timeoutable devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model attr_accessible :email, :username, :password, :password_confirmation, :remember_me, :role_ids def role?(role) return !!self.roles.find_by_name(role.to_s.camelize) end end 

Ability.rb

 class Ability include CanCan::Ability def initialize(user) user ||= User.new # guest user if user.role? :administrator can :manage, :all elsif user.role? :operator can :read, Account can :read, Server elsif user.role? :customer can :manage, Account can :read, Server end end end 

In the controller you should add only two lines:

 class YourController < ApplicationController before_filter :authenticate_user! load_and_authorize_resource ... end 
+7
source

I think you do not need to create different models, because you do not have specific fields for each. Therefore, you just need to set the "role" of each user. Two options: create a role table or add a field role to the user field. Both solutions work, the second - more flexible, but less optimized.

But in your particular case, you do not have complex role management so that you can find a simpler solution. If all your users are artists, you do not need to indicate this in your code, it is contained in an implicit description of what the user is. Therefore, you just need to save if the user is an administrator or not, and I believe that the best solution is to create the is_admin boolean field.

After that, you will need to create some before_filter in your protected controllers, for example:

 before_filter => :authorize, :only => :new, :edit, :create, :update, :destroy def authorize redirect_to :root if not current_user.is_admin? end 

And you may have simple queries:

 @artists = User.all @moderators = User.where(:is_admin => true) 

If you are looking for a more complete authorization system, you can check out this little gem: https://github.com/ryanb/cancan

But I think this is not the case at the moment. If you have a simple problem, try a simple solution!

+2
source

If you need code specific to it and its role, for example, administrator or moderator, another solution would be to create a basic user model that all other classes inherit. You can then create the Admin class and the Moderator class, which inherit from the User model. This means that you can avoid constantly checking the role of users in your code, for example. current_user.do_some_admin_thing if current_user.is_admin? . Your classes will look something like this.

 class User < ActiveRecord::Base # base user methods in here end class Moderator < User def do_moderator_thing # perform a moderator task end end class Admin < Moderator def do_admin_thing # perform an admin task end end 

In this case, the User class has the most basic privileges, moderators can do everything that users can, as well as special moderator methods and administrators can do everything that users and moderators can have, as well as special administrator methods.

All different user roles will use the same table in the database, but your problems are neatly divided into classes that help you avoid unnecessary conventions with your code, checking what role the user has all the time.

Creating new users would be simple and Admin.new :name => 'bob' the Admin class, and then takes care of how the user is defined as an administrator, which provides a nice interface where you do not need to know the internal workings of the role system for interacting with users .

+2
source

Although I agree that the combination of Devise and CanCan is powerful and works. Let's look at it from a different perspective, referring to the Association and the delegation.

Association: In object-oriented programming, an association defines relationships between classes of objects that allow one object to force another to perform an action on its behalf.

Delegation: Delegation allows you to control the behavior of an object defined in terms of the behavior of another object. The term “Delegation” refers to the delegation of responsibility. The main focus of delegation is the transmission of messages when an object could delegate the responsibility of a message that it cannot process to objects that it can potentially (its delegates).

With this, what if we design our User and Roles like this. There is no role class, and the User does not inherit or specialize a particular class (Artist, Admin), and all classes (Role) contain a User object and a delegate. What I think and the way to implement using Rails looks something like this:

 class User < AR::Base def user_method end end class Artist < AR::Base has_one :user def artist_method # perform an admin task end end class Admin < AR::Base has_one :user def admin_method # perform an admin task end end 

This role class model is described by Francis G. Mosse in his role modeling article.

+1
source

This is the basic setup for declarative authorization I use. But you can just use it as without a gem if your authorization requirements are nothing more than specifying the types of Roles that the user has.

This requires a roles table, etc., so it may not be entirely your imagination.

 class Role < ActiveRecord::Base belongs_to :user end class User < ActiveRecord::Base has_many :roles def role_symbols roles.map { |r| r.title.to_sym } end def admin? has_role?(:admin) end # include more role booleans or write some ruby magic to be DRY # ... def has_role?(r) role_symbols.include?(r.to_sym) end end # give or take user = User.new user.roles << Role.new :title => "admin" user.roles << Role.new :title => "artist" user.role_symbols # => [:admin, :artist] user.admin? # => true user.has_role?(:artist) # => true 
+1
source

You can have two User and Role models. And the role belongs to the user.

Indicate the role of users (for example, administrator, moderator) in the role model.

0
source

Source: https://habr.com/ru/post/896546/


All Articles