ecdfernandes ecdfernandes - 2 years ago 84
Ruby Question

rails can't read JSON request with "false" value as attribute

Well, I'm building a RESTfull API using rails 4.2.6 and ruby 2.3.0.
I've an :programs resources and whenever I try to make an POST request through Google Postman, I'm receiving a "can't be blank" error.
Wait, let me illustrate...

When I send this, through Postman:

"program": {
"expiration_points": "false"

I'm getting back this:

"errors": {
"expiration_points": [
"can't be blank"

I've already tried: "false", 'false', false and :false.

But it works fine, when I make the POST request with "true" or true value for the expiration_points.

Remembering that I've defined a default: false value for the expiration_points attribute on migration.

So... The question is, what I'm doing wrong? Thanks btw.

Answer Source

So you have this in your model:

validates :expiration_points, presence: true 

So what does presence: true do? We could check the validates documentation but that just says:

This method is a shortcut to all default validators and any custom validator classes ending in 'Validator'. Note that Rails default validators can be overridden inside specific classes by creating custom validator classes in their place such as PresenceValidator.

but that just gives us a bunch of examples and tells us what some of the options do. You could look for PresenceValidator documentation but there's no such thing.

If you'd been using Rails for awhile, you'd know that

validate :f, :presence => true

is functionally equivalent to:

validates_presence_of :f

and the validates_presence_of documentation is still around:

Validates that the specified attributes are not blank (as defined by Object#blank?).
If you want to validate the presence of a boolean field (where the real values are true and false), you will want to use validates_inclusion_of :field_name, in: [true, false].

This is due to the way Object#blank? handles boolean values: false.blank? # => true.

So you don't want presence: true at all, you want to use in: [ true, false ] instead:

validate :expiration_points, :in => [ true, false ]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download