Class: Dry::Logic::Rule

Inherits:
Object
  • Object
show all
Includes:
Core::Constants, Operators
Defined in:
lib/dry/logic/rule.rb,
lib/dry/logic/rule/interface.rb,
lib/dry/logic/rule/predicate.rb

Direct Known Subclasses

Predicate

Defined Under Namespace

Classes: Interface, Predicate

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Operators

#and, #or, #then, #xor

Constructor Details

#initialize(predicate, options = EMPTY_HASH) ⇒ Rule

Returns a new instance of Rule.



45
46
47
48
49
50
# File 'lib/dry/logic/rule.rb', line 45

def initialize(predicate, options = EMPTY_HASH)
  @predicate = predicate
  @options = options
  @args = options[:args] || EMPTY_ARRAY
  @arity = options[:arity] || predicate.arity
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



24
25
26
# File 'lib/dry/logic/rule.rb', line 24

def args
  @args
end

#arityObject (readonly)

Returns the value of attribute arity.



26
27
28
# File 'lib/dry/logic/rule.rb', line 26

def arity
  @arity
end

#optionsObject (readonly)

Returns the value of attribute options.



22
23
24
# File 'lib/dry/logic/rule.rb', line 22

def options
  @options
end

#predicateObject (readonly)

Returns the value of attribute predicate.



20
21
22
# File 'lib/dry/logic/rule.rb', line 20

def predicate
  @predicate
end

Class Method Details

.build(predicate, args: EMPTY_ARRAY, arity: predicate.arity, **options) ⇒ Object



41
42
43
# File 'lib/dry/logic/rule.rb', line 41

def self.build(predicate, args: EMPTY_ARRAY, arity: predicate.arity, **options)
  specialize(arity, args.size).new(predicate, {args: args, arity: arity, **options})
end

.interfacesObject



28
29
30
# File 'lib/dry/logic/rule.rb', line 28

def self.interfaces
  @interfaces ||= ::Concurrent::Map.new
end

.specialize(arity, curried, base = Rule) ⇒ Object



32
33
34
35
36
37
38
39
# File 'lib/dry/logic/rule.rb', line 32

def self.specialize(arity, curried, base = Rule)
  base.interfaces.fetch_or_store([arity, curried]) do
    interface = Interface.new(arity, curried)
    klass = Class.new(base) { include interface }
    base.const_set("#{base.name.split("::").last}#{interface.name}", klass)
    klass
  end
end

Instance Method Details

#ast(input = Undefined) ⇒ Object



87
88
89
# File 'lib/dry/logic/rule.rb', line 87

def ast(input = Undefined)
  [:predicate, [id, args_with_names(input)]]
end

#bind(object) ⇒ Object



64
65
66
67
68
69
70
71
72
73
# File 'lib/dry/logic/rule.rb', line 64

def bind(object)
  if predicate.respond_to?(:bind)
    self.class.build(predicate.bind(object), **options)
  else
    self.class.build(
      -> *args { object.instance_exec(*args, &predicate) },
      **options, arity: arity, parameters: parameters
    )
  end
end

#curry(*new_args) ⇒ Object



60
61
62
# File 'lib/dry/logic/rule.rb', line 60

def curry(*new_args)
  with(args: args + new_args)
end

#eval_args(object) ⇒ Object



75
76
77
# File 'lib/dry/logic/rule.rb', line 75

def eval_args(object)
  with(args: args.map { |arg| arg.is_a?(UnboundMethod) ? arg.bind(object).() : arg })
end

#idObject



56
57
58
# File 'lib/dry/logic/rule.rb', line 56

def id
  options[:id]
end

#parametersObject



83
84
85
# File 'lib/dry/logic/rule.rb', line 83

def parameters
  options[:parameters] || predicate.parameters
end

#typeObject



52
53
54
# File 'lib/dry/logic/rule.rb', line 52

def type
  :rule
end

#with(new_opts) ⇒ Object



79
80
81
# File 'lib/dry/logic/rule.rb', line 79

def with(new_opts)
  self.class.build(predicate, **options, **new_opts)
end