attestor 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/README.md +69 -55
  4. data/config/metrics/rubocop.yml +4 -0
  5. data/lib/attestor/invalid_error.rb +1 -12
  6. data/lib/attestor/policy/and.rb +2 -19
  7. data/lib/attestor/policy/negator.rb +2 -29
  8. data/lib/attestor/policy/node.rb +7 -33
  9. data/lib/attestor/policy/not.rb +2 -27
  10. data/lib/attestor/policy/or.rb +2 -19
  11. data/lib/attestor/policy/xor.rb +2 -19
  12. data/lib/attestor/policy.rb +0 -18
  13. data/lib/attestor/report.rb +51 -0
  14. data/lib/attestor/validations/delegator.rb +3 -18
  15. data/lib/attestor/validations/message.rb +1 -16
  16. data/lib/attestor/validations/reporter.rb +21 -0
  17. data/lib/attestor/validations/validator.rb +4 -63
  18. data/lib/attestor/validations/validators.rb +13 -41
  19. data/lib/attestor/validations.rb +12 -1
  20. data/lib/attestor/version.rb +1 -1
  21. data/lib/attestor.rb +2 -0
  22. data/spec/features/example_spec.rb +5 -5
  23. data/spec/support/policies.rb +5 -5
  24. data/spec/tests/policy/and_spec.rb +2 -2
  25. data/spec/tests/policy/node_spec.rb +9 -9
  26. data/spec/tests/policy/not_spec.rb +2 -2
  27. data/spec/tests/policy/or_spec.rb +2 -2
  28. data/spec/tests/policy/xor_spec.rb +2 -2
  29. data/spec/tests/policy_spec.rb +0 -48
  30. data/spec/tests/report_spec.rb +106 -0
  31. data/spec/tests/validations/delegator_spec.rb +6 -6
  32. data/spec/tests/validations/message_spec.rb +1 -1
  33. data/spec/tests/validations/reporter_spec.rb +47 -0
  34. data/spec/tests/validations/validator_spec.rb +56 -74
  35. data/spec/tests/validations/validators_spec.rb +81 -4
  36. data/spec/tests/validations_spec.rb +98 -10
  37. metadata +9 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3030abf371f99cd2d342e227e8d054fb718d0597
4
- data.tar.gz: 9742b46202b9d6e2cff850f6e52243f8668bdde7
3
+ metadata.gz: 1b4d9f6dfa1931f69062623223fafaf32ec4d158
4
+ data.tar.gz: a18709a18446af9c58a71287eb9b3d923c125aed
5
5
  SHA512:
6
- metadata.gz: 83ae6c32bb6be7ba47304a37ddc811ac3a22f761883dfc432f79533a2b7904860c2c81bd32e36b11d7e46e6ee445943074391dd90dab306e24548d2da58fd8d6
7
- data.tar.gz: a1d2d13d9c1c7b16e942755b482dae67d8aefb1ed12ee4ca31755d4b31d787ed5db915190af62ba4ed7893b98a6ceb41d6feacd4c7b2c7e8e3ff925291528d5b
6
+ metadata.gz: fadf072439c8efa450e86ff37f7dd5778c67ce7a087eaea4e012e0267d9dce2b877283b76c04b1434b1ab0d17b7a00a48317ddeee766304d7ff08ebb02c66109
7
+ data.tar.gz: 0c5fccf30fe0cfc574d71b3235da77acc904c3f537f4d9ffb4887184925d42c57d82736f99d0af0954fe000c0bc141cc1793bd15911275485bfcfc648bb235c6
data/.travis.yml CHANGED
@@ -6,5 +6,4 @@ rvm:
6
6
  - '2.0'
7
7
  - ruby-head
8
8
  - rbx-2 --2.0
9
- - jruby-head-20mode
10
- - jruby-head-21mode
9
+ - jruby-9.0.0.0.pre1
data/README.md CHANGED
@@ -37,7 +37,12 @@ To solve the problem, the `attestor` gem:
37
37
  Approach
38
38
  --------
39
39
 
40
- Instead of collecting errors inside the object, the module's `validate` instance method just raises an exception (`Attestor::InvalidError`), that carries errors outside of the object. The object stays untouched (and can be made immutable).
40
+ Instead of collecting errors inside the object, the module defines two instance methods:
41
+
42
+ * `validate!` raises an exception (`Attestor::InvalidError`), that carries errors outside of the object.
43
+ * `validate` - the safe version of `validate!`. It rescues an exception and returns special result object, that carries error info outside of the object.
44
+
45
+ The object stays untouched (and can be made immutable).
41
46
 
42
47
  Installation
43
48
  ------------
@@ -67,18 +72,10 @@ Basic Use
67
72
  Declare validation in the same way as ActiveModel's `.validate` method does:
68
73
 
69
74
  ```ruby
70
- class Transfer < Struct.new(:debet, :credit)
75
+ Transfer = Struct.new(:debet, :credit) do
71
76
  include Attestor::Validations
72
77
 
73
78
  validate :consistent
74
- end
75
- ```
76
-
77
- You have to define an instance validator method (that can be private):
78
-
79
- ```ruby
80
- class Transfer < Struct.new(:debet, :credit)
81
- # ...
82
79
 
83
80
  private
84
81
 
@@ -89,7 +86,16 @@ class Transfer < Struct.new(:debet, :credit)
89
86
  end
90
87
  ```
91
88
 
92
- The `#invalid` method translates its argument in a current class scope and raises an exception.
89
+ Alternatively, you can describe validation in the block (called in the scope of instance):
90
+
91
+ ```ruby
92
+ class Transfer
93
+ # ...
94
+ validate { invalid :inconsistent if credit.sum != debet.sum }
95
+ end
96
+ ```
97
+
98
+ The `#invalid` method translates its argument in a current class scope and raises an exception with that method.
93
99
 
94
100
  ```yaml
95
101
  # config/locales/en.yml
@@ -101,16 +107,7 @@ en:
101
107
  inconsistent: "Credit differs from debet by %{fraud}"
102
108
  ```
103
109
 
104
- Alternatively, you can describe validation in the block (called in the scope of instance):
105
-
106
- ```ruby
107
- class Transfer
108
- # ...
109
- validate { invalid :inconsistent if credit.sum != debet.sum }
110
- end
111
- ```
112
-
113
- To run validations use the `#validate` instance method:
110
+ To run validations use the `#validate!` instance method:
114
111
 
115
112
  ```ruby
116
113
  debet = OpenStruct.new(sum: 100)
@@ -118,14 +115,25 @@ credit = OpenStruct.new(sum: 90)
118
115
  fraud_transfer = Transfer.new(debet, credit)
119
116
 
120
117
  begin
121
- transfer.validate
122
- rescue => error
118
+ transfer.validate! # with the bang
119
+ rescue Attestor::InvalidError => error
123
120
  error.object == transfer # => true
124
- error.messages
125
- # => ["Credit differs from debet by 10"]
121
+ error.messages # => ["Credit differs from debet by 10"]
126
122
  end
127
123
  ```
128
124
 
125
+ Another option is to use the safe version `#validate`. It rescues from the exception and returns results in a separate report object:
126
+
127
+ ```ruby
128
+ report = transfer.validate # without the bang
129
+
130
+ report.valid? # => false
131
+ report.invalid? # => true
132
+ report.object == transfer # => true
133
+ report.messages # => ["Credit differs from debet by 10"]
134
+ report.error # => <Attestor::InvalidError ...>
135
+ ```
136
+
129
137
  Use of Contexts
130
138
  ---------------
131
139
 
@@ -134,43 +142,42 @@ Sometimes you need to validate the object agaist the subset of validations, not
134
142
  To do this use `:except` and `:only` options of the `.validate` class method.
135
143
 
136
144
  ```ruby
137
- class Transfer < Struct.new(:debet, :credit)
138
- include Attestor::Validations
139
-
145
+ class Transfer
146
+ # ...
140
147
  validate :consistent, except: :steal_of_money
141
148
  end
142
149
  ```
143
150
 
144
- Then call a validate method with that context:
151
+ Then call a `#validate!`/`#validate` methods with that context:
145
152
 
146
153
  ```ruby
147
- fraud_transfer.validate # => InvalidError
148
- fraud_transfer.validate :steal_of_money # => PASSES!
154
+ fraud_transfer.validate! # => InvalidError
155
+ fraud_transfer.validate! :steal_of_money # => PASSES!
149
156
  ```
