设计和多个“用户"楷模 [英] devise and multiple "user" models

查看:26
本文介绍了设计和多个“用户"楷模的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Rails 3.2 并设计 2.0,我对 Rails 还是很陌生.

I'm using rails 3.2 and devise 2.0 and I'm quite new to Rails.

我想实现以下目标:

  • 有 2 个或更多用户"模型,例如.成员、客户、管理员
  • 所有模型共享一些必填字段(例如电子邮件和密码)
  • 每个模型可能有一些独特的字段(例如,仅限客户的公司)
  • 某些字段可能是共享的,但没有相同的验证(例如,名称对于客户是必需的,而对于会员是可选的)
  • 所有字段都必须在注册过程中填写,因此表格有所不同
  • 登录表单应该是唯一的

我用谷歌搜索并搜索了 StackOverflow 很长一段时间,但对我来说似乎没有什么是正确的(我是一个 Java 人,抱歉 :) 现在我很困惑.出现了两种解决方案:

I googled and searched StackOverflow for quite a long time, but nothing seems right to me (I'm a Java guy, sorry :) and now I'm quite confused. Two solutions came up:

这是最常见的答案.只需创建默认设计用户并在成员--> 用户和客户--> 用户之间创建关系.我关心的是如何为每个模型实现定制的注册过程?我尝试了不同的方法,但结果都是一团糟!

That's the most frequent answer. Just create the default devise User and create relations between Member-->User and Customer-->User. My concern here is how can I achieve a customized registration process for each model? I tried different things but all ended as a mess!

这解决了自定义注册过程,对我来说似乎是正确的,但独特的登录表单是一个障碍.我在 SO(设计 - 从两个模型登录)上找到了一个答案,建议覆盖Devise::Models::Authenticatable.find_for_authentication(conditions).这看起来很复杂 (?),而且由于我是 Rails 新手,我想知道这是否可行?

This solves the custom registration process, and seems right to me, but the unique login form is a blocker. I found an answer on SO (Devise - login from two model) which suggests to override Devise::Models::Authenticatable.find_for_authentication(conditions). That seems complicated (?) and since I'm new to rails, I'd like to know if that could work?

感谢您的建议!

推荐答案

我找到了一个可行的方法,到目前为止我对它很满意.我会在这里为其他人描述.

I found a way to go and I'm quite happy with it so far. I'll describe it here for others.

我选择了单一的用户"类.我的问题是为每个伪模型实现一个定制的注册过程.

I went with the single "user" class. My problem was to achieve a customized registration process for each pseudo model.

model/user.rb:

class User < ActiveRecord::Base
  devise :confirmable,
       :database_authenticatable,
       :lockable,
       :recoverable,
       :registerable,
       :rememberable,
       :timeoutable,
       :trackable,
       :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :role

  as_enum :role, [:administrator, :client, :member]
  validates_as_enum :role
  ## Rails 4+ for the above two lines
  # enum role: [:administrator, :client, :member]

end

然后我改编了http://railscasts.com/episodes/217-multistep-formshttp://pastie.org/1084054 有两个注册路径和一个被覆盖的控制器:

Then I adapted http://railscasts.com/episodes/217-multistep-forms and http://pastie.org/1084054 to have two registration paths with an overridden controller:

config/routes.rb:

get  'users/sign_up'   => 'users/registrations#new',        :as => 'new_user_registration'

get  'clients/sign_up' => 'users/registrations#new_client', :as => 'new_client_registration'
post 'clients/sign_up' => 'users/registrations#create',     :as => 'client_registration'

get  'members/sign_up' => 'users/registrations#new_member', :as => 'new_member_registration'
post 'members/sign_up' => 'users/registrations#create',     :as => 'member_registration'

controllers/users/registrations_controller.rb:

我创建了一个向导类,它知道每一步要验证的字段

I created a wizard class which knows the fields to validate at each step

class Users::RegistrationsController < Devise::RegistrationsController

    # GET /resource/sign_up
    def new
        session[:user] ||= { }
        @user = build_resource(session[:user])
        @wizard = ClientRegistrationWizard.new(current_step)

        respond_with @user
    end

    # GET /clients/sign_up
    def new_client
        session[:user] ||= { }
        session[:user]['role'] = :client
        @user = build_resource(session[:user])
        @wizard = ClientRegistrationWizard.new(current_step)

        render 'new_client'
    end

    # GET /members/sign_up
    def new_member
      # same
    end

    # POST /clients/sign_up
    # POST /members/sign_up
    def create
        session[:user].deep_merge!(params[:user]) if params[:user]
        @user = build_resource(session[:user])
        @wizard = ClientRegistrationWizard.new(current_step)

        if params[:previous_button]
            @wizard.previous
        elsif @user.valid?(@wizard)
            if @wizard.last_step?
                @user.save if @user.valid?
            else
                @wizard.next
            end
        end

        session[:registration_current_step] = @wizard.current_step

        if @user.new_record?
            clean_up_passwords @user
            render 'new_client'
        else
            #session[:registration_current_step] = nil
            session[:user_params] = nil

            if @user.active_for_authentication?
                set_flash_message :notice, :signed_up if is_navigational_format?
                sign_in(:user, @user)
                respond_with @user, :location => after_sign_up_path_for(@user)
            else
                set_flash_message :notice, :"signed_up_but_#{@user.inactive_message}" if is_navigational_format?
                expire_session_data_after_sign_in!
                respond_with @user, :location => after_inactive_sign_up_path_for(@user)
            end
        end

    end

    private

    def current_step
        if params[:wizard] && params[:wizard][:current_step]
            return params[:wizard][:current_step]
        end
        return session[:registration_current_step]
    end

end

我的观点是:

  • new.rb
  • new_client.rb 包括根据向导步骤的部分内容:
    • _new_client_1.rb
    • _new_client_2.rb
    • new.rb
    • new_client.rb including a partial according to the wizard step:
      • _new_client_1.rb
      • _new_client_2.rb
      • _new_member_1.rb
      • _new_member_2.rb

      这篇关于设计和多个“用户"楷模的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