Last active
January 9, 2025 16:37
-
-
Save gecugamo/b3633ac2d65589418ba9f6fe99612731 to your computer and use it in GitHub Desktop.
Dynamic Rules
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DynamicRuleAttributeService | |
METHOD_DICTIONARY = { | |
"coverage.coverage_a" => :coverage_a, | |
"coverage.coverage_b" => :coverage_b | |
}.freeze | |
# Finds the value for a given attribute alias | |
# @param attr_alias [String] Alias of attribute to find | |
# @return [Object, nil] Result of the corresponding method call or nil if not found | |
def self.call(policy, attr_alias) | |
method_name = METHOD_DICTIONARY[attr_alias] | |
raise ArgumentError, "Unknown alias: #{attr_alias}" unless method_name | |
method(method_name).call(policy) | |
end | |
private | |
# Define methods corresponding to dictionary keys | |
def self.coverage_a(policy) | |
policy&.coverage&.coverage_a | |
end | |
def self.coverage_b(policy) | |
policy&.coverage&.coverage_b | |
end | |
end | |
class DynamicRuleOperatorService | |
METHOD_DICTIONARY = { | |
"added" => :added, | |
"removed" => :removed | |
}.freeze | |
def self.call(operator_alias, attribute, value) | |
method_name = METHOD_DICTIONARY[operator_alias] | |
raise ArgumentError, "Unknown alias: #{attr_alias}" unless method_name | |
method(method_name).call(attribute, value) | |
end | |
private | |
def self.added(attribute, value) | |
attribute == 10_000 | |
end | |
end | |
class DynamicRuleEvaluatorService | |
attr_reader :policy, :rules | |
def initialize(policy, rules) | |
@policy = policy | |
@rules = rules | |
end | |
# @return [Boolean] | |
def call | |
result = true | |
rules.each do |rule| | |
attribute = rule["attribute"] | |
operator = rule["operator"] | |
value = rule["value"] | |
should_lookup_value = rule["should_lookup_value"] | |
if should_lookup_value | |
value = DynamicRuleAttributeService.call(policy, value) | |
end | |
attribute_value = DynamicRuleAttributeService.call(policy, attribute) | |
current_result = DynamicRuleOperatorService.call( | |
operator, | |
attribute_value, | |
value | |
) | |
result = result && current_result | |
break unless result | |
end | |
result | |
end | |
end | |
# Example | |
class Coverage | |
def coverage_a | |
10_000 | |
end | |
def coverage_b | |
"10%" | |
end | |
end | |
class Policy | |
def coverage | |
Coverage.new | |
end | |
end | |
policy = Policy.new | |
rules = [ | |
{ | |
"attribute" => "coverage.coverage_a", | |
"operator" => "added", | |
"value" => nil | |
}, | |
{ | |
"attribute" => "coverage.coverage_b", | |
"operator" => "added", | |
"value" => nil | |
} | |
] | |
evaluator = DynamicRuleEvaluatorService.new(policy, rules) | |
puts evaluator.call |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment