when is a boolean not a boolean?

Weird problem.. I'm new to rails and ruby... maybe someone can explain
what I am not getting..

Env: Mac OS X 10.5.3, Rails. 2.0.2, ruby 1.8.6 (2007-09-24 patchlevel
111)

A User class created using the restful_authentication plugin

A Company class (has lots of fields not really important to the
problem below)

Users can have many companies, entered into the User.rb model as one
would expect
      has_many: :companies

In the User.rb model I've also added:

def has_companies?
    !companies.empty?
  end

..and..

def company_count
       companies.size
     end

so I can easily find out if they actually have any companies and how
many companies they have. Pretty straight-forward, right?

I create users, every thing looks fine; I ask the user if it has any
companies, if returns "false" as in:

u1 = User.find(1)

=> #<User id: 1, login: "admin", email: "info@yourapplication.com",
crypted_password: "85795571cc9fd37cb7c37827f8cf6b3abd26c4e7", salt:
    :
    :

u1.has_companies?

=> false

In my view, if the user has previously entered company info, I want to
give them a summary, if they have no companies they are offered a
link to create one. very simplistic:

<% if @user.has_companies? %>
    this user has <%= @user.company_count %> companies (has_companies?
is <%= @user.has_companies? %>) .... <br>
<% else %>
<%= link_to "Please enter some basic info about your company", "/
companies/new" %>
<% end %>

Oddly, when this view is executed, the following is displayed:

     this user has 0 companies (has_companies? is false) ....

It's as if the <% if.. clause doesn't know how to handle the
evaluation of a boolean.

If I change the test to be <% if @user.has_companies? == false %> it
works as expected.

wtf? Why would ruby not be able to grok a boolean test? What am I
missing Any suggestions??

_DHMS

Step through it in the debugger to see if it's really executing what
you thing it is?

Fred

The issue might be nil objects that are never true nor false. ...

Have a look at this article that I found interesting:

http://toolmantim.com/article/2007/3/26/bangbang_your_nil_is_dead

For the purposes of a condition, nil is false. (but of course nil ==
false is false, but if you're sane you'll never be explicitly be
testing for == false or == true).

Fred

Actually nil is always logically false.

http://www.therailsway.com/2007/8/1/dangers-of-cargo-culting

Actually it's a little more direct than that. In Rails 2.0.2, testing
a has_many relationship will return an empty array if, in fact, there
are no elements connected to the source record.

My "has_companies?" method is this:

  def has_companies?
    !companies.empty?
  end

what it returns <b>is a boolean</b>. In fact, if you look at my
original post, I AM getting back "false" but the <% if... %> test in
the erb in the view code isn't treating it as a boolean. Any ideas?

<what it returns <b>is a boolean</b>. In fact, if you look at my...

I copied this from http://en.wikipedia.org/wiki/Boolean_datatype

begin Quote
The Ruby programming language does not have a Boolean data type as
part of the language. Like many other interpreted languages, all
variables are dynamically typed. Instead, ruby defines the explicit
values of false and nil, and everything else is considered true,
including 0, [ ], and the empty string "". The values true, false, and
nil can be assigned to variables, returned from functions or methods,
and compared in Boolean expressions.

a = 0
if (a)
  print "true"
else
  print "false"
end

will print "true", which might come as a surprise to a new user of the
language.

End Quote

I think you problem stems from applying a logical "NOT" operator to
something that is not what you expect.
Does !companies get evaluated before or after !companies.empty? !
companies could be returning true before !companies.empty? gets
evaluated.

Just a guess, You have to step through the code.

well you know it returns false the second time, but that's not quite the same thing. Anyway, i'll reiterate my suggestion to step through it in the debugger and work out exactly what is happening.

Fred