Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabling Flipper for multiple IDs? #656

Closed
phstc opened this issue Aug 15, 2022 · 9 comments
Closed

Enabling Flipper for multiple IDs? #656

phstc opened this issue Aug 15, 2022 · 9 comments

Comments

@phstc
Copy link
Contributor

phstc commented Aug 15, 2022

For my use case, I need to enable Flipper for specific users or organizations.

I can add || and check for both, but that can add some complexity.

if Flipper.enabled? :search, current_user || if Flipper.enabled? :search, current_user.organization

Is there a way to simplify that?

If not, I was wondering if flipper_id could return a string (current implementation) or a string[].

def flipper_id
  [id.to_s, organization_id.to_s]
end

Then Flipper could check on both.

Any thoughts?

@jnunemaker
Copy link
Collaborator

I've considered adding Flipper.enabled?(:search, [current_user, current_user.org]) but there was a reason I didn't. Unfortunately I'm failing to remember and its driving me nuts.

I don't want to change the return value of flipper_id as that would ripple through the library. Everywhere would need to start using the first value instead of all and it would have to be clear in docs that first is used for most things but all are used for enabled?.

I think that #557 will help with this use case as then you could add organization_id as an attribute and enable based on that too. We are going to regroup on expressions/rules soon and try to get it shipped. Its mostly just the UI that is preventing a first release of it.

@phstc
Copy link
Contributor Author

phstc commented Aug 15, 2022

That makes sense! Thank you

For now, I'm considering wrapping enabled? through Feature.enabled? instead of Flipper.enabled?.

# pseudo code 

def enabled?(name, *args)
   return Flipper.enabled?(name, *args) unless args.last.is_a?(User)

   args_with_box = args.dup
   args_with_box.pop # remove user to be replaced with org
   args_with_box.push args.last.org # add org

   return Flipper.enabled?(name, *args) || Flipper.enabled?(name, *args_with_org)
end

Any thoughts?

I've considered adding Flipper.enabled?(:search, [current_user, current_user.org]) but there was a reason I didn't. Unfortunately I'm failing to remember and its driving me nuts.

That could make it easy to miss adding current_user.org in some places. Enforcing that organization would always be an option for my specific case would work best.

@jnunemaker
Copy link
Collaborator

I'd probably just do:

def enabled?(name, actors)
  actors.any? { |actor| Flipper.enabled?(name, actor) }
end

Or if you want to force always checking the user's org too:

# * to always get array
def enabled?(name, *actors)
  # flatten so passing array or single works
  actors = actors.flatten
  # get the user actors
  user_actors = actors.select { |actor| actor.is_a?(User) }
  # make sure the orgs are added automatically
  user_actors.each { |user_actor| actors << user_actor.org unless actors.include?(user_actor.org) }
  # check them all now
  actors.any? { |actor| Flipper.enabled?(name, actor) }
end

@jnunemaker
Copy link
Collaborator

Closing to keep tidy but still very happy to respond.

@phstc
Copy link
Contributor Author

phstc commented Aug 16, 2022

That's much simpler, thank you! I was copying the signature from here https://github.com/jnunemaker/flipper/blob/3dbd19323b50248eb090206b102dce4909d85223/lib/flipper/dsl.rb#L35

I wasn't sure what *args was about, but in our case, the last arg is always the actor.

@chernenkov-ayu-sbmt
Copy link

chernenkov-ayu-sbmt commented May 14, 2024

Warning! If you use code like the one above (if Flipper.enabled?(:x, actor1) || Flipper.enabled?(:x, actor2)), it will break a percentage configuration of the feature :x. E.g. if :x is enabled for 50% of the time, then checking it with the above code will actually result in 75% of if-block executions (it is like tossing the coin twice).

@chernenkov-ayu-sbmt
Copy link

it will break a percentage configuration of the feature

@jnunemaker With that said, I believe that multi-actor feature checking must be implemented by the Flipper gem itself to avoid unintended behaviour of calling Flipper.enabled? multiple times by a library user.

@bkeepers
Copy link
Collaborator

@chernenkov-ayu-sbmt You can pass multiple actor IDs to enabled? now (cc #710)

Flipper.enabled?(:x, [actor1, actor2])

See https://www.flippercloud.io/docs/features/actors

@chernenkov-ayu-sbmt
Copy link

@bkeepers Great! Thank you very much for letting me know about it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants