ruy 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,18 +5,18 @@ module Ruy
5
5
  class GreaterThanOrEqual < Ruy::Rule
6
6
  attr_reader :attr, :value
7
7
 
8
- # @param attr Context attribute's name
9
8
  # @param value
9
+ # @param attr Context attribute's name
10
10
  # @yield a block in the context of the current rule
11
- def initialize(attr, value, &block)
11
+ def initialize(value, attr, &block)
12
12
  super
13
- @attr = attr
14
13
  @value = value
14
+ @attr = attr
15
15
  instance_exec(&block) if block_given?
16
16
  end
17
17
 
18
- def call(var_ctx)
19
- var_ctx.resolve(@attr) >= @value && super
18
+ def call(ctx)
19
+ @value <= ctx.resolve(@attr) && super
20
20
  end
21
21
 
22
22
  def ==(o)
@@ -0,0 +1,31 @@
1
+ module Ruy
2
+ module Conditions
3
+
4
+ # Expects that a context attribute is included in a set of values.
5
+ class In < Ruy::Rule
6
+ attr_reader :attr, :values
7
+
8
+ # @param values Expected set of values
9
+ # @param attr Context attribute's name
10
+ # @yield a block in the context of the current rule
11
+ def initialize(values, attr, &block)
12
+ super
13
+ @values = values
14
+ @attr = attr
15
+ instance_exec(&block) if block_given?
16
+ end
17
+
18
+ def call(var_ctx)
19
+ self.values.include?(var_ctx.resolve(self.attr)) && super
20
+ end
21
+
22
+ def ==(o)
23
+ o.kind_of?(In) &&
24
+ self.attr == o.attr &&
25
+ self.values == o.values &&
26
+ self.conditions == o.conditions
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ module Ruy
2
+ module Conditions
3
+ class InCyclicOrder < Ruy::Rule
4
+ attr_reader :from, :to, :attr
5
+
6
+ def initialize(from, to, attr, &block)
7
+ super
8
+ @from = from
9
+ @to = to
10
+ @attr = attr
11
+ instance_exec(&block) if block_given?
12
+ end
13
+
14
+ def call(ctx)
15
+ value = ctx.resolve(@attr)
16
+
17
+ if @from > @to
18
+ (@from <= value || @to >= value) && super
19
+ else
20
+ (@from <= value && @to >= value) && super
21
+ end
22
+ end
23
+
24
+ def ==(o)
25
+ o.kind_of?(self.class) &&
26
+ @from == o.from &&
27
+ @to == o.to &&
28
+ @attr == o.attr &&
29
+ self.conditions == o.conditions
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,28 +1,28 @@
1
1
  module Ruy
2
2
  module Conditions
3
3
 
4
- # Expects that a context attribute is included in a set of values.
4
+ # Expects that a value is included in a set of values from the context attribute.
5
5
  class Include < Ruy::Rule
6
- attr_reader :attr, :values
6
+ attr_reader :attr, :value
7
7
 
8
+ # @param value Expected set of values
8
9
  # @param attr Context attribute's name
9
- # @param values Expected set of values
10
10
  # @yield a block in the context of the current rule
11
- def initialize(attr, values, &block)
11
+ def initialize(value, attr, &block)
12
12
  super
13
+ @value = value
13
14
  @attr = attr
14
- @values = values
15
15
  instance_exec(&block) if block_given?
16
16
  end
17
17
 
18
- def call(var_ctx)
19
- self.values.include?(var_ctx.resolve(self.attr)) && super
18
+ def call(ctx)
19
+ ctx.resolve(self.attr).include?(self.value) && super
20
20
  end
21
21
 
22
22
  def ==(o)
23
23
  o.kind_of?(Include) &&
24
24
  self.attr == o.attr &&
25
- self.values == o.values &&
25
+ self.value == o.value &&
26
26
  self.conditions == o.conditions
27
27
  end
28
28
  end
@@ -15,8 +15,8 @@ module Ruy
15
15
  instance_exec(&block) if block_given?
16
16
  end
17
17
 