150
157
 
151
- You can use the same validator several times with different contexts. Any validation will be made independently from the others:
158
+ You can use the same validator several times with different contexts.
152
159
 
153
160
  ```ruby
154
161
  class Transfer
155
162
  # ...
163
+
164
+ # validate :consistent, only: [:fair_trade, :legal]
156
165
  validate :consistent, only: :fair_trade
157
166
  validate :consistent, only: :legal
158
167
 
159
- # This is the same as:
160
- # validate :consistent, only: [:fair_trade, :legal]
161
168
  end
162
169
  ```
163
170
 
164
171
  Delegation
165
172
  ----------
166
173
 
167
- Extract validator to the external object (policy), that responds to `validate`.
174
+ Extract validator to an external object (policy), that responds to `validate!`.
168
175
 
169
176
  ```ruby
170
- class ConsistentTransfer.new(:debet, :credit)
177
+ ConsistentTransfer = Struct.new(:debet, :credit) do
171
178
  include Attestor::Validations
172
179
 
173
- def validate
180
+ def validate!
174
181
  invalid :inconsistent unless debet.sum == credit.sum
175
182
  end
176
183
  end
@@ -197,36 +204,36 @@ class Transfer
197
204
  end
198
205
  ```
199
206
 
200
- The change between `validate :something` and `validates :something` is that:
201
- * `validate` expects `#something` to make checks and raise error by itself
202
- * `validates` expects `#something` to respond to `#validate`
207
+ The difference between `.validate :something` and `.validates :something` class methods is that:
208
+ * `.validate` expects `#something` to make checks and raise error by itself
209
+ * `.validates` expects `#something` to respond to `#validate!`
203
210
 
204
211
  Policy Objects
205
212
  --------------
206
213
 
207
- Basically the policy includes `Attestor::Validations` with additional methods to allow chaining policies by logical methods.
214
+ Basically the policy includes `Attestor::Validations` with additional methods to allow logical compositions.
208
215
 
209
- To create a policy as a `Struct` use the builder method:
216
+ To create a policy as a `Struct` use the builder:
210
217
 
211
218
  ```ruby
212
219
  ConsistencyPolicy = Attestor::Policy.new(:debet, :credit) do
213
- def validate
220
+ def validate!
214
221
  fraud = credit - debet
215
222
  invalid :inconsistent, fraud: fraud if fraud != 0
216
223
  end
217
224
  end
218
225
  ```
219
226
 
220
- If you doesn't need Struct, include `Attestor::Policy` to the class and initialize its arguments somehow else:
227
+ If you doesn't need `Struct`, include `Attestor::Policy` to the class and initialize its arguments somehow else:
221
228
 
222
229
  ```ruby
223
- class ConsistencyPolicy < OpenStruct
230
+ class ConsistencyPolicy
224
231
  include Attestor::Policy
225
232
  # ...
226
233
  end
227
234
  ```
228
235
 
229
- Policy objects can be used by `validates` method like other validatable objects:
236
+ Policy objects can be used by `validates` method like other objects that respond to `#validate!`:
230
237
 
231
238
  ```ruby
232
239
  class Transfer
@@ -235,8 +242,6 @@ class Transfer
235
242
  end
236
243
  ```
237
244
 
238
- They also respond to `valid?` and `invalid?` methods (that just rescues from `vaidate` missing any error messages).
239
-
240
245
  Complex Policies
241
246
  ----------------
242
247
 
@@ -245,27 +250,27 @@ Policies (assertions) can be combined by logical methods.
245
250
  Suppose we have two policy objects:
246
251
 
247
252
  ```ruby
248
- valid_policy.valid? # => true
249
- invalid_policy.valid? # => false
253
+ valid_policy.validate.valid? # => true
254
+ invalid_policy.validate.valid? # => false
250
255
  ```
251
256
 
252
257
  Use factory methods to provide compositions:
253
258
 
