Rubocop: ZeroLengthPredicate assumes that objects respond to length or size also respond to empty?

Created on 4 Feb 2016  路  11Comments  路  Source: rubocop-hq/rubocop

Given this code:

class Foo
  def length
    0
  end
end

Foo.new.length > 0

rubocop reports:

`foo.rb:7:4: C: Style/ZeroLengthPredicate: Use !empty? instead of length > 0.

but making that change will result in:

undefined method `empty?' for #<Foo:0x007ff3db079f78> (NoMethodError)

Most helpful comment

@alexdowad I just ran into a real-world example of a commonly used Ruby library which only implements #size and not #length or #empty.

Sidekiq::ProcessSet.new.size > 0 gets changed to !Sidekiq::ProcessSet.new.empty? and throws an error.

All 11 comments

This is a valid assumption to make in the majority of cases. Can you provide a real-world example of a commonly used Ruby library which implements #length but not #empty??

@alexdowad I agree it will work in the majority of cases, but it is not correct for _all_ cases. For example,if I make an object representing a Vehicle and length represents it's length in meters. I may need to say "If the car is greater than 3m, then driver must have a commercial license". There's lots of usages of length or size that are not "discrete number of parts".

In that case RC will produce a false positive. The question is, are false positives common enough and serious enough to make this cop more harmful than helpful?

...Actually, I should have said: RC will not generate a false positive in the hypothetical situation you mention. Because this cop looks only for .length == 0, not .length > 3.

This was a calculated risk. I should always encourage people to add empty? predicates. If people see this as a big problem, they should just disable the check.

It just happened to me on Mysql2::Result (it doesn't implement empty?)
It's quite popular rubygem.

This happened to me with Rails 3.2 --
A controller checked params[:file].size == 0, which worked fine before, but got autocorrected to params[:file].empty?, which throws
undefined method 'empty?' for #<ActionDispatch::Http::UploadedFile:0x4e5e22e1>

This can lead to some problems when making SketchUp extensions. In the SketchUp Ruby API a Vector3d has a length method returning a Length object (a physical length). There is however no Vector3d.empty? method, as a zero length vector isn't refereed to as "empty".

@alexdowad I just ran into a real-world example of a commonly used Ruby library which only implements #size and not #length or #empty.

Sidekiq::ProcessSet.new.size > 0 gets changed to !Sidekiq::ProcessSet.new.empty? and throws an error.

Worth mentioning I just hit this issue- ideally you should be able to trust rubocop auto-corrects, but you can't for this one!

I'll add one more example, Restforce::Collection.

In our case, we'll disable autocorrect for this cop but leave the rule enabled, so that we know about it and we can add an inline exception to the rule if needed.

While I do agree that using #empty? is a good suggestion, this is the first cop that breaks the expectation that I can trust RuboCop's autocorrect. Maybe it was a wrong assumption to begin with, but I haven't had problems with other cops.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mikegee picture mikegee  路  3Comments

david942j picture david942j  路  3Comments

Aqualon picture Aqualon  路  3Comments

cabello picture cabello  路  3Comments

benoittgt picture benoittgt  路  3Comments