The method is doing three things:
- Determining whether or not to set
display_name
.
- Determining the default display name.
- Setting
display_name
to the default value.
Each of those adds to the Abc metric. The biggest contributor to the Abc metric is determining the default display name. To me, that also seems like the most logically separate. We can lower the Abc metric by extracting that responsibility to its own method.
def set_default_display_name
self.display_name = default_display_name if display_name.blank?
end
def default_display_name
credentials_of_type = user.credentials.where(type: type)
return name if credentials_of_type.none? || user.credentials.where(display_name: name).none?
"#{name} #{credentials_of_type.count + 1}"
end
Extracting default_display_name
makes it slightly simpler to test the default display name logic. You could also use that logic elsewhere, e.g., a UI could show the current display name and ask if they want to reset it to the default display name.
At this point, I'd question whether set_default_display_name
is necessary or if it could be inlined.
Another option, is to keep your code as is and modify your .rubocop.yml file to increase the threshold of the Abc metric, or disable it entirely. The Abc metric is all about code size, not complexity. Theoretically, bugs increase with code size. You'd have to determine if this low of a threshold makes it easier to mask bugs. (Based on an earlier thread, the answer is probably, "yes", since your original code seems to have a bug. I retained the functionality of your original code in this example.)
--- Addendum ---
@ramonrails makes a good point in the comments. I'm usually fine with return
guard clauses at the top of ruby methods. However, I agree that having a return
in the middle of this method is not ideal.
This answer was only addressing the ABC question. If this were my code, I'd extract the credentials logic completely from this "view" code.
Something like:
def default_display_name(type_credentials)
type_credentials.any? ? "#{name} #{type_credentials.count + 1}" : name
end
We're far afield from the question at that point though.