Rails: how do I validate that something is a boolean? - ruby-on-rails

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

Since Rails 3, you can do:
validates :field, inclusion: { in: [ true, false ] }

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!

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.

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

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] }

Related

Confusion between hashes and symbols

May you help me understand the concept behind the hash and especially when we use symbols.
:name is a symbol right ?
we can use symbol as a key for our hashed right ?
:name and name: for example : those are two syntaxes but it describes a symbol right ?
when we have this for example :
Geocode.configure(
units: :km
)
here units does a reference to a specified argument called units in the configure function right ? and :km is the symbol we want to send through the variable unit or am I wrong ?
A last example :
validates :home_type, presence: true
Here we try to send to the validates function the symbol home_type right ?
and the second argument is named "presence" and we want to send the boolean true through this variable right ?
I am sorry if you don't understand my question, don't hesitate to ask me.
I got many headeck nderstanding those syntaxes.
Thanks a lot !
Geocode.configure(units: :km)
We are passing an hash to the configure method. This hash {units: :km}. Convenient syntax for {:units => :km}. So an hash with a key value pair with key symbol (:units) and value symbol (:km).
validates :home_type, presence: true
Here we are passing to the validates method a symbol :home_type and an hash, {presence: true}, or {:presence => true}. So the key is :presence symbol, the value is the boolean true.
It is very basic & nothing but simplified convention in ruby
validates :home_type, presence: true, if: :check_user
is similar to
validates :home_type, { :presence => true, :if => :check_user }
So when I write as,
link_to 'Edit', edit_path(user), class: 'user_one', id: "user_#{user.id}"
In above, link_to is ActionHelper method which is taking 3 arguments where last one is hash { class: 'user_one', id: "user_#{user.id}" }

Which takes precedence: Rails type casting or validation?

I am very curious about what this expected behavior is for Rails 4.2 and I have not been able to find an answer to my question.
I'm adding validation to a model on all the time attributes. I want them to ONLY accept integers, not numerical strings. The data type in my schema for this attribute is an integer. I have my validation like so:
RANGE = 0..59
validates :start_minute, inclusion: { in: RANGE }, numericality: true
I've tried these other validations as well. I get the same result.
validates_numericality_of :start_minute, inclusion: { 0..59, only_integer: true }
validates :start_minute, inclusion: { in: 0..59 }, numericality: { only_integer: true }
When I pass my params to my controller from the request spec, start_minute is "12". BUT when I look at the created object, the start_minute is 12.
According to this article by ThoughtBot:
"This is because Active Record automatically type casts all input so that it matches the database schema. Depending on the type, this may be incredibly simple, or extremely complex."
Shouldn't the object not be able to be created? Is the typecasting taking precedence of my validation? Or is there something wrong with my validation? I appreciate any insight to this as I haven't been able to determine what is happening here. I've also created a model spec for this and I'm still able to create a new object with numerical strings.
Thank you for any insight you can give on this. I am still learning the magic of Rails under the hood.
From the rails docs it says,
If you set :only_integer to true, then it will use the
/\A[+-]?\d+\z/
What it(only_integer validator) does is that it validates that the format of value matches the regex above and a string value that contains only numbers like '12' is a match(returns a truthy value which is 0 and passes the validation).
2.3.1 :001 > '12' =~ /\A[+-]?\d+\z/
=> 0

rails validate in model that value is inside array[2]

This question similar with this one, but those answers don't work for me(May be they are deprecated). I don't want to reopen old question by bounty, because I have a little different arguments. In my case i have an array like this
allowed_values = [99.50..200] and I tried with:
class Thing < ActiveRecord::Base
validates :price, :inclusion=> { :in => allowed_values }
It does not work. I have tried with so many ways by examples validation here. I have little experience on coding rails. So please, help to find solution.
More info:
ruby version: ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]
rails version: Rails 4.1.5
The problem must be with the way you pass the allowed_values array.
You can go with this:
validates :price, inclusion: { in: (99.50..200) }
Or, with a constant:
ALLOWED_VALUES = (99.50..200).freeze
validates :price, inclusion: { in: ALLOWED_VALUES }
[99.50..200] is an array that contains a single element: the range (99.50..200).
You are testing whether the value is in the list of objects in the array, but what you probably want is to test whether it is in the range.
So define:
allowed_values = (99.50..200)
instead of:
allowed_values = [99.50..200]
I have found a solution: How to implement min/max validator in Rails 3?
validates :price, :inclusion=> { :in => allowed_values }
does not work, it seems, validation style was changed after 3 version of rails. And I tried with:
validates_inclusion_of :number, :in => min_price..max_price
This solution has no valid case if min_price=10.5 and max_price=11
My solution is:
validates :price, :numericality => { :greater_than_or_equal_to => min_price, :less_than_or_equal_to => :max_price }
I don't know ruby(and rails) deeply and I am not right some cases. but this solution is working

Ruby ActiveRecord: validate format of an integer field

I'm trying to validate the format of a field in an ActiveRecord. I want this field to either be empty, or contain a sequence of digits only (it is containing an optional port number for a database connection). I'm currently trying this:
validates_format_of :port, with: /\A[0-9]*\Z/, message: 'Only numbers allowed'
but without luck. I've found that adding a required number by using for example {1, 6} sort of works, but makes the field mandatory.
Any advice?
Many thanks in advance,
Joseph.
If you're looking to validate so that only numbers are allowed, then you should be able to use this:
validates :port, :numericality => {:only_integer => true}
You may want to try to validate the numericality of the field, like so:
validates_numericality_of :port, :only_integer => true
:only_integer will ensure that the value entered for :port is an integer.
You can also just add allow_blank: true
You can use this syntax as well
validates numericality: :only_integer

Ensure_inclusion_of keeps passing when it should fail?

I'm using Shoulda and Rspec for testing.
When I try this in my test spec it keeps passing when I haven't done the validations in the model:
it { should ensure_inclusion_of(:private).in_array(%w[true false]) }
The attribute is a boolean that is either true or false:
validates_inclusion_of :private, :in => [true, false]
How would I write this correctly?
True and False are not strings so don't use %w.
it { should ensure_inclusion_of(:private).in_array([true, false]) }
Update - 10th Apr 2014
This validation will not work in current versions of Shoulda and, as per this recent commit, it will not be fixed but will instead raise an exception.
As any value assigned to a boolean field will be cast to either true (set by true, 1, '1', 't', 'T', 'true', 'TRUE') or false (set by anything else) my preferred approach for testing a boolean field is as follows:
For a boolean that allows nulls in the database - no test is required, any possible value will be valid
For a boolean that does not allow nulls in the database - use it { should_not allow_value(nil).for(:field) which will pass when the validates :field, inclusion: { in: [true,false] } is set on the model

Resources