简体   繁体   English

Rails/Ruby 提取 if 阻塞到助手或守卫

[英]Rails/Ruby extract if block to helper or guard

In my Rails app I need to implement authentication for web app, I need to use an external resource to make it work.在我的 Rails 应用程序中,我需要为 web 应用程序实现身份验证,我需要使用外部资源才能使其工作。 To do so I'm using custom Devise Strategies.为此,我使用自定义 Devise 策略。 After a tremendous amount of work, I finally managed to implement a code that covers all scenarios - the code is working but unfortunately my eyes bleed when I see the code below:经过大量的工作,我终于设法实现了一个涵盖所有场景的代码 - 代码正在运行,但不幸的是,当我看到下面的代码时,我的眼睛在流血:

module Devise
  module Strategies
    class AwareLogin < Authenticatable
      def authenticate!
        # some logic
        # (...)

            if login.valid_password?(password) && aware_response.success?
              success!(login)
            elsif login.valid_password?(password) && !aware_response.success?
              success!(login)
            elsif login.id.nil? && aware_response.success?
              login.set_user_tokens(aware_response)
              success!(login)
            elsif !login.valid_password?(password) && !aware_response.success?
              raise ActiveRecord::Rollback
            elsif !login.valid_password?(password) && aware_response.success?
              fail!(:aware_auth)
            end

          rescue SupervisorRollback => s
            @user_to_rollback = s.user_id
            raise ActiveRecord::Rollback
          end
        end
      end
    end
  end
end

Is there any way to replace that if block by something clearer like guard or even maybe external helper instead?有没有办法用更清晰的东西代替它,比如警卫,甚至可能是外部助手?

You can consolidate the logic a bit but given that the branches perform different actions you will still need some of the branching.您可以稍微整合一下逻辑,但鉴于分支执行不同的操作,您仍然需要一些分支。

My recommended consolidation我推荐的合并

def authenticate!
  begin
    if login.valid_password?(password) || (set_token = login.id.nil? && aware_response.success?) 
      login.set_user_tokens(aware_response) if set_token
      success!(login)
    else 
      aware_response.success? ? fail!(:aware_auth) : raise(ActiveRecord::Rollback)
    end 
  rescue SupervisorRollback => s
    @user_to_rollback = s.user_id
    raise ActiveRecord::Rollback
  end
end 

Reasoning:推理:

  • Your first 2 conditions only differ in their check of aware_response.success?您的前 2 个条件仅在其对意识响应.成功的检查中有所不同aware_response.success? ; ; however whether this is true or false they perform the same action so this check is not needed.但是,无论这是对还是错,它们都会执行相同的操作,因此不需要此检查。
  • Third branch performs 1 extra step of setting a token.第三个分支执行设置令牌的 1 个额外步骤。 Since this branch is unreachable unless .login?valid_password?(password) we have simply added an or condition to the first branch and to conditionally set the token if this condition is true由于这个分支是不可访问的,除非.login?valid_password?(password)我们只是简单地在第一个分支中添加了一个 or 条件,如果这个条件为真,则有条件地设置令牌
  • The 4th and 5th conditions can be reduced to an else because we checked if login.valid_password?(password) is true in the first branch thus reaching this branch means it is false.第 4 和第 5 个条件可以简化为 else,因为我们在第一个分支中检查了login.valid_password?(password)是否为真,因此到达该分支意味着它为假。 Now the only difference is how we respond to aware_response.success?现在唯一的区别是我们如何响应aware_response.success? which I just converted to a ternary.我刚刚转换为三元。

Note: There may be uncovered scenarios in your original example, due to the fact that there is no else .注意:由于没有else ,您的原始示例中可能存在未发现的场景。 Theoretically login.id.nil? &&.aware_response?success?理论上login.id.nil? &&.aware_response?success? login.id.nil? &&.aware_response?success? is uncovered and other mutations of such;被发现和其他突变; however I am unfamiliar with the possible options in this specific case.但是我不熟悉这种特定情况下的可能选项。 My solution will cover these additional scenarios but possibly not as intended, for example: login.id.nil? &&.aware_response?success?我的解决方案将涵盖这些额外的场景,但可能与预期不符,例如: login.id.nil? &&.aware_response?success? login.id.nil? &&.aware_response?success? could result in nil using your branching whereas it will result in raise(ActiveRecord::Rollback) under mine.使用你的分支可能会导致nil ,而它会导致我的raise(ActiveRecord::Rollback)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM