class Determinator::Feature
A model for an individual feature or experiment
@attr_reader [nil,Hash<String,Integer>] variants The variants for this experiment, with the name of the variant as the key and the weight as the value. Will be nil for non-experiments.
Attributes
active[R]
bucket_type[R]
fixed_determinations[R]
identifier[R]
name[R]
overrides[R]
structured_bucket[R]
target_groups[R]
variants[R]
winning_variant[R]
Public Class Methods
new(name:, identifier:, bucket_type:, target_groups:, structured_bucket: nil, fixed_determinations: [], variants: {}, overrides: {}, active: false, winning_variant: nil)
click to toggle source
# File lib/determinator/feature.rb, line 8 def initialize(name:, identifier:, bucket_type:, target_groups:, structured_bucket: nil, fixed_determinations: [], variants: {}, overrides: {}, active: false, winning_variant: nil) @name = name.to_s @identifier = identifier.to_s @variants = variants @target_groups = parse_target_groups(target_groups) @fixed_determinations = parse_fixed_determinations(fixed_determinations) @winning_variant = parse_outcome(winning_variant, allow_exclusion: false) @active = active @bucket_type = bucket_type.to_sym @structured_bucket = structured_bucket # To prevent confusion between actor id data types @overrides = overrides.each_with_object({}) do |(identifier, outcome), hash| parsed = parse_outcome(outcome, allow_exclusion: true) hash[identifier.to_s] = parsed unless parsed.nil? end end
Public Instance Methods
==(other)
click to toggle source
# File lib/determinator/feature.rb, line 63 def ==(other) Marshal.dump(self) == Marshal.dump(other) end
active?()
click to toggle source
# File lib/determinator/feature.rb, line 26 def active? !!active end
experiment?()
click to toggle source
@return [true,false] Is this feature an experiment?
# File lib/determinator/feature.rb, line 31 def experiment? variants.any? end
feature_flag?()
click to toggle source
@return [true,false] Is this feature a feature flag?
# File lib/determinator/feature.rb, line 36 def feature_flag? variants.empty? end
overridden_for?(id)
click to toggle source
Is this feature overridden for the given actor id?
@return [true,false] Whether this feature is overridden for this actor
# File lib/determinator/feature.rb, line 48 def overridden_for?(id) overrides.has_key?(id.to_s) end
override_value_for(id)
click to toggle source
# File lib/determinator/feature.rb, line 52 def override_value_for(id) overrides[id.to_s] end
parse_outcome(outcome, allow_exclusion:)
click to toggle source
Validates the given outcome for this feature.
# File lib/determinator/feature.rb, line 57 def parse_outcome(outcome, allow_exclusion:) valid_outcomes = experiment? ? variants.keys : [true] valid_outcomes << false if allow_exclusion valid_outcomes.include?(outcome) ? outcome : nil end
structured?()
click to toggle source
@return [true,false] Is this feature using structured identification?
# File lib/determinator/feature.rb, line 41 def structured? !!structured_bucket && !structured_bucket.empty? end
to_explain_params()
click to toggle source
# File lib/determinator/feature.rb, line 67 def to_explain_params { name: name, identifier: identifier, bucket_type: bucket_type } end
Private Instance Methods
parse_fixed_determination(fixed_determination)
click to toggle source
# File lib/determinator/feature.rb, line 99 def parse_fixed_determination(fixed_determination) return fixed_determination if fixed_determination.is_a? FixedDetermination variant = fixed_determination['variant'] return nil if variant && !variants.keys.include?(variant) # if a variant is present the fixed determination should always be on return nil if variant && !fixed_determination['feature_on'] constraints = fixed_determination['constraints'].to_h FixedDetermination.new( name: fixed_determination['name'], feature_on: fixed_determination['feature_on'], variant: variant, constraints: constraints ) # Invalid fixed determinations are ignored rescue nil end
parse_fixed_determinations(fixed_determinations)
click to toggle source
# File lib/determinator/feature.rb, line 95 def parse_fixed_determinations(fixed_determinations) fixed_determinations.map(&method(:parse_fixed_determination)).compact end
parse_target_group(target_group)
click to toggle source
# File lib/determinator/feature.rb, line 79 def parse_target_group(target_group) return target_group if target_group.is_a? TargetGroup constraints = target_group['constraints'].to_h TargetGroup.new( name: target_group['name'], rollout: target_group['rollout'].to_i, constraints: constraints ) # Invalid target groups are ignored rescue nil end
parse_target_groups(target_groups)
click to toggle source
# File lib/determinator/feature.rb, line 75 def parse_target_groups(target_groups) target_groups.map(&method(:parse_target_group)).compact end