254
259
  ```ruby
255
260
  complex_policy = valid_policy.not
256
- complex_policy.validate # => fails
261
+ complex_policy.validate! # => fails
257
262
 
258
263
  complex_policy = valid_policy.and(valid_policy, invalid_policy)
259
- complex_policy.validate # => fails
264
+ complex_policy.validate! # => fails
260
265
 
261
266
  complex_policy = invalid_policy.or(invalid_policy, valid_policy)
262
- complex_policy.validate # => passes
267
+ complex_policy.validate! # => passes
263
268
 
264
269
  complex_policy = valid_policy.xor(valid_poicy, valid_policy)
265
- complex_policy.validate # => fails
270
+ complex_policy.validate! # => fails
266
271
 
267
272
  complex_policy = valid_policy.xor(valid_poicy, invalid_policy)
268
- complex_policy.validate # => passes
273
+ complex_policy.validate! # => passes
269
274
  ```
270
275
 
271
276
  The `or`, `and` and `xor` methods called without argument(s) don't provide a policy object. They return lazy composer, expecting `#not` method.
@@ -294,6 +299,15 @@ Policy.not(valid_policy)
294
299
 
295
300
  As before, you can use any number of policies (except for negation of a single policy) at any number of nesting.
296
301
 
302
+ Latest changes
303
+ --------------
304
+
305
+ ### Version 2.0.0
306
+
307
+ 1. The method `#validate` doesn't raise an error. It returns a validation results report. To raise an exception use the unsafe `#validate!` method (see [Basic Use](#basic-use) for details).
308
+
309
+ 2. Policies doesn't have `#valid?` and `#invalid?` methods any longer. Both the methods are removed to `#validate` report.
310
+
297
311
  Compatibility
298
312
  -------------
299
313
 
@@ -52,6 +52,10 @@ Style/FileName:
52
52
  Style/RaiseArgs:
53
53
  EnforcedStyle: compact
54
54
 
55
+ Style/RescueModifier:
56
+ Exclude:
57
+ - '**/*_spec.rb'
58
+
55
59
  Style/SingleLineMethods:
56
60
  Exclude:
57
61
  - '**/*_spec.rb'
@@ -2,20 +2,9 @@
2
2
 
3
3
  module Attestor
4
4
 
5
- # The exception to be raised when a validation fails
5
+ # The exception to be raised when an unsafe validation fails
6
6
  class InvalidError < RuntimeError
7
7
 
8
- # @!scope class
9
- # @!method new(object, messages = nil)
10
- # Creates an exception for given object
11
- #
12
- # @param [Object] object
13
- # The invalid object
14
- # @param [String, Array<String>] messages
15
- # The list of validation error messages
16
- #
17
- # @return [Attestor::InvalidError]
18
-
19
8
  # @private
20
9
  def initialize(object, messages = nil)
21
10
  @object = object
@@ -4,27 +4,10 @@ module Attestor
4
4
 
5
5
  module Policy
6
6
 
7
- # AND-concatenation of several policies (branches)
8
- #
9
- # The policy is valid if all its branches are valid.
10
- #
11
- # @example (see #validate)
12
- #
13
- # @api private
7
+ # @private
14
8
  class And < Node
15
9
 
16
- # Checks whether every policy is valid
17
- #
18
- # @example
19
- # first.valid? # => true
20
- # second.valid? # => false
21
- #
22
- # composition = Attestor::Policy::And.new(first, second)
23
- # composition.validate
24
- # # => Policy::InvalidError
25
- #
26
- # @return [undefined]
27
- def validate
10
+ def validate!
28
11
  return unless detect(&:invalid?)
29
12
  super
30
13
  end
@@ -4,47 +4,20 @@ module Attestor
4
4
 
5
5
  module Policy
6
6
 
7
- # Composes a policy with an argument of its {#not} method
8
- #
9
- # @api private
7
+ # @private
10
8
  class Negator
11
9
 
12
- # @!scope class
13
- # @!method new(policy, composer)
14
- # Creates the negator object, expecting {#not} method call
15
- #
16
- # @param [Policy::Base] policy
17
- # the policy to be composed with negations of other policies
18
- # @param [Class] composer
19
- # the composer for policies
20
- #
21
- # @return [Policy::Base::Negator]
22
10
  def initialize(composer, policy)
23
11
  @policy = policy
24
12
  @composer = composer
25
13
  freeze
26
14
  end
27
15
 
