9

我有一個問題得到Devise工作的方式,我想單表繼承。Rails:使用設計單表繼承

我安排兩個不同類型的帳戶如下:

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註冊。所有用戶使用單一表格登錄/account/sign_inAccount是父類)。

但是,通過此表單登錄時似乎只對Account作用域進行身份驗證。隨後對諸如/user/edit/company/edit等操作的請求將用戶引導至相應作用域的登錄屏幕。

我該如何設計識別帳戶'類型'並驗證它們的相關範圍?

任何建議非常感謝。

回答

8

我剛碰到確切的場景(帶類名如問題中概述的那樣改變)。這裏是我的解決方案(設計2.2.3,導軌3.2.13):

在配置

/routes.rb中:

devise_for :accounts, :controllers => { :sessions => 'sessions' }, :skip => :registrations 
devise_for :users, :companies, :skip => :sessions 
在app /控制器/ 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類仍然是:可註冊的,視圖/ devise/shared/_links.erb中的默認鏈接將嘗試發出,但new_registration_path(Accounts)將不起作用(我們:在路徑繪圖中跳過它)一個錯誤。您必須生成設計視圖並手動刪除它。

帽尖到https://groups.google.com/forum/?fromgroups=#!topic/plataformatec-devise/s4Gg3BjhG0E指向我在正確的方向。

+0

我用這個,我得到了錯誤NoMethodError(未定義的方法'類型'...在行sign_in(resource.type ...我需要做什麼來改變這個? – Kevin 2014-10-08 00:20:02

+0

我猜只是做一個字符串列在帳戶名稱類型?並將其設置爲模型名稱? – Kevin 2014-10-08 01:37:29

+0

這也是我的猜測。ActiveRecord STI期望。 – 2014-12-08 18:05:34

0

嘗試改變,像這樣的路線:
devise_for:帳戶,:用戶:公司
因爲設計採用複數形式的名稱爲它的資源

請讓我知道,如果它幫助你

+0

感謝您的建議。不幸的是,這並沒有解決問題。通過'/ accounts/sign_in'登錄仍然不允許我訪問'/ users/edit'或'/ companies/edit'。 – gjb 2011-04-17 19:09:16

1

如果不覆蓋會議管理員,我不認爲這是可能的。每個sign_in頁面都有一個特定的作用域,這個作用域將根據你的路由所定義的進行驗證。

通過在路徑文件中使用devise_scope函數,可以爲多個用戶範圍使用相同的sign_in頁面,以強制執行:用戶和:公司在頁面中使用相同的登錄(可以找到一個方法here),但我相當肯定,你將不得不修改會話控制器來執行一些自定義邏輯以確定哪種類型的用戶正在登錄。

+0

@gjb你怎麼能夠處理這個?你有沒有找到更好的解決方案? – 2011-08-01 06:35:20

15

有一種簡單的方法來處理路線中的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文件中指定的認證方法的方塊:

## 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 

這就是我解決導軌設計STI問題的方法。

+0

不應該:用戶是:在這行代碼中的公司?''#只有公司的路線 認證:用戶,lambda {| u | u.type ==「公司」}做 結束''' – MDekker 2016-02-12 18:01:36