18
- def call(var_ctx)
19
- var_ctx.resolve(self.attr).include?(self.value) && super
18
+ def call(ctx)
19
+ ctx.resolve(self.attr).include?(self.value) && super
20
20
  end
21
21
 
22
22
  def ==(o)
@@ -5,16 +5,16 @@ module Ruy
5
5
  class LessThan < Ruy::Rule
6
6
  attr_reader :attr, :value
7
7
 
8
- # @param attr Context attribute's name
9
8
  # @param value
10
- def initialize(attr, value)
9
+ # @param attr Context attribute's name
10
+ def initialize(value, attr)
11
11
  super
12
- @attr = attr
13
12
  @value = value
13
+ @attr = attr
14
14
  end
15
15
 
16
- def call(var_ctx)
17
- var_ctx.resolve(@attr) < @value
16
+ def call(ctx)
17
+ @value > ctx.resolve(@attr)
18
18
  end
19
19
 
20
20
  def ==(o)
@@ -7,14 +7,14 @@ module Ruy
7
7
 
8
8
  # @param attr Context attribute's name
9
9
  # @param value
10
- def initialize(attr, value)
10
+ def initialize(value, attr)
11
11
  super
12
- @attr = attr
13
12
  @value = value
13
+ @attr = attr
14
14
  end
15
15
 
16
- def call(var_ctx)
17
- var_ctx.resolve(@attr) <= @value
16
+ def call(ctx)
17
+ @value >= ctx.resolve(@attr)
18
18
  end
19
19
 
20
20
  def ==(o)
@@ -2,9 +2,10 @@ module Ruy
2
2
  module Conditions
3
3
 
4
4
  # Evaluates a block using comparison matchers that receive time-related objects with time zone awareness.
5
- # Does not support time zone-aware matchers inside sub-blocks.
6
- # A workaround for this is always surrounding your time zone-aware matchers by a 'tz' block even in sub-blocks
7
- # already surrounded by one.
5
+ #
6
+ # @note Does not support time zone-aware matchers inside sub-blocks.
7
+ # A workaround for this is always surrounding your time zone-aware matchers by a 'tz' block even in sub-blocks
8
+ # already surrounded by one.
8
9
  class TZ < Ruy::Rule
9
10
  # @param [String] tz_identifier String representing IANA's time zone identifier.
10
11
  def initialize(tz_identifier)
@@ -12,25 +13,25 @@ module Ruy
12
13
  @tz_identifier = tz_identifier
13
14
  end
14
15
 
15
- # @param [Ruy::VariableContext] var_ctx
16
- def call(var_ctx)
16
+ # @param [Ruy::VariableContext] ctx
17
+ def call(ctx)
17
18
  @conditions.all? do |condition|
18
- condition.call(var_ctx)
19
+ condition.call(ctx)
19
20
  end
20
21
  end
21
22
 
22
23
  # Adds a DayOfWeek condition
23
24
  #
24
25
  # @param (see Ruy::Conditions::DayOfWeek#initialize)
25
- def day_of_week(attr, dow)
26
- @conditions << DayOfWeek.new(attr, dow, @tz_identifier)
26
+ def day_of_week(dow, attr)
27
+ @conditions << DayOfWeek.new(dow, attr, @tz_identifier)
27
28
  end
28
29
 
29
30
  # Intercepts an 'eq' call to the superclass and enhances its arguments
30
31
  #
31
32
  # @param (see Ruy::Conditions::Eq#initialize)
32
- def eq(attr, pattern, &block)
33
- super(attr, TimePattern.new(pattern, @tz_identifier), &block)
33
+ def eq(pattern, attr, &block)
34
+ super(TimePattern.new(pattern, @tz_identifier), attr, &block)
34
35
  end
35
36
 
36
37
  # TODO Add Greater condition call here
@@ -38,29 +39,29 @@ module Ruy
38
39
  # Intercepts a 'greater_than_or_equal' call to the superclass and enhances its arguments
39
40
  #
40
41
  # @param (see Ruy::Conditions::GreaterThanOrEqual#initialize)
41
- def greater_than_or_equal(attr, pattern, &block)
42
- super(attr, TimePattern.new(pattern, @tz_identifier), &block)
42
+ def greater_than_or_equal(pattern, attr, &block)
43
+ super(TimePattern.new(pattern, @tz_identifier), attr, &block)
43
44
  end
44
45
 
45
46
  # Intercepts a 'less_than' call to the superclass and enhances its arguments
46
47
  #
47
48
  # @param (see Ruy::Conditions::LessThan#initialize)
48
- def less_than(attr, pattern, &block)
49
- super(attr, TimePattern.new(pattern, @tz_identifier), &block)
49
+ def less_than(pattern, attr, &block)
50
+ super(TimePattern.new(pattern, @tz_identifier), attr, &block)
50
51
  end
51
52
 
52
53
  # Intercepts a 'less_than_or_equal' call to the superclass and enhances its arguments
53
54
  #
54
55
  # @param (see Ruy::Conditions::LessThanOrEqual#initialize)
55
- def less_than_or_equal(attr, pattern, &block)
56
- super(attr, TimePattern.new(pattern, @tz_identifier), &block)
56
+ def less_than_or_equal(pattern, attr, &block)
57
+ super(TimePattern.new(pattern, @tz_identifier), attr, &block)
57
58
  end
58
59
 
59
60
  # Intercepts a 'between' call to the superclass and enhances its arguments
60
61
  #
61
62
  # @param (see Ruy::Conditions::Between#initialize)
62
- def between(attr, from, to, &block)
63
- super(attr, TimePattern.new(from, @tz_identifier), TimePattern.new(to, @tz_identifier), &block)
63
+ def between(from, to, attr, &block)
64
+ super(TimePattern.new(from, @tz_identifier), TimePattern.new(to, @tz_identifier), attr, &block)
64
65
  end
65
66
 
66
67
  end
@@ -1,10 +1,28 @@
1
1
  module Ruy
2
- class Context < Hash
3
- def self.from_hash(hash)
4
- ctx = Context.new
5
- ctx.merge!(hash)
2
+ # Context that resolves lets and values access.
3
+ class Context
6
4
 
7
- ctx
5
+ # @param [Hash] ctx
6
+ # @param [Array] lets Names of the 'let' variables
7
+ def initialize(ctx, lets = [])
8
+ @ctx = ctx
9
+ @lets = lets
10
+
11
+ @resolved_lets = {}
12
+ end
13
+
14
+ # Resolve the given attr from the lets or the context.
15
+ #
16
+ # @param [Symbol] attr
17
+ #
18
+ # @return [Object]
19
+ # @return [nil] when attribute cannot be resolved
20
+ def resolve(attr)
21
+ if @lets.include?(attr)
22
+ @resolved_lets[attr] ||= @ctx.instance_exec(&@ctx[attr])
23
+ else
24
+ @ctx.fetch(attr) { |key| @ctx[key.to_s] }
25
+ end
8
26
  end
9
27
  end
10
28
  end
