2011-10-20 13 views
1

我有Rails站點,我已經用User類推出了我自己的認證,但爲了滿足不同角色的需要,我分別使用了Customer,CustomerServiceRepRepairman類。 User表具有一個user_type列,指示它是什麼類型的用戶。保理Ruby方式

我的問題是如何利用Ruby來最有效地編寫與用戶對應的不同視圖。例如,登錄後,我會根據用戶的user_type將每個用戶引導到不同的地方。

我能做到這樣,我SessionsController創建行動,但我敢肯定這是「錯」的方式:

if user.user_type == 'customer'   
    redirect_back_or root_path 
elsif user.user_type == 'repairman' 
    redirect_to repairman_panel_path, :flash => { :success => "Welcome Back Mr. #{user.repairman.last_name}" } 
elsif user.user_type == 'customer_service_rep' 
    redirect_to customer_service_panel_path, :flash => { :success => "Welcome Back #{user.customer_service_rep.first_name}" } 
end 

是我的直覺正確的,有使用符號的更好的方法或一些這樣的事情,以避免列出了每次我想通過同一系統漏斗每個用戶,然後退出到他們的適當區域的if-else結構?

+0

你有沒有在數據庫中每個角色一個'users'表,或1臺? – Anurag

+0

@Auurag單個用戶表。然後爲Customer創建一個表格,爲CustomerServiceRep創建一個表格等。 – LikeMaBell

+0

到目前爲止,這對夫婦的回答很有幫助,但並不完全符合我想象的方向。爲了更具體地陳述我的問題,是否有可能爲每個類編寫一個具有相同名稱的方法(例如goto_landing_page),然後使用user_type作爲參數將它指向正確的類方法,然後在User對象上調用它? – LikeMaBell

回答

3

雖然不建議將模型與您的網址結構混合使用,但除非您有虛擬網址,否則您可以將此信息存儲在模型類中。我們以一個班級爲例 - Repairman

class Repairman 
    # this allows you to use route helpers inside the Model 
    include Rails.application.routes.url_helpers 

    def greeting 
    "Welcome Back Mr. #{last_name}" 
    end 

    def home_path 
    repairman_panel_path 
    end 
end 

定義在每個類greetinghome_path方法。現在,在重定向用戶時,您可以依靠這兩種方法,而不用擔心它是什麼類型的用戶。

SessionController#create,你現在可以做內部,

class SessionController 
    def create 
    .. 
    redirect_to user.home_path, flash: { success: user.greeting } 
    end 
end 
0

的最明顯的重構是轉起來,並使用case聲明:

case (user.user_type) 
when 'customer'   
    redirect_back_or root_path 
when 'repairman' 
    redirect_to repairman_panel_path, :flash => { :success => "Welcome Back Mr. #{user.repairman.last_name}" } 
when 'customer_service_rep' 
    redirect_to customer_service_panel_path, :flash => { :success => "Welcome Back #{user.customer_service_rep.first_name}" } 
end 

這就是當你對很多事情比較同樣的事情有用。它還具有不會修改該屬性的優勢,因爲如果您錯誤地使用=而不是==,則可能會出現這種情況。無論如何,如果將user_type存儲爲字符串,則使用符號不一定非常有用。

一般來說,這種分支邏輯是一種標誌,你沒有從面向對象的角度來正確地做事,但在有時你必須妥協的MVC世界裏。如果你有一個用戶可以調用和派發的方法,而不是根據user_type硬連線邏輯,那將會更理想。舉例來說,拆分這件事:

case (user.home_action) 
when :repairman_panel 
    redirect_to repairman_panel_path, :flash => { :success => "Welcome Back Mr. #{user.repairman.last_name}" } 
when :customer_service_panel 
    redirect_to customer_service_panel_path, :flash => { :success => "Welcome Back #{user.customer_service_rep.first_name}" } 
else 
    redirect_back_or root_path 
end 

然後,您可以定義一個home_action方法計算出你正在處理什麼「厚道」的用戶有:

def home_action 
    case (self.user_type) 
    when 'repairman' 
    :repairman_panel 
    when 'customer_service_rep' 
    :customer_service_panel 
    else 
    :root 
    end 
end 

分裂的邏輯這樣品牌它更容易測試,因爲您可以獨立於實際重定向驗證正確的home_action行爲。

0

如果在您的控制器的多個位置使用此開關,您可以考慮爲您的控制器使用mixin。只需在另一個文件中定義一個新模塊並將其與控制器混合即可。你可以有一個名爲redirect_for_user的方法。

module ControllerMixin 
    def redirect_params_for_user user 
    case user.user_type 
    when 'customer' 
     root_path 
    when 'repairman' 
     repairman_panel_path, :flash => { :success => "Welcome Back Mr. #{user.repairman.last_name}" } 
    when 'customer_service_rep' 
     customer_service_panel_path, :flash => { :success => "Welcome Back #{user.customer_service_rep.first_name}" } 
    end 
    end 
end 

然後在您的控制器,你只是包括它並使用它:

class YourController < ApplicationController 
    include ControllerMixin 

    def your_action 
    ... #logic here 
    redirect_to redirect_params_for_user(user) 
    end 
end 

使你不能重複自己,很好地分開它進行測試。