I’m quite sure
blank? and friends are universally loved. But, just recently I’ve learned through an annoying bug that
false.blank? == true. This seems unexpected. Can anyone help me to understand the rationale for that?
I’m quite sure
The great question is: why is there a method that verifies if a value is blank, if that value could never, by definition, be blank?
Accordingly to the 7.0.4 docs: “An instance of ActiveSupport::TimeWithZone is never blank”
Of course that
blank? has at least another 3 different implementations in other classes, but in this case doesn’t make sense to me either.
I’ll keep digging into docs and implementation trying to answer that, but it oddingly seems a bug. Nice observation!
false.blank? == true seems correct for me.
In Ruby only
false in a conditional. Everything else evaluates to
true. These semantics are simple but sometimes you want different semantics. You want things like an empty string or an empty array to evaluate to false. Therefore as an extension Rails adds the concept of “blank” to includes other things. But the
nil are also considered blank. The new items added are in addition to what is already considered
false. Some languages/libraries uses the term “falsey” as this sort of extended version of false.
NOTE: There are other things that can evaluate to blank besides just
''. Really anything that responds to
blank?. I just used
'' as to common examples of things that are blank.
I disagree with this. The word “blank” to me means “has no value”. Boolean has 3 possible states - true, false, and nil. Nil is the absence of value, so it’s blank. True and false are both values, so neither are blank.
This confusion has caused a number of logic issues for me in Rails.
The docs define the meaning of blank.
While the word may mean different things to each of us, the “correct” meaning is what’s defined in the docs.
I agree this is bit confusing. If you’re testing a boolean, you could use
nil? to get the result you’re after.
@wale Yeah, I’m not debating how it’s implemented. My point is that I think how it’s implemented is not intuitive.
In Ruby there is no Boolean type. The boolean space is flat, with
nil being false, and everything else being true.
The boolean semantics of a Ruby object do not matter for
blank?, as you can see by the amount of objects that are true and blank.
In the case of the singletons,
false is considered to be blank and
true is not. And this definition makes sense to me. You need to revise the definition of blank in your head to match what it truly means (which is not absence of value).
That said, I believe people tend to overuse
blank?, I prefer
nil? or just evaluate the object in boolean context where that is enough.
I realize this is semantics and one person’s subjective interpretation of what words mean. It also doesn’t matter one bit what I think because there’s no way this is going to change at this point.
To me, the implementations of
present? are both incorrect for a boolean false. The method
present? means “has value” in the context of a string, so why doesn’t it in the context of a boolean? The same argument for
blank? - it means “has no value” for a string but not for a boolean. That feels inconsistent.
For evidence to back up my case (and then I’ll give it a rest), you can’t validate the presence of a boolean. Instead you have to validate inclusion in
[true,false] and that just feels wrong. If there weren’t a presence validation that behaves incorrectly (IMO), I wouldn’t care at all.
I know what you’re saying, and from “a certain point of view”, you are absolutely correct. I used to believe that a boolean could only have two states, but a co-worker convinced me otherwise. It all depends on what you want that field to represent.
For many things, I often will use the database default to enforce that if it isn’t true, it is FALSE, and therefore never NIL. Example might be a
But that’s not the same thing as I might need for an
approved boolean. In that case, there are really three possible states: yes, no, and ‘haven’t decided’. A true (nullable) boolean can represent all of them. Perhaps that would be better modeled by an enum, with named states for the three possibilities, but that’s the example that opened my eyes.
Maybe we make it sweeter, and add a
validates :my_field, boolean: true to the framework. But would that be another bikeshed to paint?
Yes, exactly. You described my two scenarios perfectly. Sometimes I want to validate that the user explicitly answered a true/false question, and in that case the absence of true is not false, it’s nil, and assuming false is incorrect.
As I said, there’s a workaround for this so it’s a minor annoyance. The fact that we’re even debating such a small issue must mean that Rails is pretty great.
If you know it’s going to be one of
true, you can validate the presence of a boolean with the
@joeldrapper Trying to understand what you mean. Can you give me an example?
@kiddrew sorry, I mean if you have a value that you know is a nullable boolean (
true), then you can check if it “has a value” with the
true.nil? # → false false.nil? # → false nil.nil? # → true
@joeldrapper Aha, yeah I can write a custom validator. I just meant that you can’t use the built-in PresenceValidator for a boolean. As I said, it’s a minor annoyance.
I might be wrong here, but only
nil has no value in Ruby, so we already have a method answering that