Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #5090 (closed defect: invalid)

Opened 3 years ago

Last modified 2 years ago

validates_presence_of :boolean_var `ActiveRecord::RecordInvalid: Validation failed` if :boolean_var == 0

Reported by: johnwulff@gmail.com Assigned to: David
Priority: normal Milestone:
Component: ActiveRecord Version:
Severity: normal Keywords:
Cc:

Description

class CreateNodes < ActiveRecord::Migration
  def self.up
    create_table :nodes do |t|
      t.column :boolean_var, :boolean, :default => 0
    end
  end
end

class Node < ActiveRecord::Base
  validates_presence_of :boolean_var
end

class NodeTest < Test::Unit::TestCase
  def test_boolean_var
    node = Node.new
    node.boolean_var = 0
    node.save!
  end
end

  1) Error:
test_boolean_var(NodeTest):
ActiveRecord::RecordInvalid: Validation failed: Boolean var can't be blank
    /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.2/lib/active_record/validations.rb:736:in `save!'
    /Users/jwulff/Development/NodeTestApp/test/unit/node_test.rb:5:in `test_boolean_var'

1 tests, 0 assertions, 0 failures, 1 errors

Change History

05/16/06 01:19:14 changed by johnwulff@gmail.com

An effective work-around:

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

05/16/06 08:26:44 changed by rails@tddsworld.com

John: what are you trying to achieve here? Usually, validates_presence_of on a boolean is like checking it's true. It's intended for requiring that a checkbox be checked, for instance.

In effect, your boolean won't ever be nil *except* before the model is first saved, or if (or so I surmise) your DB column would allow NULL and happens to be NULL for that particular line. As your model example uses a 0 default, any attempt at loading a model will result in your boolean attr being assigned to either false or true.

So is there really a defect here? Is a 0-thus-false value deemed still-present, or deemed absent (as most apps seem to use it anyhow)?

05/23/06 04:56:19 changed by johnwulff@gmail.com

The documentation for validates_presence_of says: "Validates that the specified attributes are not blank"

Doesn't that mean that the attribute must be set? Must not be null?

I ran into this problem *because* my boolean was *not* set after the model was first saved.

(follow-up: ↓ 5 ) 05/23/06 05:13:58 changed by blake@near-time.com

To me, validates_presence_of indicates a check for the presence of a value for that attribute. It follows then that presence is defined as any value that is not nil. true and false are instances of TrueClass and FalseClass, thus not nil and therefor are present. 0 is also present.

Isn't a non-conflation of false and nil idiomatic of the Ruby language? In terms of AR serialization, we serialize 0 and 1 as true and false and nil as NULL. Isn't 0 and false as non-present out of line with the expectations of the programmer.

Also consider the example of a file column. If I do

validates_presence_of :file_size

But the file is empty, shouldn't I correctly expect the model to pass validation?

This behavior seems to break expectations and established idioms...

(in reply to: ↑ 4 ) 01/17/07 13:10:09 changed by Spakman

Replying to blake@near-time.com:

To me, validates_presence_of indicates a check for the presence of a value for that attribute. It follows then that presence is defined as any value that is not nil. true and false are instances of TrueClass and FalseClass, thus not nil and therefor are present. 0 is also present.

<snip>

This behavior seems to break expectations and established idioms...

I agree, I expect validates_presence_of to work exactly as you describe and use other validation methods to check for specific values.

(follow-up: ↓ 7 ) 01/17/07 22:40:49 changed by manfred

  • status changed from new to closed.
  • resolution set to invalid.

validates_presence_of behaves exactly as documented. Please use {{{validates_inclusion_of :boolean_var, :in => [true, false]}} as the first commenter suggested.

(in reply to: ↑ 6 ) 06/11/07 21:50:12 changed by roberto.r

Replying to manfred:

validates_presence_of behaves exactly as documented. Please use {{{validates_inclusion_of :boolean_var, :in => [true, false]}} as the first commenter suggested.

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

This doesn't seem to work. Anything not nil evaluates to either true or false and is acceptable.