Stepan Parunashvili
Stepan Parunashvili

Reputation: 2845

Rails where clause returns nil when asking for all records with boolean set to false

I have a User model which has the boolean attribute :sourced

I wanted to write the code below, but I get returned an empty array

User.where(sourced: false)
#   User Load (2.0ms)  SELECT "users".* FROM "users" WHERE "users"."sourced" = 'f' ORDER BY  users.id DESC
# => [] 

However, this isn't the case, because there actually are records that have sourced set to false.

i.e, when I run

  User.first.sourced #=> false 

In my schema.rb file, it shows that the default value for the 'sourced' column is false

  create_table "users", force: true do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "password_digest"
    t.string   "remember_token"
    t.boolean  "admin",                              default: false
    t.string   "password_reset_token"
    t.datetime "password_reset_sent_at"
    t.text     "admin_note",             limit: 800
    t.integer  "applications_count"
    t.string   "admin_link"
    t.boolean  "sourced",                            default: false
    t.boolean  "told_admin"
  end

What's going on here?

Upvotes: 0

Views: 586

Answers (1)

engineerDave
engineerDave

Reputation: 3935

This is caused because you don't have a default value of false set in your migration, so it is saving it as nil which you aren't looking for. With duck typing nil == false so on the ruby level its false.

While you could do a query for false and nil... this is a bit cumbersome. Just set a default value in your database.

you can fix this with a migration

def up
  #change column
  change_column :users, :sourced, :boolean, default: false


  # reload schema https://stackoverflow.com/a/8935621/793330
  User.reset_column_information

  # update the nils 
  User.find_each(&:save) 
end 

Always remember to set a default value for boolean values in your database. This will save you a ton of frustration in the future and also helps with validations by always setting a default value on the database level.

Also if you're using SQLite? perhaps its not typecasting properly does this work?

User.where(sourced: 0) 

Upvotes: 1

Related Questions