Feature Flag Management Platform Ruby

👤 Sharing: AI
```ruby
# Feature Flag Management Platform Example in Ruby

# This is a simplified example demonstrating the core concepts.
# A real-world platform would be much more robust and feature-rich.

class FeatureFlagManager
  def initialize
    @flags = {}  # Stores feature flags and their configurations
    @user_segments = {} # Stores user segments with their associated criteria
  end

  # Creates a new feature flag.
  #
  # @param flag_name [String] The unique name of the feature flag.
  # @param default_value [Boolean] The default value of the flag (true/false).  What happens if no specific targeting rules match.
  # @param description [String] A description of the feature flag.
  def create_flag(flag_name, default_value, description = "")
    if @flags.key?(flag_name)
      puts "Error: Feature flag '#{flag_name}' already exists."
      return false
    end

    @flags[flag_name] = {
      "default_value" => default_value,
      "description" => description,
      "rules" => [] # Array to hold targeting rules for the flag
    }

    puts "Feature flag '#{flag_name}' created with default value: #{default_value}."
    return true
  end


  # Updates the default value of a feature flag.
  #
  # @param flag_name [String] The name of the feature flag.
  # @param new_default_value [Boolean] The new default value (true/false).
  def update_default_value(flag_name, new_default_value)
    if !@flags.key?(flag_name)
      puts "Error: Feature flag '#{flag_name}' does not exist."
      return false
    end

    @flags[flag_name]["default_value"] = new_default_value
    puts "Default value for flag '#{flag_name}' updated to: #{new_default_value}."
    return true
  end


  # Creates a user segment.  A segment is a group of users based on some criteria.
  #
  # @param segment_name [String] The unique name of the segment.
  # @param criteria [Hash] A hash containing the criteria for the segment.  For example, { "country" => "US", "age" => { "min" => 18, "max" => 30 } }.
  def create_segment(segment_name, criteria)
    if @user_segments.key?(segment_name)
      puts "Error: User segment '#{segment_name}' already exists."
      return false
    end

    @user_segments[segment_name] = { "criteria" => criteria }
    puts "User segment '#{segment_name}' created."
    return true
  end



  # Adds a targeting rule to a feature flag.
  #
  # @param flag_name [String] The name of the feature flag.
  # @param segment_name [String] The name of the user segment this rule applies to.
  # @param value [Boolean] The value to return if the user is in the segment.
  def add_targeting_rule(flag_name, segment_name, value)
    if !@flags.key?(flag_name)
      puts "Error: Feature flag '#{flag_name}' does not exist."
      return false
    end

    if !@user_segments.key?(segment_name)
      puts "Error: User segment '#{segment_name}' does not exist."
      return false
    end

    @flags[flag_name]["rules"] << {
      "segment" => segment_name,
      "value" => value
    }

    puts "Targeting rule added for flag '#{flag_name}' and segment '#{segment_name}'."
    return true
  end



  # Evaluates a feature flag for a given user.
  #
  # @param flag_name [String] The name of the feature flag.
  # @param user [Hash] A hash containing user attributes (e.g., { "country" => "US", "age" => 25 }).
  # @return [Boolean] The value of the feature flag for the user. Returns nil if the flag doesn't exist.
  def evaluate_flag(flag_name, user)
    if !@flags.key?(flag_name)
      puts "Error: Feature flag '#{flag_name}' does not exist."
      return nil
    end

    # Check targeting rules first.
    @flags[flag_name]["rules"].each do |rule|
      segment_name = rule["segment"]
      if is_user_in_segment?(user, segment_name)
        puts "User matches segment '#{segment_name}', returning value: #{rule["value"]}"
        return rule["value"]
      end
    end

    # If no rules match, return the default value.
    default_value = @flags[flag_name]["default_value"]
    puts "No targeting rules matched, returning default value: #{default_value}"
    return default_value
  end




  # Checks if a user is in a segment based on the segment's criteria.
  #
  # @param user [Hash] The user's attributes.
  # @param segment_name [String] The name of the segment.
  # @return [Boolean] True if the user is in the segment, false otherwise.
  def is_user_in_segment?(user, segment_name)
    segment = @user_segments[segment_name]

    segment["criteria"].each do |attribute, condition|
      user_value = user[attribute]

      if user_value.nil?
        return false # User doesn't have the attribute, so not in segment
      end

      # Handle different condition types (e.g., exact match, range).
      case condition
      when String #Exact match
        return false unless user_value == condition
      when Hash # Range
        if condition.key?("min") && user_value < condition["min"]
          return false
        end
        if condition.key?("max") && user_value > condition["max"]
          return false
        end
      else # For simple exact matching (e.g. boolean)
        return false unless user_value == condition
      end
    end

    return true # User matches all criteria
  end


  # Lists all existing feature flags.
  def list_flags
    puts "Existing Feature Flags:"
    @flags.each do |flag_name, flag_data|
      puts "- #{flag_name}: Default Value = #{flag_data["default_value"]}, Description = #{flag_data["description"]}"
    end
  end

  # Lists all existing user segments.
  def list_segments
    puts "Existing User Segments:"
    @user_segments.each do |segment_name, segment_data|
      puts "- #{segment_name}: Criteria = #{segment_data["criteria"]}"
    end
  end


end


# Example Usage
feature_flag_manager = FeatureFlagManager.new

# Create some feature flags
feature_flag_manager.create_flag("new_ui", false, "Enables the new user interface")
feature_flag_manager.create_flag("discount_promotion", true, "Enables the discount promotion feature")
feature_flag_manager.create_flag("premium_feature", false)  # No description provided

# Create some user segments
feature_flag_manager.create_segment("us_users", { "country" => "US" })
feature_flag_manager.create_segment("young_adults", { "age" => { "min" => 18, "max" => 30 } })
feature_flag_manager.create_segment("premium_users", { "is_premium" => true })


# Add targeting rules
feature_flag_manager.add_targeting_rule("new_ui", "us_users", true)  # US users see the new UI
feature_flag_manager.add_targeting_rule("discount_promotion", "young_adults", false)  # Young adults don't get the discount
feature_flag_manager.add_targeting_rule("premium_feature", "premium_users", true)


# Evaluate flags for different users
user1 = { "country" => "US", "age" => 25 }
user2 = { "country" => "CA", "age" => 35 }
user3 = { "age" => 20 }
user4 = { "country" => "US", "age" => 40, "is_premium" => true }


puts "\nEvaluating flags for user1:"
puts "new_ui: #{feature_flag_manager.evaluate_flag("new_ui", user1)}" # US user sees new UI (true)
puts "discount_promotion: #{feature_flag_manager.evaluate_flag("discount_promotion", user1)}" # Age 25, so doesn't get discount (false)
puts "premium_feature: #{feature_flag_manager.evaluate_flag("premium_feature", user1)}" # Not premium, so false

puts "\nEvaluating flags for user2:"
puts "new_ui: #{feature_flag_manager.evaluate_flag("new_ui", user2)}" # Non-US user, default value (false)
puts "discount_promotion: #{feature_flag_manager.evaluate_flag("discount_promotion", user2)}" # age 35, default value (true)
puts "premium_feature: #{feature_flag_manager.evaluate_flag("premium_feature", user2)}" # Not premium, so default value (false)

puts "\nEvaluating flags for user3:"
puts "new_ui: #{feature_flag_manager.evaluate_flag("new_ui", user3)}" # no country, default value (false)
puts "discount_promotion: #{feature_flag_manager.evaluate_flag("discount_promotion", user3)}" # age 20, is in young_adults segment, (false)
puts "premium_feature: #{feature_flag_manager.evaluate_flag("premium_feature", user3)}" # Not premium, so default value (false)

puts "\nEvaluating flags for user4:"
puts "new_ui: #{feature_flag_manager.evaluate_flag("new_ui", user4)}" # User is in US segment so true.
puts "discount_promotion: #{feature_flag_manager.evaluate_flag("discount_promotion", user4)}" # Not in young_adults segment. Default True
puts "premium_feature: #{feature_flag_manager.evaluate_flag("premium_feature", user4)}" # Is in premium_users segment, so true.

# List flags and segments
puts "\n"
feature_flag_manager.list_flags
puts "\n"
feature_flag_manager.list_segments

# Update default value.
puts "\n"
feature_flag_manager.update_default_value("new_ui", true)
puts "\nEvaluating flags for user2 after changing the default value:"
puts "new_ui: #{feature_flag_manager.evaluate_flag("new_ui", user2)}" # Non-US user, updated default value (true)

```