@@ -0,0 +1,146 @@
1
+ module Ruy
2
+ module DSL
3
+
4
+ # Adds an All condition.
5
+ #
6
+ # @yield Evaluates the given block in the context of the new rule
7
+ def all(&block)
8
+ cond = Conditions::All.new
9
+ cond.instance_exec(&block)
10
+
11
+ self.conditions << cond
12
+ end
13
+
14
+ # Adds an Any condition.
15
+ #
16
+ # @yield Evaluates the given block in the context of the new rule
17
+ def any(&block)
18
+ cond = Conditions::Any.new
19
+ cond.instance_exec(&block)
20
+
21
+ self.conditions << cond
22
+ end
23
+
24
+ # Adds an Assert condition.
25
+ #
26
+ # @param (see Conditions::Assert#initialize)
27
+ def assert(attr)
28
+ self.conditions << Conditions::Assert.new(attr)
29
+ end
30
+
31
+ # Adds a Between condition.
32
+ #
33
+ # @param (see Conditions::Between#initialize)
34
+ def between(from, to, attr, &block)
35
+ self.conditions << Conditions::Between.new(from, to, attr, &block)
36
+ end
37
+
38
+ # Adds an Eq condition.
39
+ #
40
+ # @param (see Conditions::Eq#initialize)
41
+ def eq(value, attr, &block)
42
+ self.conditions << Conditions::Eq.new(value, attr, &block)
43
+ end
44
+
45
+ # Adds a Cond condition.
46
+ #
47
+ # @yield Evaluates the given block in the context of the new rule
48
+ def cond(&block)
49
+ cond = Conditions::Cond.new
50
+ cond.instance_exec(&block)
51
+
52
+ self.conditions << cond
53
+ end
54
+
55
+ # Adds an Except condition.
56
+ #
57
+ # @param (see Conditions::Except#initialize)
58
+ def except(value = nil, attr = nil, &block)
59
+ self.conditions << Conditions::Except.new(value, attr, &block)
60
+ end
61
+
62
+ # Adds a GreaterThan condition.
63
+ #
64
+ # @param (see Conditions::GreaterThanOrEqual#initialize)
65
+ def greater_than(value, attr)
66
+ @conditions << Conditions::GreaterThan.new(value, attr)
67
+ end
68
+
69
+ # Adds a GreaterThanOrEqual condition.
70
+ #
71
+ # @param (see Conditions::GreaterThanOrEqual#initialize)
72
+ def greater_than_or_equal(value, attr)
73
+ self.conditions << Conditions::GreaterThanOrEqual.new(value, attr)
74
+ end
75
+
76
+ # Adds an In condition.
77
+ #
78
+ # @param (see Conditions::Include#initialize)
79
+ def in(values, attr, &block)
80
+ self.conditions << Conditions::In.new(values, attr, &block)
81
+ end
82
+
83
+ # Adds a InCyclicOrder condition.
84
+ #
85
+ # @param (see Conditions::InCyclicOrder#initialize)
86
+ def in_cyclic_order(from, to, attr, &block)
87
+ @conditions << Conditions::InCyclicOrder.new(from, to, attr, &block)
88
+ end
89
+
90
+ # Adds an Include condition.
91
+ #
92
+ # @param (see Conditions::Included#initialize)
93
+ def include(value, attr, &block)
94
+ self.conditions << Conditions::Include.new(value, attr, &block)
95
+ end
96
+
97
+ # Adds a LessOrEqualThan condition.
98
+ #
99
+ # @param (see Conditions::LessOrEqualThan#initialize)
100
+ def less_than_or_equal(value, attr, &block)
101
+ self.conditions << Conditions::LessThanOrEqual.new(value, attr)
102
+ end
103
+
104
+ # Adds a LessThan condition.
105
+ #
106
+ # @param (see Conditions::LessThan#initialize)
107
+ def less_than(value, attr)
108
+ self.conditions << Conditions::LessThan.new(value, attr)
109
+ end
110
+
111
+ # Adds a TZ condition block
112
+ #
113
+ # @param [String] tz_identifier String representing IANA's
114
+ # time zone identifier. Defaults to UTC if none passed.
115
+ # @yield Evaluates the given block in the context of the TZ rule
116
+ def tz(tz_identifier = 'UTC', &block)
117
+ cond = Conditions::TZ.new(tz_identifier)
118
+ cond.instance_exec(&block)
119
+
120
+ self.conditions << cond
121
+ end
122
+
123
+ # @param [Integer] indentation Indentation level
124
+ def to_s(indentation = 0)
125
+ rule_name = Ruy::Utils::Naming.rule_name(self)
126
+
127
+ s = Ruy::Utils::Printable.indent(indentation) << rule_name
128
+
129
+ if self.params.any?
130
+ stringified_params = self.params.map(&:inspect)
131
+
132
+ s << ' ' << stringified_params.join(', ')
133
+ end
134
+
135
+ if self.conditions.empty?
136
+ s << "\n"
137
+ else
138
+ s << " do\n"
139
+ s << self.conditions.map { |c| c.to_s(indentation + 1) }.join()
140
+ s << Ruy::Utils::Printable.indent(indentation) + "end\n"
141
+ end
142
+
143
+ s
144
+ end
145
+ end
146
+ end