Defaulting boolean attributes to true #43

Open
garyv opened this Issue Sep 27, 2012 · 6 comments

Projects

None yet

4 participants

@garyv
garyv commented Sep 27, 2012

I was wondering what the best way is to make an Active Record attribute default to true.

This guide recommends setting defaults in the model, not the migration
https://github.com/bbatsov/rails-style-guide#migrations

But this technique fails when defaulting a boolean to true.

def allow_robots
  self[:allow_robots] or true
end

In the code above, allow_robots will always evaluate to true, even if set to false in Active Record. At the very least, there should be a short disclaimer in the guide about the technique not working in this case. But I'd prefer to arrive at a recommended solution.

This variation of the method will get the desired result.

def allow_robots
  !self[:allow_robots].nil? ? self[:allow_robots] : true 
end

At this point, the code's purpose is much less obvious, and defaulting in the migration is starting to look pretty by comparison.

def change
  add_column :settings, :allow_robots, :boolean, :default => true
end

Any thoughts? I feel like there's probably a better way to default true that I just haven't thought of yet.

@garethrees

Personally when it comes to booleans I add defaults in the migration to the table itself.

@slamotte

As with @garethrees, I set boolean defaults in the table's migration.

@garyv
garyv commented Oct 16, 2012

To play devil's advocate for a moment, I just read a blog post suggesting that anytime you store a Boolean in a database, it's a code smell, and you should use a State Machine pattern instead, because it it's easier to maintain or something.

http://railstips.org/blog/archives/2012/10/10/booleans-are-baaaaaaaaaad/

Personally, I've never found State Machines to be intuitive, and I didn't find this argument very convincing. A Boolean state is a much simpler and easier concept to work with. But it's an interesting idea, and it would sidestep the need to set defaults in the database.

@slamotte

@garyv thanks for that link. I get what you were trying to add. Personally I hated the article's title (too absolute and polarizing) as well as his example (too contrived, and as you would read in the comments, his problem was really due to a poor design and naming) but regardless, it's an alternative.

I see nothing wrong with using booleans in a table but that's probably because I've been coding long enough to inherently recognize when to use them versus something else. See http://goo.gl/SD8J7

@bbatsov
Owner
bbatsov commented Oct 17, 2012

Well, setting the defaults in the migrations might be a better idea (especially if several applications are accessing the database).

@slamotte

@bbatsov I know it's not "The Rails Way" but I'm a big fan of putting such things as defaults, unique indexes, and declarative referential integrity constraints into databases. If there's the slightest possibility that another app might ever touch the database then I consider this imperative. I've had many heated debates about how this isn't portable or designed right but in my professional opinion you've got to protect your data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment