[英]How to refactor method with multiple boolean variables in Ruby
我在ruby中有一個方法,可以有條件地設置一些實例變量,我想知道如何重構它以清理它並使它不那么冗長。 我的第一步雖然是將不同的條件分解為多個較小的輔助方法,但是我不確定這是否是正確的方法。 任何建議都會有所幫助。
def admin_view
if resource.present?
if resource.ed_level == 'group'
if current_user && (current_user.admin || resource.admins_byemail.include?(current_user.email))
@admin_full = true
@admin_edit = true
@admin_view = true
else
@admin_full = false
@admin_edit = false
@admin_view = false
end
else
if current_user && (current_user.admin || resource.admin_email_list('view').include?(current_user.email.downcase))
if current_user.admin || (resource.admin_email_list('full').include?(current_user.email.downcase) && resource.ed_level != 'group')
@admin_full = true
@admin_edit = true
@admin_view = true
elsif resource.admin_email_list('edit').include?(current_user.email.downcase) && resource.ed_level != 'group'
@admin_full = false
@admin_edit = true
@admin_view = true
elsif resource.admin_email_list('view').include?(current_user.email.downcase) && resource.ed_level != 'group'
@admin_full = false
@admin_edit = false
@admin_view = true
end
else
@admin_full = false
@admin_edit = false
@admin_view = false
end
end
else
redirect_to school_missing_path
end
end
根據下面的答案,我已經更新了我的代碼,如下所示。
def admin_view
if resource.present?
if resource.ed_level == 'group'
if current_user && (current_user.admin || resource.admins_byemail.include?(current_user.email))
set_admin_permissions(full: true, edit: true, view: true)
else
set_admin_permissions(full: false, edit: false, view: false)
end
else
if current_user && (current_user.admin || resource.admin_email_list('view').include?(current_user.email.downcase))
if current_user.admin || (resource.admin_email_list('full').include?(current_user.email.downcase) && resource.ed_level != 'group')
set_admin_permissions(full: true, edit: true, view: true)
elsif resource.admin_email_list('edit').include?(current_user.email.downcase) && resource.ed_level != 'group'
set_admin_permissions(full: false, edit: true, view: true)
elsif resource.admin_email_list('view').include?(current_user.email.downcase) && resource.ed_level != 'group'
set_admin_permissions(full: false, edit: false, view: true)
end
else
set_admin_permissions(full: false, edit: false, view: false)
end
end
else
redirect_to school_missing_path
end
end
private
def set_admin_permissions(full:, edit:, view:)
@admin_full = full
@admin_edit = edit
@admin_view = view
end
首先,您可能想看看使用CanCanCan正確封裝您的權限。 這是定義訪問限制並在控制器和視圖代碼中對其進行測試的更正式的方法。
話雖如此,如果您將代碼的結構稍作不同,則可以大大簡化代碼:
def admin_permissions
return [ ] unless resource.present?
case resource.ed_level
when 'group'
if current_user && (current_user.admin || resource.admins_byemail.include?(current_user.email))
[ :full, :edit, :view ]
else
[ ]
end
else
email = current_user && current_user.email.downcase
if current_user && (current_user.admin || resource.admin_email_list('view').include?(email))
if current_user.admin || resource.admin_email_list('full').include?(email)
[ :full, :edit, :view ]
elsif resource.admin_email_list('edit').include?(email)
[ :edit, :view ]
elsif resource.admin_email_list('view').include?(email)
[ :view]
end
else
[ ]
end
end
end
然后像這樣使用它:
@admin_privs = admin_permissions
定義一些輔助方法,如下所示:
def admin_full?
@admin_privs and admin_privs.include?(:full)
end
def admin_edit?
@admin_privs and admin_privs.include?(:edit)
end
def admin_view?
@admin_privs and admin_privs.include?(:view)
end
我個人發現,通過應用“不要重復自己”(DRY)原理來減少代碼中的重復項通常會暴露底層結構,並使其更容易重塑為更簡潔,更靈活的方式。
例如,這里有許多針對resource.ed_level != 'group'
的測試,因為由於處於測試的else
塊中而斷言了相反的情況,所以不可能有這種情況。
基於Maxim的想法,但注意到您的權限是分層的(即“完整”表示編輯和查看,而“編輯”表示查看),我將您的輔助方法濃縮為:
def set_access_level(level)
case level
when :full
@admin_full, @admin_edit, @admin_view = true, true, true
when :edit
@admin_full, @admin_edit, @admin_view = false, true, true
when :view
@admin_full, @admin_edit, @admin_view = false, false, true
else
@admin_full, @admin_edit, @admin_view = false, false, false
end
end
然后您的代碼變為:
def admin_view
if resource.present?
if resource.ed_level == 'group'
if current_user && (current_user.admin || resource.admins_byemail.include?(current_user.email))
set_access_level(:full)
else
set_access_level(:none)
end
else
if current_user && (current_user.admin || resource.admin_email_list('view').include?(current_user.email.downcase))
if current_user.admin || (resource.admin_email_list('full').include?(current_user.email.downcase) && resource.ed_level != 'group')
set_access_level(:full)
elsif resource.admin_email_list('edit').include?(current_user.email.downcase) && resource.ed_level != 'group'
set_access_level(:edit)
elsif resource.admin_email_list('view').include?(current_user.email.downcase) && resource.ed_level != 'group'
set_access_level(:view)
end
else
set_access_level(:none)
end
end
else
redirect_to school_missing_path
end
end
只需創建一個setter助手方法,就像這樣:
def admin_view
if resource.present?
if resource.ed_level == 'group'
if current_user && (current_user.admin || resource.admins_byemail.include?(current_user.email))
set_values(true, true, true)
else
set_values(false, false, false)
end
else
if current_user && (current_user.admin || resource.admin_email_list('view').include?(current_user.email.downcase))
if current_user.admin || (resource.admin_email_list('full').include?(current_user.email.downcase) && resource.ed_level != 'group')
set_values(true, true, true)
elsif resource.admin_email_list('edit').include?(current_user.email.downcase) && resource.ed_level != 'group'
set_values(false, true, true)
elsif resource.admin_email_list('view').include?(current_user.email.downcase) && resource.ed_level != 'group'
set_values(false, false, true)
end
else
set_values(false, false, false)
end
end
else
redirect_to school_missing_path
end
end
def set_values(full, edit, view)
@admin_full = full
@admin_edit = edit
@admin_view = view
end
如果發現所有嵌套的if和重復的邏輯有點混亂。 請記住,您可以使用return語句使代碼更清晰。 我不能保證以下邏輯正是您所追求的,但是我認為該結構更具可讀性。
def admin_view
redirect_to school_missing_path unless resource.present?
access_level = calc_access_level
end
def calc_access_level
return :none unless resource.present?
return :none unless current_user
return :full if current_user.admin
email_raw = current_user.email
email = email_raw.downcase
if (resource.ed_level == 'group')
return resource.admins_byemail.include?(email_raw) ? :full, :none
end
['view','full','edit'].each do |access_level|
if resource.admin_email_list(access_level).include?(email)
return access_level.to_sym
end
end
return :none
end
def set_access_level(level)
@admin_full, @admin_edit, @admin_view = false, false, false
case level
when :full
@admin_full, @admin_edit, @admin_view = true, true, true
when :edit
@admin_edit, @admin_view = true, true
when :view
@admin_view = true
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.