28
- # Returns a composition of the {#policy} with negations of other policies
29
- #
30
- # @param [Policy::Base, Array<Policy::Base>] policies
31
- #
32
- # @return [Policy::Base]
33
16
  def not(*policies)
34
17
  composer.new policy, policies.flat_map(&Not.method(:new))
35
18
  end
36
19
 
37
- # @!attribute [r] policy
38
- # The the policy to be composed with negations of other policies
39
- #
40
- # @return [Policy::Base]
41
- attr_reader :policy
42
-
43
- # @!attribute [r] composer
44
- # The the composer for policies
45
- #
46
- # @return [Class]
47
- attr_reader :composer
20
+ attr_reader :policy, :composer
48
21
 
49
22
  end # class Negator
50
23
 
@@ -4,49 +4,23 @@ module Attestor
4
4
 
5
5
  module Policy
6
6
 
7
- # The base class for composite policies
8
- #
9
- # @api private
7
+ # @private
10
8
  class Node
11
- include Attestor::Policy
12
- include Enumerable
13
-
14
- # @!scope class
15
- # @!method new(*branches)
16
- # Creates the node with branches
17
- #
18
- # @param [<Attestor::Policy>, Array<Attestor::Policy>] branches
19
- #
20
- # @return [Policy::Base::Node]
21
-
22
- # @private
9
+ include Attestor::Policy, Enumerable
10
+
11
+ attr_reader :branches
12
+
23
13
  def initialize(*branches)
24
14
  @branches = branches.flatten
25
15
  freeze
26
16
  end
27
17
 
28
- # @!attribute [r] branches
29
- # The branches of the node
30
- #
31
- # @return [Array<Policy::Base>]
32
- attr_reader :branches
33
-
34
- # Validates the policy as invalid
35
- #
36
- # To be reloaded by subclasses (And, Or, Xor, Not)
37
- #
38
- # @raise [Policy::InvalidError]
39
- #
40
- # @return [undefined]
41
- def validate
18
+ def validate!
42
19
  invalid :base
43
20
  end
44
21
 
45
- # Iterates throught branches
46
- #
47
- # @return [Enumerator]
48
22
  def each
49
- block_given? ? branches.each { |item| yield(item) } : to_enum
23
+ block_given? ? branches.each { |item| yield(item.validate) } : to_enum
50
24
  end
51
25
 
52
26
  end # class Node
@@ -4,39 +4,14 @@ module Attestor
4
4
 
5
5
  module Policy
6
6
 
7
- # Negation of a single policy
8
- #
9
- # The policy is valid if its only branch is invalid
10
- #
11
- # @example (see #validate)
12
- #
13
- # @api private
7
+ # @private
14
8
  class Not < Node
15
9
 
16
- # @!scope class
17
- # @!method new(policy)
18
- # Creates the policy negation
19
- #
20
- # @param [Array<Policy::Base>] policy
21
- #
22
- # @return [Policy::Base::Node]
23
-
24
- # @private
25
10
  def initialize(_)
26
11
  super
27
12
  end
28
13
 
29
- # Checks whether every policy is valid
30
- #
31
- # @example
32
- # policy.valid? # => true
33
- #
34
- # composition = Attestor::Policy::Not.new(policy)
35
- # composition.validate
36
- # # => Policy::InvalidError
37
- #
38
- # @return [undefined]
39
- def validate
14
+ def validate!
40
15
  return unless detect(&:valid?)
41
16
  super
42
17
  end
@@ -4,27 +4,10 @@ module Attestor
4
4
 
5
5
  module Policy
6
6
 
7
- # OR-concatenation of several policies (branches)
8
- #
9
- # The policy is valid unless all its branches are invalid.
10
- #
11
- # @example (see #validate)
12
- #
13
- # @api private
7
+ # @private
14
8
  class Or < Node
15
9
 
16
- # Checks whether any policy is valid
17
- #
18
- # @example
19
- # first.valid? # => false
20
- # second.valid? # => false
21
- #
22
- # composition = Attestor::Policy::Or.new(first, second)
23
- # composition.validate
24
- # # => Policy::InvalidError
25
- #
26
- # @return [undefined]
27
- def validate
10
+ def validate!
28
11
  return if detect(&:valid?)
29
12
  super
30
13
  end
