用户的Rails模型结构

时间:2011-09-03 11:43:42

标签: ruby-on-rails ruby

我是rails的新手,我正在开发第二个rails应用程序。

应用程序将为用户提供不同的角色,但某些用户将拥有多个角色。

该网站的每位用户都是艺术家。一些用户将扮演主持人的角色。

我如何构建这个?在我使用过的一些PHP应用程序中,只有一个用户,然后是is_admin的数据库列,等等。但我查看了rails应用程序的源代码,并看到了用户和管理员等的单独模型,尽管我我不确定为什么。

那么,我应该有一个带有角色属性的用户模型,可以是主持人,然后在我的视图,路线等中调用用户“艺术家”吗?

或者我应该拥有一个用户模型,一个继承自它的主持人模型,以及一个属于用户的艺术家模型?

我真的很困惑。

6 个答案:

答案 0 :(得分:7)

你可以寻找宝石Devise和CanCan。这对真是强大的组合。这使得两个模型User和Role。在角色中,您可以创建新角色,而无需为其创建新模型。虽然它创建了模型能力,但您可以在此处定义角色的访问规则。

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

在这里你可以找到Devise和CanCan的来源和wikies:

https://github.com/plataformatec/devise

https://github.com/ryanb/cancan

我的模特看起来像这样:

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

在控制器中,您必须只添加以下两行:

class YourController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource

  ...

end

答案 1 :(得分:2)

我认为您不必创建不同的模型,因为每个模型都没有特定的字段。所以你只需要设置每个用户的“角色”。两个选项:在表User中创建角色表或添加角色字段。两种解决方案都有效,第二种解决方案更灵活但不太优化。

但是,在您的特定情况下,您没有复杂的角色管理,因此您可以找到更简单的解决方案。如果您的所有用户都是艺术家,则不必在代码中指定它,它包含在用户内容的隐含描述中。所以如果用户是管理员,你只需要保存,我认为最好的解决方案是创建一个布尔字段“is_admin”。

之后,您必须在受保护的控制器中创建一些before_filter,如下所示:

before_filter => :authorize, :only => :new, :edit, :create, :update, :destroy

def authorize
  redirect_to :root if not current_user.is_admin?
end

你可以有这样简单的请求:

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

如果您寻找更完整的授权系统,您可以查看这个小宝石:https://github.com/ryanb/cancan

但我认为目前情况并非如此。如果您有一个简单的问题,请寻找一个简单的解决方案!

答案 2 :(得分:2)

如果您需要具有特定于角色的代码或者诸如管理员或主持人之类的代码,则另一个解决方案是创建所有其他类继承的基本用户模型。然后,您可以创建从User模型继承的Admin类和Moderator类。这意味着您可以避免不断检查代码中的用户角色,例如current_user.do_some_admin_thing if current_user.is_admin?。你的课程看起来像这样

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

在这种情况下,User类具有最基本的权限,主持人可以完成用户可以使用的所有内容以及主持人特定的方法,管理员可以执行用户和主持人可以使用的管理特定方法。

所有不同的用户角色都会在数据库中使用相同的表,但您的关注点被整齐地分成几类,这样可以通过代码检查用户一直扮演的角色来避免过多的条件。

创建新用户也很简单Admin.new :name => 'bob' Admin类然后负责管理用户如何定义为管理员,提供一个很好的界面,您不需要知道角色系统的内部工作原理与用户互动。

答案 3 :(得分:1)

虽然我同意Devise和CanCan的结合是强大而有效的。让我们以不同的视角来看待它,并牢记协会和代表团。

  

关联:在面向对象的编程中,关联定义了一个   允许一个对象的对象类之间的关系   实例,以使另一个代表它执行某个操作。

     

委托:委派允许对象的行为   根据另一个对象的行为来定义。术语   “代表团”是指责任的授权。首要的   委托的重点在于对象可以传递的消息传递   委托无法处理对象的消息的责任   可能(其代表)。

有了这个,如果我们像这样设计我们的用户和角色怎么办?没有Role类,用户不会继承或专门化特定的类(Artist,Admin),所有(Role)类都包含User对象和委托。我正在思考的方式和使用Rails实现的方式是这样的:

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

FrancisG.Mossé在他关于建模角色的文章中描述了这个role class model

答案 4 :(得分:1)

这是我使用的declarative authorization gem的基本设置。但是如果您的授权要求不仅仅是询问用户的角色类型,那么您可以在没有gem的情况下使用它。

它确实需要一个roles表,所以这可能不是你想象的。

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

答案 5 :(得分:0)

您可以拥有两个模型User和Role。角色属于用户。

在角色模型中指定用户角色(如admin,moderator)。