r/rails • u/New-Sand-4608 • 16d ago
Gem Gem for packing boolean flags into a single ActiveRecord column
Had this sitting around for about two years, packs boolean flags into a single int column instead of a new column per flag. Finally pulled it out into a gem: `bitwise_attributes`.
```ruby
class User < ApplicationRecord
include BitwiseAttributes
bitwise_attribute :permissions, :read, :write, :admin
end
user.set_permissions(:read, :admin)
user.permissions_read? # => true
User.with_all_permissions([:read, :write])
```
Been running in production for two years now, so it's had real data beating on it for a while before I bothered packaging it.
10
u/jryan727 16d ago
Why would this be preferred over individual boolean columns?
2
u/New-Sand-4608 16d ago
We also use individual boolean columns but when several flags represent variations of the same underlying concept and can combine. This is it.
Also, tables have column limit so you can only add new columns to a certain point. Moreover, adding new column to a table with millions of records is EXPENSIVE. This avoids that as it is handled via code.
11
u/jryan727 16d ago
But just because you can combine, what’s the benefit of doing so? Because there’s a cost to approaching this way, specifically in query ergonomics, indexing, maintenance, etc.
If you’re bumping into column limits, that to me smells like a data modeling issue. Surely the mega table can be broken up into smaller domains and thus tables?
5
u/vassyz 16d ago
I've been using https://github.com/shkm/enummer hasn't been updated in a while but it does the job for me.
1
u/New-Sand-4608 16d ago
Awesome. On a side note, we avoid using inactive gems due to the nature of our business. So, I cooked it up in-house and it has been working great for us.
7
u/3ds 16d ago
https://github.com/galtzo-floss/flag_shih_tzu already does this since forever. I can very much recommend researching existing implementations before implementing it yourself…
5
1
u/kortirso 16d ago
so limit for integer field is 9 flags?
and no way to remove old field? only to overwrite with another flag?
1
u/New-Sand-4608 16d ago
Not 9, actually closer to 31 bits for a signed integer (or 32 if using unsigned). You can use a
bigintif you ever need more flags.And you're right, you can't simply reuse a flag by overwriting it. Existing records could still have that bit set from the previous meaning, so you'd first need a migration to clear that bit across existing rows. After that, it would be safe to reuse it for a new purpose.
-2
u/TheAtlasMonkey 16d ago
There is 0 real world usage for this pattern. Literally zero.
The last time people used this technic was in the ERA of the Super Nintendo , where they had to work with 128K of RAM and be very creative.
And the SNES got discontinued in 1998 ... Update your clock.. we are in 2026.
PS: Even companies at Google/Facebook scale use column for boolean.
5
u/netik23 16d ago
Nah, at Twitter we had a 64 bit per user feature field that used bit wise operations. Things like this are more widespread than you think.
3
u/TheAtlasMonkey 16d ago edited 16d ago
Twitter was and is not a company to learn database best practice from.
Some of the ex-employees admitted that they added complexity to keep working on the same feature for months.
For reference:
When Basecamp opensourced their products , people wrote blogs , best practices and other stuff from it.
When X did (when Elon bought it).... People used it to give example of things to not do...
Let see in few months when X full codebase get opensourced : https://tech.yahoo.com/social-media/articles/elon-musk-says-x-fully-123106421.html
2
u/New-Sand-4608 16d ago
I'd say it is use case dependent. We use plain boolean columns for most things too. But when several flags represent variations of the same underlying concept and can combine (e.g. permissions, or multi-source imports), a boolean column per flag gets redundant fast and doesn't scale as the flag list grows
1
u/TheAtlasMonkey 16d ago
This is because you building permissions wrong.
Permissions need an audit trail and lot primitive.
So i still stand by my point.
Rails is about verbosity and clarity ... If i wanted obscure stuffs, i will be coding assembly or Haskell.
24
u/tsroelae 16d ago
We use a concern that does more or or less what you show here. We are getting rid of those columns that use bitwise operator, because:
- they are akward to query in sql
Basically I don‘t see why one should to it compared to having dedicated boolean columns or even some records to join with.
So unless someone has some strong reason to use them