如何编写 RuboCop Cop 以防止使用关键字参数编写 Sidekiq worker?
How to write a RuboCop Cop to prevent writing Sidekiq workers using keyword arguments?
不久前,我发现 you can't use keyword arguments when defining Sidekiq workers。因为它只会在排队后引发异常,所以我想防止它永远进入生产环境。为此,我想添加一个 cop 来检查 #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 工作人员。我在这里遵循正确的方法吗?有更好的方法吗?
您可以使用 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
将 return 四个值之一:
# 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 将 return 以下输出:
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
不久前,我发现 you can't use keyword arguments when defining Sidekiq workers。因为它只会在排队后引发异常,所以我想防止它永远进入生产环境。为此,我想添加一个 cop 来检查 #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 工作人员。我在这里遵循正确的方法吗?有更好的方法吗?
您可以使用 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
将 return 四个值之一:
# 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 将 return 以下输出:
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