Class: FeatureFlag

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Attributes, ActiveModel::Model
Defined in:
app/models/feature_flag.rb

Overview

Presents a Flipper feature for the admin UI. Wrapping Flipper::Feature in an ActiveModel-compatible object lets it flow through Koi's table, form, and routing helpers.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(feature: nil) ⇒ FeatureFlag

Returns a new instance of FeatureFlag.

Parameters:

  • feature (Flipper::Feature) (defaults to: nil)


35
36
37
38
39
40
41
42
43
44
# File 'app/models/feature_flag.rb', line 35

def initialize(feature: nil, **)
  super(**)

  if feature
    self.key = feature.key
    @feature = feature
  else
    @feature = Flipper.feature(key.to_s)
  end
end

Instance Attribute Details

#featureFlipper::Feature (readonly)

Returns:

  • (Flipper::Feature)


30
31
32
# File 'app/models/feature_flag.rb', line 30

def feature
  @feature
end

Class Method Details

.allObject



10
11
12
# File 'app/models/feature_flag.rb', line 10

def self.all
  Flipper.features.sort_by(&:key).map { |feature| new(feature:) }
end

.build(key: nil) ⇒ Object



20
21
22
# File 'app/models/feature_flag.rb', line 20

def self.build(key: nil)
  new(key:)
end

.find(key) ⇒ Object

Raises:

  • (ActiveRecord::RecordNotFound)


14
15
16
17
18
# File 'app/models/feature_flag.rb', line 14

def self.find(key)
  raise ActiveRecord::RecordNotFound, "Couldn't find feature #{key.inspect}" unless Flipper.exist?(key)

  new(key:)
end

Instance Method Details

#actorsObject

Enabled actors as a newline-separated list of flipper ids, for editing.



89
90
91
# File 'app/models/feature_flag.rb', line 89

def actors
  actors_value.to_a.join("\n")
end

#destroyObject

Remove the feature from Flipper entirely.



71
72
73
# File 'app/models/feature_flag.rb', line 71

def destroy
  Flipper.remove(key)
end

#groupsObject

Enabled groups as names, for display and form pre-fill.



76
77
78
# File 'app/models/feature_flag.rb', line 76

def groups
  groups_value.to_a
end

#percentage_of_actorsObject



80
81
82
# File 'app/models/feature_flag.rb', line 80

def percentage_of_actors
  percentage_of_actors_value
end

#percentage_of_timeObject



84
85
86
# File 'app/models/feature_flag.rb', line 84

def percentage_of_time
  percentage_of_time_value
end

#persisted?Boolean

A wrapped feature is backed by a registered Flipper feature, so it counts as persisted. Lets Koi helpers (e.g. link_to_delete) treat it like a record.

Returns:

  • (Boolean)


95
96
97
# File 'app/models/feature_flag.rb', line 95

def persisted?
  key.present? && Flipper.exist?(key)
end

#saveObject

Validate and register the feature. Returns false (leaving errors populated) when invalid. Adding is idempotent, so re-saving an existing key is a no-op.



48
49
50
51
52
53
# File 'app/models/feature_flag.rb', line 48

def save # rubocop:disable Naming/PredicateMethod
  return false unless valid?

  Flipper.add(key)
  true
end

#to_paramObject



99
100
101
# File 'app/models/feature_flag.rb', line 99

def to_param
  key
end

#to_sObject



103
104
105
# File 'app/models/feature_flag.rb', line 103

def to_s
  key
end

#update(attributes) ⇒ Object

Apply the desired availability from the form: fully on, fully off, or a set of conditional rules. Clear the gates before applying rules so a previously set boolean gate can't mask them — Flipper reads a feature as fully on whenever its boolean gate is set, and there's no way to disable only that gate.



60
61
62
63
64
65
66
67
68
# File 'app/models/feature_flag.rb', line 60

def update(attributes) # rubocop:disable Naming/PredicateMethod
  case attributes[:state]
  when "on"  then enable
  when "off" then disable
  else            configure(attributes)
  end

  true
end