zendesk / arturo

Feature Sliders for Rails
http://github.com/zendesk/arturo
Other
206 stars 24 forks source link

Can I deploy some features on a per-user basis and others on a per-account basis? #8

Open jamesarosen opened 13 years ago

jamesarosen commented 13 years ago

This question from martinstreicher:

Can the feature_recipient be dynamic? I have an account and a network that might have different features -- which would be the recipient?

That's an interesting point use case that I hadn't considered. The problem is that #feature_recipient can't know which to return since it doesn't know which feature you're asking about. One option would be to change #if_feature_enabled(feature_name, &block) and #feature_enabled?(feature_name) to allow a second, optional argument that takes the place of the result of #feature_recipient. Specifically:

def if_feature_enabled(feature_name, recipient = nil, &block)
  recipient ||= self.feature_recipient
  ...
end

def feature_enabled?(feature_name, recipient = nil)
  recipient ||= self.feature_recipient
  ...
end
jamesarosen commented 13 years ago

Another idea would be to add an Arturo::FeatureRecipient mixin:

module Arturo
  module FeatureRecipient
    def feature_enabled?(feature_name)
      Arturo::Feature.to_feature(feature_name).enabled_for?(self)
    end
  end
end

Then you could mix that into Network and User and use them like so:

current_user.feature_enabled?(:feature_that_is_deployed_to_users)

current_user.network.feature_enabled?(:feature_that_is_deployed_to_networks)
plukevdh commented 12 years ago

Possible solution is just to make #enabled_for? overridable. See

https://github.com/crunchy/arturo/blob/master/test/dummy_app/test/unit/features_override_test.rb

jamesarosen commented 12 years ago

At Zendesk, we've been using a modified version of Arturo, but I've been having trouble figuring out how to make it generally applicable. Our features have a state attribute in addition to the deployment_percentage. state can be any of the following:

You seem to be going after something similar, though you may not need all those features.

plukevdh commented 12 years ago

Is that what issue #16 is talking about?

jamesarosen commented 12 years ago

Yes.

plukevdh commented 12 years ago

I think the whitelist/blacklist concept handles a lot of these kinds of cases, or it could be used to do so. Maybe some sort of DSL for defining states -> what group is can access a feature per a boolean method. Something like

Arturo::RolloutScheme do |f|
  f.off = false
  f.beta = :in_beta_group?
  f.rollout = :passes_threshold?  
  f.on = true
end

Then then some sort eval checks the feature state, evals the given method (or just takes the bool) for the enabled state. this way it can be flexibly defined in an initializer or something.

jamesarosen commented 11 years ago

@plukevdh I like the DSL idea. What about making it a little more like FactoryGirl's DSL, which I like?

Arturo::Feature.phased_rollout do
  off     { false }
  beta    { |recipient| in_beta_group?(recipient) }
  rollout { |recipient| passes_threshold?(recipient) }
  on      { true }
end
jamesarosen commented 11 years ago

@plukevdh what have you done to solve this in your projects? I'm still not totally happy with anything we've got so far.

plukevdh commented 11 years ago

Dude, you gotta not respond to ALL THE THINGS on one day. Spread the love around :)

Are we talking about dsls? I've got some good ones, but let me find a simple example somewhere. I'll get back on this. Shortly.

jamesarosen commented 11 years ago

I finished my sprint early, so I'm using the time to clean out old open source issues. It's a great feeling :)

Can you use the new global whitelists to solve this problem? Something like

Arturo.Feature.whitelist do |feature, _|
  feature.enabled_for?(0)
end

(And forget the phase DSL, at least for now. I'm happy to talk about it later, but I don't want to cloud the problem you're having here.)

plukevdh commented 11 years ago

Yeah maybe. I still like the idea of the DSL. Your factorygirl-like example is cool too.

https://gist.github.com/plukevdh/5499688 is a DSL I wrote for setting abilities on a user for state machine control. Pretty simple and I think something similar could be done for this.

psulightning commented 10 years ago

Has there been any movement on this issue? This engine might be something that I want to use.

We have a situation where we may want multiple rules for a feature where they can be per company and per multiple groups and per operating area and per platform (like ios, web, etc.)

jamesarosen commented 10 years ago

No movement. I think the whitelist feature will suffice for most use-cases. If anyone comes up with a particularly elegant API / design, I'm all for considering an enhancement.

psulightning commented 10 years ago

Sure whitelisting would work if I wanted to hardcode (at least that's my interpretation from the readme). But, our configuration could be changing on the fly, so modifying the initializer every time is not feasible. Please let me know if my interpretation is mistaken.

jamesarosen commented 10 years ago

Let's assume that you enhance the features table and Feature model to understand whether it's an Account-based or User-based feature.

Let's further assume that you declare your (default) feature_recipient to be the current user, and the user has a reference to the account.

Then to get account-based rollout for those features that need it, you could do

Arturo::Feature.whitelist do |feature, user|
  if feature.is_account_feature?
    feature.enabled_for?(user.account)
  end
end