ruby-on-railsrubocop

Rubocop Assignment Branch Condition Size Error


I have a class Invoice that belongs to an Entity. In the entity, the current period, meaning the business year, is set. When creating a new invoice I want to have an invoice number that is an increment of 1 over the last highest invoice number for the period. If there are no invoices in the current period yet, the invoice number is taken from a preset in another model: InvoiceNumberFormat.start_at.

class Invoice < ApplicationRecord
  belongs_to :entity
  has_one :invoice_number_format, through: :entity, dependent: :restrict_with_error
  
  before_create :generate_invoice_number

  private

  def generate_invoice_number
    self.number = if entity.invoices.where(period: entity.current_period).count.zero?
                    invoice_number_format.start_at
                  else
                    entity.invoices.where(period: entity.current_period).maximum(:number) + 1
                  end
  end
end

This code generated the Rubocop error

Assignment Branch Condition Size for generate_invoice_number is too high. [<1, 17, 2>17.15/17]

I tried to read up on ABC metrics and I'm starting to understand some of this but the application to my little code block totally eludes me. I'm curious where this score comes from in my example. Moreover I am wondering if there is a less complicated way to achieve what I'm trying to achieve.


Solution

  • First simple solution is

    def generate_invoice_number
      self.number =
        if entity.invoices.exists?(period: entity.current_period)
          entity.invoices.where(period: entity.current_period).maximum(:number) + 1
        else
          invoice_number_format.start_at
        end
    end
    

    but for both conditions there will be 2 sql requests

    So I prefer another option

    def generate_invoice_number
      max_num = entity.invoices.where(period: entity.current_period).maximum(:number)
    
      self.number = if max_num.nil?
        invoice_number_format.start_at
      else
        max_num + 1
      end
    end
    

    In this solution 2 requests will be in case where max_num is nil, in another - just one