Class: EightBall::Conditions::Percentage

Inherits:
Base
  • Object
show all
Defined in:
lib/eight_ball/conditions/percentage.rb

Overview

The Percentage Condition is satisfied for a deterministic, sticky subset of values sized to percentage percent. Bucketing is salted by the owning flag's name (injected by Feature), so a value buckets independently per flag. See the README for the bucket algorithm.

Instance Attribute Summary collapse

Attributes inherited from Base

#parameter

Instance Method Summary collapse

Methods inherited from Base

#==, #hash, #to_wire

Constructor Details

#initialize(options = {}) ⇒ Percentage

Returns a new instance of Percentage.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :percentage (Integer)

    Integer 0..100. 0 is never satisfied; 100 is always satisfied.

  • :parameter (String)

    The name of the parameter this Condition was created for (eg. "account_id").

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/eight_ball/conditions/percentage.rb', line 18

def initialize(options = {})
  options ||= {}

  raise ArgumentError, 'Missing value for percentage' if options[:percentage].nil?

  percentage = options[:percentage]
  percentage = percentage.to_i if percentage.is_a?(Float) && percentage.to_i == percentage
  unless percentage.is_a?(Integer) && percentage >= 0 && percentage <= 100
    raise ArgumentError, 'percentage must be an integer between 0 and 100'
  end

  @percentage = percentage
  @flag_name = nil

  self.parameter = options[:parameter]
end

Instance Attribute Details

#flag_nameObject

Returns the value of attribute flag_name.



11
12
13
# File 'lib/eight_ball/conditions/percentage.rb', line 11

def flag_name
  @flag_name
end

#percentageObject (readonly)

Returns the value of attribute percentage.



11
12
13
# File 'lib/eight_ball/conditions/percentage.rb', line 11

def percentage
  @percentage
end

Instance Method Details

#satisfied?(value) ⇒ Boolean

Returns whether the subject falls within the bucket.

Parameters:

  • value

    The value of Base#parameter for the subject being evaluated.

Returns:

  • (Boolean)

    whether the subject falls within the bucket.

Raises:

  • (ArgumentError)

    if #flag_name was never injected.



43
44
45
46
47
48
# File 'lib/eight_ball/conditions/percentage.rb', line 43

def satisfied?(value)
  raise ArgumentError, 'flag_name has not been set on Percentage condition' if @flag_name.nil?

  bucket = Integer(Digest::SHA256.hexdigest("#{@flag_name}:#{value}")[0, 8], 16) % 100
  bucket < @percentage
end

#wire_fieldsObject



50
51
52
# File 'lib/eight_ball/conditions/percentage.rb', line 50

def wire_fields
  %i[percentage parameter]
end