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

Add #flipper_enabled? to ActiveRecord models #755

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions lib/flipper/model/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ module ActiveRecord
def flipper_properties
{"type" => self.class.name}.merge(attributes)
end

# Check if a feature is enabled for this record or any associated actors
# returned by `#flipper_actors`
def flipper_enabled?(feature_name)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One interesting thing with this, you could have user and org. In user you override flipper_actors but in org you can't because you don't know the specific user. I think that is part of my concern with adding flipper_actors and this method name (even though it is now scoped).

I want the convenience but also don't want it to be too sharp for users.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One interesting thing with this, you could have user and org. In user you override flipper_actors but in org you can't because you don't know the specific user.

I'm not sure I understand. If you have access to a user, you would check against that instead of the organization.

current_user.flipper_enabled?(:thing)

If not, then you check against just the organization:

current_org.flipper_enabled?(:thing)

Either way, enabling the feature for the organization would make both checks pass:

Flipper.enable(:thing, current_org)

Every feature check would benefit from the user knowing it's related actors.

I want the convenience but also don't want it to be too sharp for users.

By default the behavior doesn't change. It's only if you explicitly overwrite #flipper_actors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the feature is enable for 1 of the users organizations, then wouldn't they see it enabled on all of their organizations? That doesn't seem correct.

Flipper.enabled?(feature_name, *flipper_actors)
end

# Returns the set of actors associated with this record. Override to
# return any other records that should be considered actors.
#
# class User < ApplicationRecord
# # …
# def flipper_actors
# [self, company]
# end
# end
def flipper_actors
[self]
end
end
end
end
29 changes: 29 additions & 0 deletions spec/flipper/model/active_record_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,33 @@ class User < ActiveRecord::Base
})
end
end

describe "flipper_enabled?" do
subject { User.create!(name: "Test") }

it "delegates to Flipper.enabled?" do
expect(subject.flipper_enabled?(:stats)).to be(false)
Flipper.enable :stats, subject
expect(subject.flipper_enabled?(:stats)).to be(true)
end

it "returns true if feature is enabled for associated actor" do
friend = User.create!(name: "Friend")

# Add a flipper_actors method to this instanc
subject.extend Module.new {
attr_accessor :friends

def flipper_actors
[self] + Array(friends)
end
}

subject.friends = [friend]

expect(subject.flipper_enabled?(:stats)).to be(false)
Flipper.enable :stats, friend
expect(subject.flipper_enabled?(:stats)).to be(true)
end
end
end