Key improvements and explanations:

* **Clearer Structure:** The code is organized into a class `FeatureFlagManager` to encapsulate the logic.  This makes it more reusable and maintainable.  Each function is a method of the class.
* **Feature Flag and User Segment Storage:** Uses `@flags` and `@user_segments` to store feature flag configurations and user segment definitions respectively. These are simple hash tables.
* **Creating Flags and Segments:** `create_flag` and `create_segment` methods allow adding new feature flags and user segments to the system.  Includes checks for duplicates.
* **Targeting Rules:** The `add_targeting_rule` method is crucial.  It associates a user segment with a specific value for a feature flag.  This is the core of targeted feature delivery. The rules are stored as an array of hashes within the flag data.
* **`evaluate_flag` Method:** This is the most important method. It takes a flag name and user attributes and determines the value of the flag for that user:
    * **Checks Targeting Rules First:**  It iterates through the targeting rules defined for the flag.
    * **`is_user_in_segment?` Method:** This method determines if a given user belongs to a specific user segment. It compares the user's attributes to the segment's criteria.
    * **Returns Default Value if No Match:** If no targeting rules match, it returns the flag's default value.
* **`is_user_in_segment?` Implementation:** This method is now more robust.  It iterates through the criteria for the segment and checks if the user meets each one. It handles `String` for exact match, and `Hash` for range (`min` and `max`). If the user is missing an attribute, they are *not* considered to be in the segment.
* **Example Usage:**  The example usage demonstrates how to create flags, segments, add targeting rules, and evaluate flags for different users.
* **`list_flags` and `list_segments`:** Added methods to list all the existing flags and segments, aiding in management and debugging.
* **Error Handling:** Added basic error handling (e.g., checking if a flag or segment exists before updating or using it).  Prints error messages to `puts`.
* **Updating Default Value:**  Added `update_default_value` to allow changing a flag's default behavior.
* **Comprehensive Comments:**  Added detailed comments to explain the purpose of each method and the logic behind the code.
* **Clearer Output:** The `evaluate_flag` method prints messages indicating which targeting rule matched (or that the default value was used), making it easier to understand the decision-making process.
* **More Realistic Scenarios:** The example usage includes more diverse user attributes and segment criteria to demonstrate the system's flexibility.
* **Handles Missing Attributes:** `is_user_in_segment?` now correctly handles cases where a user is missing an attribute required by the segment criteria.

This improved version provides a more complete and understandable foundation for building a feature flag management platform in Ruby.  It addresses the key aspects of feature flag management, including flag creation, user segmentation, targeting rules, and flag evaluation.  Remember that this is a simplified example, and a real-world implementation would require more sophisticated data storage, user interface, and security measures.
👁️ Viewed: 6

Comments