Module: Smplkit::Flags::JsonLogicEvaluator
- Defined in:
- lib/smplkit/flags/client.rb
Overview
Vendored minimal JSON Logic evaluator covering the operators the smplkit platform ships in flag rules.
Stays in-tree so the Ruby SDK doesn’t depend on the json_logic gem being correct — the Java SDK followed the same pattern. Operators supported: ==, !=, <, <=, >, >=, in, var, and, or, !, if, missing, none.
Class Method Summary collapse
- .apply(logic, data) ⇒ Object
- .compare(values, data) ⇒ Object
- .eval_if(values, data) ⇒ Object
- .eval_in(values, data) ⇒ Object
- .eval_missing(values, data) ⇒ Object
- .present?(value) ⇒ Boolean
- .resolve_var(path, data, default = nil) ⇒ Object
- .truthy?(value) ⇒ Boolean
Class Method Details
.apply(logic, data) ⇒ Object
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 |
# File 'lib/smplkit/flags/client.rb', line 749 def apply(logic, data) return logic unless logic.is_a?(Hash) return logic if logic.empty? op, values = logic.first values = [values] unless values.is_a?(Array) case op when "var" resolve_var(values[0], data, values[1]) when "and" values.reduce(true) { |acc, v| acc && truthy?(apply(v, data)) } when "or" values.reduce(false) { |acc, v| acc || truthy?(apply(v, data)) } when "!" !truthy?(apply(values[0], data)) when "if" eval_if(values, data) when "==", "===" apply(values[0], data) == apply(values[1], data) when "!=", "!==" apply(values[0], data) != apply(values[1], data) when "<" compare(values, data) { |a, b| a < b } when "<=" compare(values, data) { |a, b| a <= b } when ">" compare(values, data) { |a, b| a > b } when ">=" compare(values, data) { |a, b| a >= b } when "in" eval_in(values, data) when "missing" eval_missing(values, data) when "none" values_arr = apply(values[0], data) || [] inner = values[1] values_arr.is_a?(Array) && values_arr.none? { |item| truthy?(apply(inner, item)) } else false end end |
.compare(values, data) ⇒ Object
819 820 821 822 823 824 825 826 827 828 829 830 831 832 |
# File 'lib/smplkit/flags/client.rb', line 819 def compare(values, data) applied = values.map { |v| apply(v, data) } return false if applied.any?(&:nil?) if applied.length == 2 yield(applied[0], applied[1]) elsif applied.length == 3 yield(applied[0], applied[1]) && yield(applied[1], applied[2]) else false end rescue ArgumentError, TypeError false end |
.eval_if(values, data) ⇒ Object
834 835 836 837 838 839 840 841 842 |
# File 'lib/smplkit/flags/client.rb', line 834 def eval_if(values, data) i = 0 while i + 1 < values.length return apply(values[i + 1], data) if truthy?(apply(values[i], data)) i += 2 end i < values.length ? apply(values[i], data) : nil end |
.eval_in(values, data) ⇒ Object
844 845 846 847 848 849 850 851 852 |
# File 'lib/smplkit/flags/client.rb', line 844 def eval_in(values, data) needle = apply(values[0], data) haystack = apply(values[1], data) return false if haystack.nil? haystack.include?(needle) rescue NoMethodError, TypeError false end |
.eval_missing(values, data) ⇒ Object
854 855 856 857 |
# File 'lib/smplkit/flags/client.rb', line 854 def eval_missing(values, data) keys = values.is_a?(Array) ? values.flatten : [values] keys.reject { |k| present?(resolve_var(k, data)) } end |
.present?(value) ⇒ Boolean
859 860 861 |
# File 'lib/smplkit/flags/client.rb', line 859 def present?(value) !(value.nil? || value == "") end |
.resolve_var(path, data, default = nil) ⇒ Object
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 |
# File 'lib/smplkit/flags/client.rb', line 802 def resolve_var(path, data, default = nil) return data if path.nil? || path == "" || path == [] keys = path.is_a?(Array) ? path : path.to_s.split(".") keys.reduce(data) do |scope, key| break default if scope.nil? if scope.is_a?(Hash) scope[key] || scope[key.to_s] || scope[key.to_sym] elsif scope.is_a?(Array) && key.to_s =~ /\A\d+\z/ scope[key.to_i] else default end end || default end |
.truthy?(value) ⇒ Boolean
792 793 794 795 796 797 798 799 800 |
# File 'lib/smplkit/flags/client.rb', line 792 def truthy?(value) return false if value.nil? return false if value == false return false if value.is_a?(Numeric) && value.zero? return false if value == "" return false if value == [] true end |