簡體   English   中英

如何在Ruby中使用多個布爾變量重構方法

[英]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.

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