3

ActiveSupport extends Object with an instance method blank?:

class Object
  def blank?
    respond_to?(:empty?) ? !!empty? : !self
  end
end

Could !!empty? be written as empty? instead? Is this a stylistic choice so that it reads easily as a method returning a boolean? Or is there something else?

sawa
  • 165,429
  • 45
  • 277
  • 381
eeeeeean
  • 1,774
  • 1
  • 17
  • 31
  • I presume you recognize that the operative line is the same as `self.respond_to?(:empty?)? !!self.empty? : !self` ? I don't understand why `!!` is needed since `empty?` returns a Boolean. – Cary Swoveland Jan 11 '16 at 19:25
  • Good job reading code and clarifying any doubts. This is a great way to learn new languages. – Leonel Galán Jan 11 '16 at 19:27
  • I've reopened the question because it is a bit different. The OP specifically asks why `!!` is needed in conjunction with a predicate method that is supposed to return a boolean value. – Stefan Jan 11 '16 at 20:39

5 Answers5

6

The reason for this is that !! coerces the response from empty to a boolean. Empty can be defined differently on different objects so it is possible that someone in rails could have defined .empty? to not return a boolean. Since .blank? needs to return a boolean the !! is needed to ensure that a boolean is returned.

NateSHolland
  • 1,130
  • 2
  • 11
  • 25
4

It is a common way to convert a truthy versus falesy value into strict true and false.

sawa
  • 165,429
  • 45
  • 277
  • 381
3

It is a common approach in Ruby to call !!(something). The result of the calculation will be boolean, not nil or something else:

!!(true) # true
!!(false) # false
!!(nil) # false
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
kimrgrey
  • 562
  • 2
  • 10
2

!! is used to force falsey/truthy values to false/true:

irb(main):001:0> !!nil == false
=> true
Leonel Galán
  • 6,993
  • 2
  • 41
  • 60
2

In fact, it used to be empty?. Here's the commit that changed it to !!empty?: https://github.com/rails/rails/commit/126dc47665c65cd129967cbd8a5926dddd0aa514

From the comments:

Bartuz:
Why double !! ? It returns the TrueClass / FalseClass anynway

fxn:
Because it is a dynamic language and subject to polymorphism, you just can't rely on empty? returning singletons, what you need to guarantee is that you return one no matter what.

The "improved" implementation however is incomplete, because you could just as well implement ! to return a non-boolean value:

class Foo
  def !
    nil
  end
end

Foo.new.blank? #=> nil

To handle both methods (empty? and !), it should be implemented as:

!!(respond_to?(:empty?) ? empty? : !self)
Stefan
  • 109,145
  • 14
  • 143
  • 218