1

I'm facing issues when I'm trying to check for boolean values in Rails. Earlier my condition used to check against a boolean value against 1 or 0 and this worked. But recently, this doesn't work any more.

When I check them at MySQL level, the booleans are stored as tinyint(1) with values 1 and 0. But when I print those values in the rails development.log, they come up as true and false respectively.

Earlier comparison logic
is_admin == 1

When I check for true and false now instead of 1 and 0(because of the recent issue) things work well. I'm not sure why this didn't fail for me earlier.

Current comparison logic
is_admin == true

I'm also not 100% confident that a comparison of a boolean column should be done against true or false always in the context of Rails or it should be against 1 and 0.

One thing I did realize in the process is, the earlier comparison was between say 1 (an integer) and true (the actual boolean) is evaluating to false. This I can now understand, but I'm still not able to get over how did this logic seem to work for me earlier.

I'd be interested to hear the best practice to do these kind of checks in Rails.

halfer
  • 19,824
  • 17
  • 99
  • 186
boddhisattva
  • 6,908
  • 11
  • 48
  • 72

3 Answers3

1

Different databases store booleans in different ways. Mysql stores them as 0 or 1. These are translated into false and true by rails. Generally you you treat them as booleans in your ruby code.

This code

if is_admin == true

is redundant. you might as well just say

if is_admin

since the result will be the same either way.

Max Williams
  • 32,435
  • 31
  • 130
  • 197
  • Thanks for your answer, I get your point. So you're saying if I I want to check for if `is_admin == true` I can simply use `if is_admin` and if I want to check for false, I can use if `!is_admin`, right ? – boddhisattva May 17 '14 at 05:43
  • Yep. You can also do "unless is_admin" instead of "if !is_admin" which can be more readable – Max Williams May 17 '14 at 08:05
  • BTW, in Ruby, anything can be put into an "if" test, and will evaluate as either "truthy" (passing the test) or "falsey" (failing the test). The only objects that are "falsey" are `nil` and `false`. Everything else, including empty strings, empty arrays, the number 0 etc, is considered "truthy". Also, an undefined local variable (`foo` - note the lack of @) will cause an exception if it is referenced, but an undefined instance variable (`@foo`) will be treated as nil. This means you can do "if @foo" and this will fail if @foo is falsey OR if it hasn't been defined. – Max Williams May 19 '14 at 08:56
  • I didn't yet get a solution to the problem I'm facing(may be I need to dig deeper which I'm unable to do to that extent at the moment, but your answer definitely answers the question as per the title, thus accepting it. Valid point on redundancy. – boddhisattva May 28 '14 at 17:55
0

As @Max Williams stated,the different databases store boolean values in different ways.

MySQL store them as 0 or 1.So calling is_admin == true will return true and calling is_admin == false will return false.

And when it comes to PostgreSQL,it has many ways

For true,the valid values are

TRUE,'t','true','y','yes'and '1'

For false,the valid values are

FALSE,'f','false','n','no' and '0'

Note: I just gave a comparison of how Boolean values are stored in MySQL and PostgreSQL,so that it clears your confusion.And i hope it surely helps you.

Pavan
  • 33,316
  • 7
  • 50
  • 76
  • The problem is that when I used the comparison with `is_admin == 1` , it passed earlier but it doesn't pass any more. That's when I replaced that with `is_admin == true`. But it working earlier and not working now confuses me, hence the question on what is the safest way of doing it right. – boddhisattva May 17 '14 at 05:40
  • @boddhisattva Seems Weird! I don't know what caused it.But i suggest you to go with `is_admin == true` because it looks like a reasonable call on boolean values. – Pavan May 17 '14 at 05:43
  • One reason, why I think that could be the case(as already mentioned in the question) is.. when I checked the log.. i think it was trying to compare a boolean(i.e., a true or false) against an integer(1) in this case.. So it would evaluate `if true == 1` to false... – boddhisattva May 17 '14 at 05:45
  • @boddhisattva Hmm, might it had confused with the integer value for Boolean datatype. – Pavan May 17 '14 at 05:47
  • Possible, but I really can't understand why it worked earlier. It should have failed even back then. – boddhisattva May 17 '14 at 05:55
  • @boddhisattva Have you used that with any of the operators to compare? – Pavan May 17 '14 at 05:57
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/53866/discussion-between-boddhisattva-and-pavan) – boddhisattva May 17 '14 at 06:02
  • `is_admin == 1` will not pass: it's stored as 1 in the database, but in ruby it has been translated into `true`, and true does not equal 1. I suggest you use my suggestion earlier and not test `is_admin` against any value: it's already a boolean (or perhaps nil) so just test it directly like `if is_admin` – Max Williams May 29 '14 at 08:52
  • @boddhisattva If we compare is_admin with 1, 'true', 0 etc, its just a ruby comparison and gives result as false. But in Rails if you are using postgres and assign the is_admin value to '1', '0', 'true' etc, then rails postgres adapter comes into action and changes these values to corresponding true or false. – Abhi Nov 16 '15 at 07:01
0

If you are using Mysql, the trick is to add a question mark (?):

is_admin => 0 
is_admin? => false
Sidonai
  • 3,088
  • 3
  • 13
  • 12