[英]Rails: Using Devise with single table inheritance
我遇到了一個問題,就是讓Devise按照單表繼承的方式工作。
我有兩種不同類型的帳戶,如下所示:
class Account < ActiveRecord::Base
devise :database_authenticatable, :registerable
end
class User < Account
end
class Company < Account
end
我有以下路線:
devise_for :account, :user, :company
用戶在/user/sign_up
注冊, /company/sign_up
在/company/sign_up
注冊。 所有用戶都使用/account/sign_in
的單個表單/account/sign_in
( Account
是父類)。
但是,通過此表單登錄似乎只是為Account
范圍驗證它們。 對/user/edit
或/company/edit
等操作的后續請求將用戶指向相應范圍的登錄屏幕。
如何讓Devise識別帳戶“類型”並對相關范圍進行身份驗證?
任何建議非常感謝。
有一種簡單的方法來處理路線中的STI。
假設您有以下STI模型:
def Account < ActiveRecord::Base
# put the devise stuff here
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
def User < Account
end
def Company < Account
一個經常被忽視的方法是您可以在routes.rb文件中的authenticated方法中指定一個塊:
## config/routes.rb
devise_for :accounts, :skip => :registrations
devise_for :users, :companies, :skip => :sessions
# routes for all users
authenticated :account do
end
# routes only for users
authenticated :user, lambda {|u| u.type == "User"} do
end
# routes only for companies
authenticated :user, lambda {|u| u.type == "Company"} do
end
獲取各種輔助方法,如“current_user”和“authenticate_user!” (“current_account”和“authenticate_account!”已定義),無需為每個方法定義單獨的方法(隨着更多用戶類型的添加而迅速變得不可維護),您可以在ApplicationController中定義動態幫助器方法:
## controllers/application_controller.rb
def ApplicationController < ActionController::Base
%w(User Company).each do |k|
define_method "current_#{k.underscore}" do
current_account if current_account.is_a?(k.constantize)
end
define_method "authenticate_#{k.underscore}!" do
|opts={}| send("current_#{k.underscore}") || not_authorized
end
end
end
這就是我解決了rails設計STI問題的方法。
我剛剛遇到了問題中概述的確切場景(類名已更改)。 這是我的解決方案(Devise 2.2.3,Rails 3.2.13):
在config / routes.rb中:
devise_for :accounts, :controllers => { :sessions => 'sessions' }, :skip => :registrations
devise_for :users, :companies, :skip => :sessions
在app / controllers / sessions_controller.rb中:
class SessionsController < Devise::SessionsController
def create
rtn = super
sign_in(resource.type.underscore, resource.type.constantize.send(:find, resource.id)) unless resource.type.nil?
rtn
end
end
注意:由於您的Accounts類仍然是:可注冊的,因此將嘗試發出views / devise / shared / _links.erb中的默認鏈接,但new_registration_path(Accounts)將不起作用(我們:在路由圖中跳過它)導致錯誤。 您必須生成設計視圖並手動刪除它。
請聯系https://groups.google.com/forum/?fromgroups=#!topic/plataformatec-devise/s4Gg3BjhG0E,以便指出我正確的方向。
如果不覆蓋會話控制器,我認為這是不可能的。 每個sign_in頁面都有一個特定的范圍,設計將根據您的路由進行身份驗證。
通過使用路由文件中的devise_scope函數可以對同一個sign_in頁面使用相同的sign_in頁面來強制:users和:公司使用相同的登錄頁面(可以在這里找到操作方法),但是我非常肯定你必須修改會話控制器來做一些自定義邏輯,以確定登錄的用戶類型。
嘗試改變這樣的路線:
devise_for:accounts,:users,:companies
因為Devise為它的資源使用復數名稱
如果有幫助,請告訴我
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.