【问题标题】:How to write a RuboCop Cop to prevent writing Sidekiq workers using keyword arguments?如何编写 RuboCop Cop 以防止使用关键字参数编写 Sidekiq 工作人员?
【发布时间】:2020-04-20 21:58:22
【问题描述】:

不久前,我发现you can't use keyword arguments when defining Sidekiq workers。因为它只在入队后引发异常,所以我想防止它永远进入生产环境。为此,我想添加一个警察来检查#perform 的参数,并在使用关键字参数时引发错误。到目前为止,这是我失败的尝试:

module RuboCop
  module Cop
    class SidekiqDontUseKeywordArguments < RuboCop::Cop::Cop
      MSG = "Don't use keyword arguments in workers".freeze
      OBSERVED_METHOD = :perform

      def on_def(node)
        return if node.method_name != OBSERVED_METHOD

        node.arguments.each do |argument|
          if keyword_argument?(argument)
            add_offense(node, location: :expression)
          end
        end
      end

      private

      def keyword_argument?(argument)
        # detect if the argument is a keyword
      end
    end
  end
end

我在这里遗漏了两件事。首先也是最重要的是,我不知道如何判断参数是否是关键字。第二个是我想只为 Sidekiq 工人申请这个警察。我在这里遵循正确的方法吗?有更好的方法吗?

【问题讨论】:

    标签: ruby-on-rails ruby sidekiq rubocop


    【解决方案1】:

    您可以使用inheritance 为您的 Sidekiq 工作人员启用特定警察。例如,如果您的工作人员居住在app/workers,那么您可以在那里创建一个从项目根目录继承的新规则集,然后启用您的自定义警察:

    # app/workers/.rubocop.yml
    inherit_from:
      - ../../.rubocop.yml
    require:
      - ../lib/rubocop/cop/custom/sidekiq_dont_use_keyword_arguments.rb
    Custom/SidekiqDontUseKeywordArguments:
      Enabled: true
    # For validation of this theory only; do not use this
    Lint/DuplicateMethods:
      Enabled: false
    

    要让您的自定义 cop 检测关键字参数,请使用 node.type 方法。 node.arguments 的元素本身就是节点,支持相同的方法,读取参数的type 将返回四个值之一:

    # Standard argument: perform(foo)
    :arg
    
    # Optional standard argument: perform(foo = 1)
    :optarg
    
    # Keyword argument: perform(foo:)
    :kwarg
    
    # Optional keyword argument: perform(foo: 1)
    :kwoptarg
    

    因此检查:kwarg:kwoptarg(并注意路径更改和附加Custom 模块以定义此警察的部门):

    # app/lib/rubocop/cop/custom/sidekiq_dont_use_keyword_arguments.rb
    
    module RuboCop
      module Cop
        module Custom
          class SidekiqDontUseKeywordArguments < RuboCop::Cop::Cop
            MSG = "Don't use keyword arguments in workers".freeze
            OBSERVED_METHOD = :perform
    
            def on_def(node)
              return if node.method_name != OBSERVED_METHOD
    
              node.arguments.each do |argument|
                if argument.type == :kwarg || argument.type == :kwoptarg
                  add_offense(node, location: :expression)
                end
              end
            end
          end
        end
      end
    end
    

    让我们以此作为示例工人:

    # app/workers/example_worker.rb
    class ExampleWorker
      # Standard argument; this will not trigger the cop
      def perform(foo); end
    
      # Optional standard argument; this will not trigger the cop
      def perform(foo = 1); end
    
      # Keyword argument; this will trigger the cop
      def perform(foo:); end
    
      # Optional keyword argument; this will trigger the cop
      def perform(foo: 1); end
    end
    

    运行 Rubocop 将返回以下输出:

    rubocop app/workers
    Inspecting 1 file
    C
    
    Offenses:
    
    app/workers/example_worker.rb:9:3: C: Custom/SidekiqDontUseKeywordArguments: Don't use keyword arguments in workers
      def perform(foo:); end
      ^^^^^^^^^^^^^^^^^^^^^^
    app/workers/example_worker.rb:12:3: C: Custom/SidekiqDontUseKeywordArguments: Don't use keyword arguments in workers
      def perform(foo: 1); end
      ^^^^^^^^^^^^^^^^^^^^^^^^
    
    1 file inspected, 2 offenses detected
    

    【讨论】:

      猜你喜欢
      • 2013-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 2021-07-06
      • 2019-01-16
      • 1970-01-01
      相关资源
      最近更新 更多