We are exploring using the flipper gem (https://github.com/jnunemaker/flipper) to gate who sees new features. In one of our first tests, we want to show a specific feature to only the first X users that see a banner promoting it.
We looked at using a percentage, but the business is very specific on the number, and also wants to reach that number right away, then disable the feature for all other users, without disabling it for those that saw it first. Using a percentage, we weren't able to see a way to ensure the correct number would see it, and that everyone of the first x would see it.
Inside the gates/actor.rb, there is this:
enabled_actor_ids = value
which implies we could get the list of enabled ids, and perform a count on that, but we couldn't find whether or where that list may be exposed.
Since we are using the AR adapter as a trial, we instead created a scope on an actor object that joins to the flipper_gates table, but this feels extremely fragile and getting very much into the inner workings of the gem.
Any advice is greatly appreciated.
You should be able to accomplish this by programmatically turning the feature on for Individual Actors until an upper limit is reached.
IMPORTANT NOTE: according to the documentation:
The individual actor gate is typically not designed for hundreds or thousands of actors to be enabled. This is an explicit choice to make it easier to batch load data from the adapters instead of performing individual checks for actors over and over. If you need to enable something for more than 20 individual people, I would recommend using a group.
Now that we've agreed that we want to move forward with this anyways.. Let's talk about implementation.
The first thing you need to do is to ensure that the actor (probably a User) responds to flipper_id
and that the flipper_id
is unique for every actor. Once that is set up, you should be able to simply do enable the feature for a user when they see the banner like this:
flipper[:stats].enable_actor user
Now, in order to determine if we should enable the feature for a user, we need to determine how many users have been enrolled in the feature.
To do this we can query the Gate directly:
Flipper::Adapters::ActiveRecord::Gate.where(
feature_key: "stats",
key: "actors"
).count
This will return a count of the number of actors enrolled in a feature.
Well, let's take a look at the gem.
flipper[:stats].enable_actor
actually calls Feature#enable_actor
with the user
we passed in earlier (that responds to flipper_id
) being passed in as the actor.
Next, Feature#enable_actor
passes the actor into Types::Actor.wrap
which creates a new instance of Types::Actor which checks to make sure the actor isn't nil and that it has a flipper_id and then sets two instance variables, thing
which is set to the actor, and value
which is set to the flipper_id
of the actor.
Now that we have an instance of Types::Actor
, we pass it into Feature#enable
which looks up the gate
which in our case would be a Gates::Actor
instance. Finally we call enable on the adaptor (which in your case is ActiveRecord).
In Adapters::ActiveRecord.enable
we first look at gate.data_type
which in our case, is :set
. From there we do:
@gate_class.create! do |g|
g.feature_key = feature.key
g.key = gate.key
g.value = thing.value.to_s
end
Where, as mentioned earlier, thing.value
is the flipper_id
. Bingo! @gate_class
is the active record class responsible for the gates table and the default table name is "flipper_gates".
Now we know exactly what to query to get a count of the actors enrolled in the feature!
number_of_actors_enrolled_in_stats_feature = Flipper::Adapters::ActiveRecord::Gate.where(
feature_key: "stats",
key: "actors"
).count