简体   繁体   English

这种方法如何超过Rubocop账户分支条件大小?

[英]How is this method exceeding the Rubocop Account Branch Condition size?

I have a simple before_save method used to assign an account_id based on whether a user_id , application_id or contact_id is already present in the model. 我有一个简单的before_save方法,用于根据user_idapplication_idcontact_id是否已存在于模型中来分配account_id

class Note < ApplicationRecord
  belongs_to :contact
  belongs_to :application
  belongs_to :user
  belongs_to :account

  before_save :assign_account_id

  private

  def assign_account_id
    self.account_id =
      if user_id.present?
        user.account.id
      elsif application_id.present?
        application.account.id
      elsif contact_id.present?
        contact.account.id
      end
  end
end

The method works and, in my opinion, is about as simple as I can get it, but Rubocop insists it is slightly over the Assign Branch Condition size (ABC size), where the limit is 15 and my method's ABC is 15.33 . 该方法有效,在我看来,就像我能得到它一样简单,但Rubocop坚持认为它稍微超过了指定分支条件大小(ABC大小),其中限制为15 ,我的方法的ABC为15.33

According to this article , the ABC size of 15 is achieved with 8 assignments, 8 branches and 8 conditions. 根据这篇文章 ,ABC大小为15,通过8个任务,8个分支和8个条件实现。 However, I only count 1 assignment self.account_id = , 1 branch (the return), and three conditions (the 3 if/elsif statements). 但是,我只计算1个赋值self.account_id = ,1个分支(返回)和3个条件(3个if / elsif语句)。

Am I mistaken? 我错了吗? Where are the additional assignments, branches or conditions coming from? 附加任务,分支机构或条件来自哪里? The calls to present? 打电话present? , traversing the model hierarchy? ,遍历模型层次结构?

NOTE: I'm note looking for alternative implementations, I'm interested in understanding what is causing this score. 注意:我注意寻找替代实现,我有兴趣了解导致此分数的原因。


For anyone interested, here's the solution I eventually went with that satisfies the ABC size. 对于任何感兴趣的人,这里是我最终使用的解决方案,满足ABC大小。

self.account_id = [
  user&.account&.id,
  application&.account&.id,
  contact&.account&.id
].find(&:present?)

I chose it because of the vertical list conveys the cascading nature of the fields the most strongly. 我选择它是因为垂直列表最强烈地传达了场的级联性质。 I felt I'd be able to return to this and still be able to grok what it's doing. 我觉得我能够回到这里,仍然能够理解它在做什么。

This is the web page that the rubocop documentation references in its source code , in the documentation for Metrics/AbcSize (as of the latest version; 0.61.0 ). 这是 rubocop文档在其源代码中引用 的网页 ,在Metrics/AbcSize的文档中(截至最新版本; 0.61.0 )。

To paraphrase, it says that: 换句话说,它说:

A scalar ABC size value (or "aggregate magnitude") is computed as: |ABC| = sqrt((A*A)+(B*B)+(C*C)) 标量ABC大小值(或“聚合幅度”)计算如下: |ABC| = sqrt((A*A)+(B*B)+(C*C)) |ABC| = sqrt((A*A)+(B*B)+(C*C))

Where A is the number of Assignments , B is the number of Branches and C is the number of Conditions . 其中A分配数, B分支数, C条件数

  • Your code has 1 Assignment ( self.account_id = ). 您的代码有1个分配self.account_id = )。
  • Your code has 15 Branches (!!!) ( user_id , .present? , user , .account , .id , application_id , .present? , application , .account , .id , contact_id , .present? , contact , .account and .id ) 您的代码有15个分支 (!!!)( user_id.present? , user.account.idapplication_id.present?application.account.idcontact_id.present? , contact.account.id
  • Your code has 3 Conditions ( if ... elsif ... elsif ). 您的代码有3个条件if ... elsif ... elsif )。

Plugging this into the above formula gives: 将其插入上述公式给出:

ABC = sqrt(1*1 + 15*15 + 3*3)
    = sqrt(235)
    = 15.32970...

And that's where the (rounded) value of 15.33 is coming from. 这就是15.33的(舍入)值来自的地方。


I know you're not really asking for an alternative implementation, but here's one anyway: 我知道你并不是真的要求一个替代的实现,但无论如何这里是一个:

def assign_account_id
  self.account_id = (user || application || contact).account.id
end

...And you could even consider moving those brackets into a separate method. ......你甚至可以考虑将这些括号移到一个单独的方法中。

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

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