The Active Model Flags Gem lets you attach the has_flags
trait to your User, Account, or any other rails active models.
For some applications you don't want to add a million different attributes in your database for flags that are potentially one-time events. For example, if you wanted to track whether a user has been notified of something, or has been sent an email. These arbitrary flag columns start to clutter your DB.
The Active Model Flags gem solves this issue by allowing you to arbitrarily set and get flags from a serialized column.
Table of Contents
Add this line to your application's Gemfile:
gem 'activemodel_flags'
And then execute: $ bundle Or install it yourself as: $ gem install activemodel_flags
Choose the model you want to have flags and add the has_flags
function to it. For example, with a User model this may look like this:
class User < ActiveRecord::Base
# ...
has_flags
# ...
end
Then, you'll need to install the column in your database. This gem comes with this generator for you that you can use like this:
rails g activemodel_flags:column User
rake db:migrate
Replace User
with your own model class.
Once a model has_flags then you can now set a flag like this:
user = User.create
user.has! :been_sent_email_about_usage
user.has? :been_sent_email_about_usage
# false
or you can do the opposite:
user = User.create
user.hasnt! :been_sent_email_about_usage
user.has? :been_sent_email_about_usage
# true
To set the value without saving to the DB use user.has :been_sent_email_about_usage
.
Consider this example to see how the getters work:
user = User.create
user.has! :been_sent_email_about_usage
user.has? :been_sent_email_about_usage
# true
user.hasnt? :been_sent_email_about_usage
# false
user.has? :been_eating_a_big_chocolate_cake
# false
Generally this gem is not made for mass querying, so if you plan on doing joins based on the flag attribute then this gem is probably to for you and you should use a boolean column.
That being said, here's how you can use the
User.that_havent?(:been_sent_email_about_usage) do |user|
# * send that user the email about usage here. *
user.has! :been_sent_email_about_usage
end
# Returns query list of all users that have been sent a message
If you want to now what flags are being used for debugging purposes then you can use
u = User.flags_used
# returns something like ["been_sent_email_about_usage", "been_eating_a_big_chocolate_cake"]
User.where("age > ?", 40).all_have! :seen_james_bond_movies
# Sets the seen_james_bond_movies flag to true for all matched users.
And to do the opposite (set the flag to false for all matched users):
User.that_have?(:used_a_cd).where("age < ", 20).all_have_not! :felt_the_anger_of_skipping_cds
# Sets the felt_the_anger_of_skipping_cds flag to false for all matched users
User.where(took_the_red_pill: true).reset_flags! :been_in_the_matrix
# Now all users that were matched will return false for has?(:been_in_the_matrix)
User.reset_all_flags!
Models that have the has_flags trait will call the protected method on_flag_change(old_val, new_val)
any time the value of their flag changes, but only if it is done individually.
Feel free to fork and contribute so we can make this better!
- Build in method_missing functionality so you can do things like
model.has_eaten_a_pie!
andmodel.has_eaten_a_pie?
- Make the flags column customizable so you can add multiple flag columns
Bug reports and pull requests are welcome on GitHub at https://github.com/jayelkaake/user_timezone. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.