124

Does rails have a validator like validates_numericality_of for boolean or do I need to roll my own?

aarona
  • 35,986
  • 41
  • 138
  • 186

5 Answers5

262

Since Rails 3, you can do:

validates :field, inclusion: { in: [ true, false ] }
Luca Spiller
  • 2,248
  • 4
  • 24
  • 28
Drew Dara-Abrams
  • 8,016
  • 11
  • 40
  • 48
  • 2
    So, this gets the validation right, but the error message is not helpful for the end user: "myfield is not included in the list" – Peter Sankauskas Mar 28 '13 at 05:12
  • 3
    Good point. You can customize the error message: http://guides.rubyonrails.org/active_record_validations_callbacks.html#message – Drew Dara-Abrams Mar 28 '13 at 16:56
  • 60
    Shorter form `validates :field, inclusion: [true, false]` – barelyknown Jun 29 '13 at 13:33
  • 10
    Note that you cannot have the usual validation for the presence (`validates :field, presence: true`) for a boolean field (the field would not be valid for a `false` value). But in both Rails 3 and 4, having `validates :field, inclusion: [true, false]` would test for inclusion in a list of values, with the side-effect to test for the field's presence (unless one of those values is `nil` of course). – Martin Carel Jul 14 '15 at 19:38
  • 2
    And for those who need it with an error-message: `validates :field, inclusion: { in: [ true, false ], message: "Please, select one!" }` – tagaism Mar 23 '18 at 09:28
  • But this does not validate if the field is assigned with a string value. Say `'True'` or `'Some value'`. These string values are definitely not boolean. But validation does not fail for these. Any updates on this? – SriramK89 Feb 27 '19 at 14:08
43

I believe for a boolean field you will need to do something like:

validates_inclusion_of :field_name, :in => [true, false]

From an older version of the API: "This is due to the way Object#blank? handles boolean values. false.blank? # => true"

I'm not sure if this will still be fine for Rails 3 though, hope that helped!

Budgie
  • 2,279
  • 1
  • 21
  • 26
  • lol @ Rails 3. I can bet this will be the caveat for months to come. Ok, I thought this migth have been it and you agree. Thanks! – aarona Aug 31 '10 at 11:19
  • It's true for Rails 4! Wow, false.blank? # => true just seems like the *wrong* answer, something I would not expect from Rails. – Dan Barron Sep 12 '13 at 12:49
  • 1
    This does not work, as any string eg, "foo" will be converted into `true`. – Ka Mok Jun 04 '18 at 22:55
15

When I apply this, I get:

Warning from shoulda-matchers:

You are using validate_inclusion_of to assert that a boolean column allows boolean values and disallows non-boolean ones. Be aware that it is not possible to fully test this, as boolean columns will automatically convert non-boolean values to boolean ones. Hence, you should consider removing this test.

user708617
  • 196
  • 1
  • 4
  • For fields where null is allowed, does it still convert nil to boolean? – mwfearnley Sep 28 '16 at 16:09
  • 1
    Just remove that test, except if column is nullable you should do this: it { should allow_value(nil).for(:field) } [Reference](https://www.rubydoc.info/github/thoughtbot/shoulda-matchers/Shoulda%2FMatchers%2FActiveModel:validate_inclusion_of) – Ardi Nusawan Nov 19 '19 at 08:36
  • The link in the above comment is broken, but here's a working link: http://matchers.shoulda.io/docs/v4.4.1/Shoulda/Matchers/ActiveModel.html#validate_inclusion_of-instance_method – Dave Powers Nov 11 '20 at 18:06
6

You can use the shorter version:

validates :field, inclusion: [true, false]

Extra thought. When dealing with enums, I like to use a constant too:

KINDS = %w(opening appointment).freeze

enum kind: KINDS

validates :kind, inclusion: KINDS
Flavio Wuensche
  • 9,460
  • 1
  • 57
  • 54
3

Answer according to Rails Docs 5.2.3

This helper (presence) validates that the specified attributes are not empty. It uses the blank? method to check if the value is either nil or a blank string, that is, a string that is either empty or consists of whitespace.

Since false.blank? is true, if you want to validate the presence of a boolean field you should use one of the following validations:

validates :boolean_field_name, inclusion: { in: [true, false] }
Cody Elhard
  • 655
  • 1
  • 7
  • 17
  • This the same answer as a previous one except the updated documents reflect the fact that hash rockets are no longer necessary. +1. – aarona May 30 '19 at 22:10