在使用Devise注册后登录继承的用户

pin*_*ngu 2 ruby-on-rails single-table-inheritance sti devise ruby-on-rails-3

我正在使用rails 3.2.14和设计3.2.1,并且我有一个与我的设计"用户"模型具有STI关系的"管理员".

当我使用下面的表单注册一个新的管理员时,我收到以下错误:

undefined method `new_admin_session_path' for #<ActionDispatch::Routing::RoutesProxy:0x007fa6fe068f18>
Run Code Online (Sandbox Code Playgroud)

因为我有:

devise_for :users, :skip => :registrations do
Run Code Online (Sandbox Code Playgroud)

在我的路线.

如何注册新的"管理员",然后以"用户"身份登录?

请注意,如果我在我的form_for中为"用户"交换"管理员",并从我的路线中的"用户"中删除跳过注册,那么我得到我想要的行为,除了它是"用户"而不是"管理员" .

我创建了一个独立的应用程序来演示我的问题.https://github.com/deathwishdave/devise_test

user.rb

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

  attr_accessible :email, :password, :password_confirmation, :remember_me
end
Run Code Online (Sandbox Code Playgroud)

admin.rb

class Admin < User
end
Run Code Online (Sandbox Code Playgroud)

index.html.erb

<h2>Sign up</h2>

<%= form_for(Admin.new, :as => :admin, :url => registration_path(:admin)) do |f| %>
  <%= devise_error_messages! %>

  <div><%= f.label :email %><br />
  <%= f.email_field :email, :autofocus => true %></div>

  <div><%= f.label :password %><br />
  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation %></div>

  <div><%= f.submit "Sign up" %></div>
<% end %>
Run Code Online (Sandbox Code Playgroud)

的routes.rb

  devise_for :users, :skip => :registrations do
      delete '/logout', :to => 'sessions#destroy', :as => :destroy_user_session
      get '/login', :to => 'sessions#new', :as => :new_user_session
      post '/login', :to => 'sessions#create', :as => :user_session
  end

  devise_for :admins, :skip => :sessions

  authenticated :user do
    root :to => "dashboard#index"
  end

  authenticated :admin do
    root :to => "dashboard#index"
  end

  root :to => 'welcome#index'
Run Code Online (Sandbox Code Playgroud)

更新

要求…

  1. 四种不同的用户角色.
  2. 能够在将来轻松添加其他角色.
  3. 所有角色的单一登录/登录表单.

附加信息.

  1. 所有当前和未来角色共享相同的状态(具有相同的DB字段)
  2. 每个角色都与其他模型类有不同的关系.

为了满足这些要求,我考虑了多种选择,包括STI,多态关联,授权宝石以及单独的模型和表格.

多态关联是一个糟糕的选择,因为角色之间的字段是相同的,并且可能导致用户创建的困难.诸如cancan之类的授权gem不是一种选择,因为角色与其他模型类具有不同的关系.如果我使用cancan,则用户模型将受到不适用于所有用户的关系的污染.具有单独的模型和表将不允许所有类型的用户的单个入口点.

STI似乎很合适,因为所有角色字段都是相同的,因此数据库将被标准化.可以轻松添加其他用户.

从纯粹主义的角度来看,这是有道理的.我的不同角色是所有用户,用户是所有其他专业的接口或合同.

jok*_*lan 5

STI与多态

根据您提供的有关用户的要求和信息,STI似乎是一个很好的解决方案,特别是如果每​​个用户都有不同的逻辑关系.然而,即使每个角色没有任何其他数据库信息,多态关联也可以正常工作(请参阅http://railscasts.com/episodes/394-sti-and-polymorphic-associations).

关于CanCan的注意事项

纠正我,如果我错了,但CanCan似乎仍然是一个很好的解决方案,也与STI.CanCan基于roled,因此您可以检查您授权的用户类型,然后根据该用户类型/角色创建规则(带关系).

以用户身份登录admin

要回答关于如何以用户身份登录管理员的实际问题,您应该能够简单地覆盖sign_up注册控制器中的方法,如下所示:

class Admin::RegistrationsController < Devise::RegistrationsController
  def sign_up(resource_name, resource)
    sign_in(:user, resource)
  end
end
Run Code Online (Sandbox Code Playgroud)

并将以下内容添加到您的路由:

devise_for :admins, :skip => :sessions, :controllers => { :registrations => "admins/registrations" }
Run Code Online (Sandbox Code Playgroud)

此外,我觉得关于STI这个环节并制定,这是比你有点不同的场景,但仍正常为你一些有用的提示:http://adamrobbie.me/blog/2013-3-29-sti-with-rails-40 -β-和色器件