pboling / flag_shih_tzu

Bit fields for ActiveRecord
http://railsbling.com/flag_shih_tzu
MIT License
496 stars 64 forks source link

Scope SQL extremely clumsy for large number of flags; suggest using bitwise operators #53

Closed henrebotha closed 8 years ago

henrebotha commented 8 years ago

The way the generated scopes currently work is by generating an array of all possible values of flags where the desired flag is set, and then checking array membership in SQL. For example:

has_flags 1 => :foo,
          2 => :bar,
          3 => :baz

User.bar
#=> SELECT "users".* FROM "users" WHERE users.flags in (2, 3, 6, 7)

Here 2, 3, 6, 7 are all the possible values for flags in which bar is set.

This is fine for a small number of flags. However, my application currently uses 19 (!) flags on a single model. You don't want to see the query it generates... (It's long enough to overflow my terminal buffer.)

I wonder whether it wouldn't be faster to use bitwise operators in the generated SQL. Something like this:

User.bar
#=> SELECT "users".* FROM "users" WHERE users.flags & 2 = 2

Not only is this a hell of a lot more readable, it stays true to the spirit of the gem (after all, "Bitwise Operations are fast!"), and it uses a syntax which does not grow in length or complexity as the number of flags on the model increases.

henrebotha commented 8 years ago

Please disregard, I'm retarded.

pboling commented 8 years ago

For the sake of future search landers: using bitwise SQL operators is fully supported by the gem as an option, but it does render DB indexes unusable by the query, so there is a tradeoff.

If you want bitwise action:

has_flags 1 => :warpdrive,
          2 => :shields,
          :flag_query_mode => :bit_operator
henrebotha commented 8 years ago

Yup, I totally missed that option in the docs. And I can confirm it is super dang fast even with many flags.

pboling commented 8 years ago

The docs need help 🎱