@@ -4,27 +4,10 @@ module Attestor
4
4
 
5
5
  module Policy
6
6
 
7
- # XOR-concatenation of several policies (branches)
8
- #
9
- # The policy is valid when it has both valid and invalid branches.
10
- #
11
- # @example (see #validate)
12
- #
13
- # @api private
7
+ # @private
14
8
  class Xor < Node
15
9
 
16
- # Checks whether both valid and invalid branches are present
17
- #
18
- # @example
19
- # first.valid? # => true
20
- # second.valid? # => true
21
- #
22
- # composition = Attestor::Policy::Xor.new(first, second)
23
- # composition.validate
24
- # # => Policy::InvalidError
25
- #
26
- # @return [undefined]
27
- def validate
10
+ def validate!
28
11
  return if detect(&:valid?) && detect(&:invalid?)
29
12
  super
30
13
  end
@@ -36,24 +36,6 @@ module Attestor
36
36
  end
37
37
  end
38
38
 
39
- # Checks whether the policy is valid
40
- #
41
- # @return [Boolean]
42
- def valid?
43
- validate
44
- rescue InvalidError
45
- false
46
- else
47
- true
48
- end
49
-
50
- # Checks whether the policy is invalid
51
- #
52
- # @return [Boolean]
53
- def invalid?
54
- !valid?
55
- end
56
-
57
39
  # Negates the current policy
58
40
  #
59
41
  # @return [Attestor::Policy::Not]
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ module Attestor
4
+
5
+ # Describes the result, returned by safe validation
6
+ class Report
7
+
8
+ # @private
9
+ def initialize(object, error = nil)
10
+ @object = object
11
+ @error = error
12
+ freeze
13
+ end
14
+
15
+ # @!attribute [r] object
16
+ # The object being validated
17
+ #
18
+ # @return [Object]
19
+ attr_reader :object
20
+
21
+ # @!attribute [r] error
22
+ # The exception raised by validation
23
+ #
24
+ # @return [Attestor::InvalidError] if validation fails
25
+ # @return [nil] if validation passes
26
+ attr_reader :error
27
+
28
+ # Checks whether validation passes
29
+ #
30
+ # @return [Boolean]
31
+ def valid?
32
+ error.blank?
33
+ end
34
+
35
+ # Checks whether validation fails
36
+ #
37
+ # @return [Boolean]
38
+ def invalid?
39
+ !valid?
40
+ end
41
+
42
+ # Returns the list of error messages
43
+ #
44
+ # @return [Array<String>]
45
+ def messages
46
+ error ? error.messages : []
47
+ end
48
+
49
+ end # class Report
50
+
51
+ end # module Attestor
@@ -4,26 +4,11 @@ module Attestor
4
4
 
5
5
  module Validations
6
6
 
7
- # Describe a validator that delegates validation to instance method or block
8
- #
9
- # The follower not only calls an instance method (block) as validator does,
10
- # but calls #validate method of the result.
11
- #
12
- # @example
13
- # follower = Validator.new(:foo, only: :baz) { FooPolicy.new(foo) }
14
- #
15
- # @api private
7
+ # @private
16
8
  class Delegator < Validator
17
9
 
18
- # Validates an object by delegation
19
- #
20
- # @param [Object] object
21
- #
22
- # @raise [Attestor::InvalidError] if a policy isn't valid
23
- #
24
- # @return [undefined]
25
- def validate(_)
26
- super.validate
10
+ def validate!(_)
11
+ super.validate!
27
12
  end
28
13
 
29
14
  end # class Follower
@@ -4,24 +4,9 @@ module Attestor
4
4
 
5
5
  module Validations
6
6
 
7
- # Bulder for error messages
8
- #
9
- # @api private
7
+ # @private
10
8
  class Message < String
11
9
 
12
- # @!scope class
13
- # @!method new(value, object, options = {})
14
- # Builds a string from value
15
- #
16
- # @param [#to_s] value
17
- # @param [Object] object
18
- # @param [Hash] options
19
- # options for translating symbolic value
20
- #
21
- # @return [String]
22
- # either translation of symbolic value or stringified value argument
23
-
24
- # @private
25
10
  def initialize(value, object, options = {})
26
11
  @value = value
27
12
  @object = object