簡體   English   中英

Rails:使用具有單表繼承的Devise

[英]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_inAccount是父類)。

但是,通過此表單登錄似乎只是為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM