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
But this technique fails when defaulting a boolean to true.
self[:allow_robots] or true
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.
!self[:allow_robots].nil? ? self[:allow_robots] : true
At this point, the code's purpose is much less obvious, and defaulting in the migration is starting to look pretty by comparison.
add_column :settings, :allow_robots, :boolean, :default => true
Any thoughts? I feel like there's probably a better way to default true that I just haven't thought of yet.
Personally when it comes to booleans I add defaults in the migration to the table itself.
As with @garethrees, I set boolean defaults in the table's migration.
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.
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.
@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
Well, setting the defaults in the migrations might be a better idea (especially if several applications are accessing the database).
@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.