Problem validating boolean

Hi

I've got a problem validating a boolean and I can't see what the problem is. Here's my model:

   class FinanceAgreement < ActiveRecord::Base      belongs_to :asset

     validates_presence_of :finance_company      validates_inclusion_of :balance, :in => 0.01..10_000_000      validates_inclusion_of :term, :in => 1..600      validates_numericality_of :term, :only_integer => true      validates_inclusion_of :linked_to_residual_value_of_asset, :in => [true, false]    end

and here's the RSpec code I'm using to test it:

   context "A FinanceAgreement with valid attributes" do      setup do        @finance_agreement = FinanceAgreement.new(:finance_company => "Jigsaw Finance", :start_date => nil,                                                  :balance => 5000, :term => 36, :linked_to_residual_value_of_asset => true)      end

     aspect "validation" do        specify "should be valid" do          @finance_agreement.should be_valid        end

       specify "should be invalid if linked_to_residual_value_of_asset is not true or false" do          @finance_agreement.linked_to_residual_value_of_asset = true          @finance_agreement.should be_valid

         @finance_agreement.linked_to_residual_value_of_asset = false          @finance_agreement.should be_valid

         @finance_agreement.linked_to_residual_value_of_asset = 1          @finance_agreement.should_not be_valid        end      end    end

The first two expectations (true and false should be valid values) pass but it fails on this error:

   should be invalid if linked_to_residual_value_of_asset is not true or false    expected valid? to return false, got true

   /Users/ashleymoran/Documents/Development/YourMoney/trunk/src/spec/models/finance_agreement_spec.rb:65:

(I cut some specs out, line 65 is "@finance_agreement.should_not be_valid")

Any idea why 1 makes the model valid? The only thing I can find that makes it (correctly) invalid is nil.

Thanks Ashley

Well, I would say it’s probably because in a lot of programming languages (and in a MySQL database), a 1 counts as true and a 0, false. Ruby is strongly typed, so it normally doesn’t automatically convert things so easily, but I expect rails is configured to convert numbers to boolean because it has to accept values from databases which may not have strictly boolean objects. There’s not a lot you can do about it. You could work something into before_validation or after_validation, it’s not worth it IMO. Just re-write your tests.

Any idea why 1 makes the model valid? The only thing I can find that makes it (correctly) invalid is nil.

Hi Ashley,

ActiveRecord casts the values when you pull them out via the normal readers. So, if you have a class Flag with a boolean attribute #value:

flag.value = ‘1’ => “1” flag.value => true flag.value = ‘Wibble.’ => “Wibble.”

flag.value => false

In rails 1.2.3, a `value’ is converted to a boolean by:

%w(true t 1).include?(value.to_s.downcase)

If you want the value before it’s been cast, you can append “_before_type_cast” to the accessor name:

flag.value = ‘Wibble.’ => “Wibble.”

flag.value_before_type_cast => “Wibble.”

Not sure how useful that is to test, really, though.

Regards, George.