清理参数哈希时减少 AbcSize 指标
Reduce AbcSize metric when sanitizing params hash
我的 Purchases 控制器中有一个简单的方法,可以在应用强参数之前调整来自 params 哈希的用户表单输入。
def sanitize_params
params[:purchase][:invoice] = nil if params[:purchase][:invoice] == ''
params[:purchase][:note] = nil if params[:purchase][:note] == ''
params[:purchase][:product_id] = nil if params[:purchase][:product_id].blank?
end
Rubocop 因 Metrics/AbcSize… [<3, 19, 5> 19.87/17]
被捕。
ABC指标中的‘Branch’如何计算为19?
我可以重构为:
def sanitize_params
unsanitized_purchase_params = params[:purchase]
params[:purchase][:invoice] = nil if unsanitized_purchase_params[:invoice] == ''
params[:purchase][:note] = nil if unsanitized_purchase_params[:note] == ''
params[:purchase][:product_id] = nil if unsanitized_purchase_params[:product_id].blank?
end
这就通过了,但是以可读性和额外代码为代价。
为什么'Branch'在原始代码中是19?我应该关心吗? (我的实际用例有一条额外的相似线,所以那里的指标更高)。有更好的方法吗?
谢谢
丹尼尔
目前 Rails 参数未实现 #deep_transform_values!
,但您可以执行以下操作:
def sanitize_params
%i[invoice note product_id].each do |param_name|
params[:purchase][param_name] = params[:purchase][param_name].presence
end
end
或者:
def sanitize_params
params[:purchase] = params[:purchase].transform_values(&:presence)
end
更新。您还可以考虑使用 https://github.com/rmm5t/strip_attributes - 此 gem 将在模型级别
上用 nils 替换空值
由 documentation 给出:
Branch -- an explicit forward program branch out of scope -- a function call, class method call, or new operator
所以,ABC中的“Branch”计算为“跳出当前方法的任何东西”。
按照您描述的方法,
def sanitize_params
params[:purchase][:invoice] = nil if params[:purchase][:invoice] == ''
params[:purchase][:note] = nil if params[:purchase][:note] == ''
params[:purchase][:product_id] = nil if params[:purchase][:product_id].blank?
end
这些是需要离开当前方法的 19 个调用:
01. params (on line 1, before the assignment)
02. params[:purchase] (on line 1, before the assignment)
03. params[:purchase][:invoice] (on line 1, before the assignment)
04. params (on line 1, after the assignment)
05. params[:purchase] (on line 1, after the assignment)
06. params[:purchase][:invoice] (on line 1, after the assignment)
07. params (on line 2, before the assignment)
08. params[:purchase] (on line 2, before the assignment)
09. params[:purchase][:note] (on line 2, before the assignment)
10. params (on line 2, after the assignment)
11. params[:purchase] (on line 2, after the assignment)
12. params[:purchase][:note] (on line 2, after the assignment)
13. params (on line 3, before the assignment)
14. params[:purchase] (on line 3, before the assignment)
15. params[:purchase][:product_id] (on line 3, before the assignment)
16. params (on line 3, after the assignment)
17. params[:purchase] (on line 3, after the assignment)
18. params[:purchase][:product_id] (on line 3, after the assignment)
19. params[:purchase][:product_id].blank? (on line 3, after the assignment)
重要提示:无论何时您调用 params
,您都在访问不同的方法,并且每次您访问散列上的索引时,您都是在该散列上调用一个方法来访问所需的索引。
关于您是否应该关心:ABC 大小是衡量代码质量的标准,因此通常最好坚持使用它,当然,只要它有意义。
但是有一些方法可以重构代码以降低 ABC 的复杂性。一项建议如下:
def sanitize_params
params.tap do |params|
params[:purchase][:invoice] = nil if params.dig(:purchase, :invoice) == ''
params[:purchase][:note] = nil if params.dig(:purchase, :note) == ''
params[:purchase][:product_id] = nil if params.dig(:purchase, :product_id).blank?
end
end
在这个例子中,Branch 的复杂度降低了很多,因为我们只调用外部 params
一次并应用 tap
块内的所有更改。此外,通过在参数上使用 dig
方法,我们只调用一种方法来达到我们想要的深度。
另一个想法是将此方法分解为更具体的方法来清理每个属性,例如。
希望对您有所帮助。
我的 Purchases 控制器中有一个简单的方法,可以在应用强参数之前调整来自 params 哈希的用户表单输入。
def sanitize_params
params[:purchase][:invoice] = nil if params[:purchase][:invoice] == ''
params[:purchase][:note] = nil if params[:purchase][:note] == ''
params[:purchase][:product_id] = nil if params[:purchase][:product_id].blank?
end
Rubocop 因 Metrics/AbcSize… [<3, 19, 5> 19.87/17]
被捕。
ABC指标中的‘Branch’如何计算为19?
我可以重构为:
def sanitize_params
unsanitized_purchase_params = params[:purchase]
params[:purchase][:invoice] = nil if unsanitized_purchase_params[:invoice] == ''
params[:purchase][:note] = nil if unsanitized_purchase_params[:note] == ''
params[:purchase][:product_id] = nil if unsanitized_purchase_params[:product_id].blank?
end
这就通过了,但是以可读性和额外代码为代价。 为什么'Branch'在原始代码中是19?我应该关心吗? (我的实际用例有一条额外的相似线,所以那里的指标更高)。有更好的方法吗? 谢谢 丹尼尔
目前 Rails 参数未实现 #deep_transform_values!
,但您可以执行以下操作:
def sanitize_params
%i[invoice note product_id].each do |param_name|
params[:purchase][param_name] = params[:purchase][param_name].presence
end
end
或者:
def sanitize_params
params[:purchase] = params[:purchase].transform_values(&:presence)
end
更新。您还可以考虑使用 https://github.com/rmm5t/strip_attributes - 此 gem 将在模型级别
上用 nils 替换空值由 documentation 给出:
Branch -- an explicit forward program branch out of scope -- a function call, class method call, or new operator
所以,ABC中的“Branch”计算为“跳出当前方法的任何东西”。
按照您描述的方法,
def sanitize_params
params[:purchase][:invoice] = nil if params[:purchase][:invoice] == ''
params[:purchase][:note] = nil if params[:purchase][:note] == ''
params[:purchase][:product_id] = nil if params[:purchase][:product_id].blank?
end
这些是需要离开当前方法的 19 个调用:
01. params (on line 1, before the assignment)
02. params[:purchase] (on line 1, before the assignment)
03. params[:purchase][:invoice] (on line 1, before the assignment)
04. params (on line 1, after the assignment)
05. params[:purchase] (on line 1, after the assignment)
06. params[:purchase][:invoice] (on line 1, after the assignment)
07. params (on line 2, before the assignment)
08. params[:purchase] (on line 2, before the assignment)
09. params[:purchase][:note] (on line 2, before the assignment)
10. params (on line 2, after the assignment)
11. params[:purchase] (on line 2, after the assignment)
12. params[:purchase][:note] (on line 2, after the assignment)
13. params (on line 3, before the assignment)
14. params[:purchase] (on line 3, before the assignment)
15. params[:purchase][:product_id] (on line 3, before the assignment)
16. params (on line 3, after the assignment)
17. params[:purchase] (on line 3, after the assignment)
18. params[:purchase][:product_id] (on line 3, after the assignment)
19. params[:purchase][:product_id].blank? (on line 3, after the assignment)
重要提示:无论何时您调用 params
,您都在访问不同的方法,并且每次您访问散列上的索引时,您都是在该散列上调用一个方法来访问所需的索引。
关于您是否应该关心:ABC 大小是衡量代码质量的标准,因此通常最好坚持使用它,当然,只要它有意义。
但是有一些方法可以重构代码以降低 ABC 的复杂性。一项建议如下:
def sanitize_params
params.tap do |params|
params[:purchase][:invoice] = nil if params.dig(:purchase, :invoice) == ''
params[:purchase][:note] = nil if params.dig(:purchase, :note) == ''
params[:purchase][:product_id] = nil if params.dig(:purchase, :product_id).blank?
end
end
在这个例子中,Branch 的复杂度降低了很多,因为我们只调用外部 params
一次并应用 tap
块内的所有更改。此外,通过在参数上使用 dig
方法,我们只调用一种方法来达到我们想要的深度。
另一个想法是将此方法分解为更具体的方法来清理每个属性,例如。
希望对您有所帮助。