【问题标题】:How would I implement a multi-type user system for Rails?我将如何为 Rails 实现多类型用户系统?
【发布时间】:2014-11-26 02:19:11
【问题描述】:

我正在创建一个 Rails 应用程序,用户可以通过选中表单中的“个人”或“组织”框来注册。我正在努力寻找一种将其实现到 Rails 中的方法。这两种用户类型将具有相同的授权。我不知道是否要在我的 ActiveRecord 数据库中使用字符串或布尔值作为数据类型。另外,我需要在我的模型(User.rb)和我的控制器中放入什么才能分别对其进行验证和实现?

【问题讨论】:

    标签: ruby-on-rails types rails-activerecord


    【解决方案1】:

    有很多方法可以实现这一点;这取决于您的需求。问问自己:“人和组织是否具有相同的属性?

    AR 枚举

    如果他们这样做了,那么区分两者的唯一因素就是角色(或您想称呼的任何名称),即个人或组织。对于这种情况,Rails 4.1 provides AR enums。这是最简单的解决方案,它可以是这样的:

    class User < ActiveRecord::Base
      enum role: [ :person, :organization ] # @user.role => 'person', @user.person? => true
    end
    

    多态关联

    另一方面,如果人员和组织仅共享某些属性,您可以考虑使用polymorphic association(如果人员和组织不共享任何属性,甚至role,它们应该是两个不同的模型)。基本模型应该包含人和组织共享的属性。个人/组织模型应包含特定于该模型的属性。

    # common attributes
    class User < ActiveRecord::Base
      belongs_to :profile, polymorphic: true
    
      def self.roles
        %w(person organization)
      end
    end
    
    # person-specific attributes
    class PersonProfile < ActiveRecord::Base
      has_one :user, as: :profile, dependent: :destroy
    end
    
    # organization-specific attributes
    class OrganizationProfile < ActiveRecord::Base
      has_one :user, as: :profile, dependent: :destroy
    end
    

    对于用户注册,您可以创建 users#newusers#create 操作。在您的用户注册表单(可能是app/views/users/new.html.erb)中,您可以使用select_tag 让用户指定他们的角色。然后,使用它来确定要附加到用户模型的配置文件类型。例如(users#create):

    def create
      @user = User.new(user_params)
      if role = params[:role]
        # return HTTP 400
        head :bad_request and return unless User.roles.include?(role)
    
        # Assign the User's profile
        @user.profile = "#{role.capitalize}Profile".constantize.new
      else
        # enter your own logic here
      end
    
      @user.save ? redirect_to(@user) : render(:new)
    end
    

    在我看来,会话的处理(用户登录/注销)应该在单独的SessionsController 中处理。

    【讨论】:

    • 好的,谢谢@jmera!我想我可能会实现多态关联。我遇到的一个主要问题是,当用户注册时,我如何让他们在视图下的注册表单中选择成为“人”或“组织”?
    • 嘿@jtarr523,看看我的编辑。如果我是你,我会使用两个不同的控制器。一个用于人员,另一个用于组织。当你使用同一个控制器来处理在我看来像是两个完全不同的模型时,它会变得混乱。
    • 你弄错了多态关系。 PersonProfileOrganizationProfile 始终属于 User,因此这些关系不是多态的。另外,我认为您不能按照您在此处的意图使用 has_one - AR 无法知道要查看哪个表以查找相关记录。
    • 你是对的@ToddAgulnick。请参阅我的编辑。我还没有测试过,但我很确定它现在是正确的。
    【解决方案2】:

    向名为user_types 的数据库中添加一个新表,其中包含roleid 字段。在users 表中,您需要添加user_type_id 列。然后,在UserType模型中

    class UserType < ActiveRecord::Base
      has_many :users
    end
    

    User模型中你需要添加

    class User < ActiveRecord::Base
      belongs_to :user_type
    end
    

    您可以在种子中创建 UserType 记录,但请确保每次重置数据库时它都会运行,请将其添加到 seeds.rb

    UserType.create!(role: "person")
    UserType.create!(role: "organization")
    

    希望这是有道理的!

    【讨论】:

      【解决方案3】:

      如果您的问题中只有两种类型的用户(个人和组织),您可以只拥有一个个人模型,并在其中添加一个布尔字段 is_organization。有关详细信息,请参阅流行的身份验证 gem 如何处理此here(此方法是链接页面上的选项 2,您也可以查看选项 1,即创建一个全新的模型)。

      【讨论】:

        猜你喜欢
        • 2019-12-20
        • 2011-10-19
        • 2021-04-23
        • 1970-01-01
        • 2020-09-26
        • 1970-01-01
        • 1970-01-01
        • 2017-12-30
        • 1970-01-01
        相关资源
        最近更新 更多