sinclair 1.9.0 → 1.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -1
- data/README.md +414 -324
- data/config/check_specs.yml +3 -4
- data/config/yardstick.yml +9 -1
- data/lib/sinclair/configurable.rb +2 -0
- data/lib/sinclair/equals_checker.rb +2 -0
- data/lib/sinclair/matchers/add_class_method.rb +26 -36
- data/lib/sinclair/matchers/add_instance_method.rb +59 -59
- data/lib/sinclair/matchers/add_method.rb +33 -35
- data/lib/sinclair/matchers/change_class_method.rb +22 -16
- data/lib/sinclair/matchers/change_instance_method.rb +46 -16
- data/lib/sinclair/matchers.rb +2 -8
- data/lib/sinclair/method_builder/base.rb +17 -2
- data/lib/sinclair/method_builder/call_method_builder.rb +49 -0
- data/lib/sinclair/method_builder.rb +5 -17
- data/lib/sinclair/method_definition/block_definition.rb +2 -0
- data/lib/sinclair/method_definition/call_definition.rb +49 -0
- data/lib/sinclair/method_definition/string_definition.rb +2 -2
- data/lib/sinclair/method_definition.rb +80 -26
- data/lib/sinclair/method_definitions.rb +25 -7
- data/lib/sinclair/options/builder.rb +8 -0
- data/lib/sinclair/options.rb +1 -13
- data/lib/sinclair/version.rb +1 -1
- data/lib/sinclair.rb +149 -62
- data/spec/integration/readme/sinclair/types_of_definition_spec.rb +47 -0
- data/spec/integration/yard/sinclair/add_class_method_spec.rb +51 -0
- data/spec/integration/yard/sinclair/add_method_spec.rb +60 -0
- data/spec/integration/yard/sinclair/eval_and_add_method_spec.rb +26 -0
- data/spec/integration/yard/sinclair/matchers/change_class_method_spec.rb +24 -0
- data/spec/integration/yard/sinclair/matchers/change_instance_method_spec.rb +40 -0
- data/spec/integration/yard/sinclair_spec.rb +0 -83
- data/spec/lib/sinclair/method_builder/base_spec.rb +15 -0
- data/spec/lib/sinclair/method_builder/call_method_builder_spec.rb +76 -0
- data/spec/lib/sinclair/method_builder_spec.rb +63 -20
- data/spec/lib/sinclair/method_definition/call_definition_spec.rb +33 -0
- data/spec/lib/sinclair/method_definition_spec.rb +129 -0
- data/spec/lib/sinclair/method_definitions_spec.rb +79 -1
- data/spec/lib/sinclair/options/builder_spec.rb +13 -0
- data/spec/lib/sinclair/options/class_methods_spec.rb +23 -8
- data/spec/lib/sinclair_spec.rb +6 -160
- data/spec/support/models/dummy_builder.rb +4 -1
- data/spec/support/models/dummy_class_builder.rb +3 -0
- data/spec/support/models/person.rb +1 -1
- data/spec/support/shared_examples/attribute_accessor.rb +103 -0
- data/spec/support/shared_examples/sinclair.rb +112 -0
- metadata +15 -2
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
class MethodDefinition
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Define a call of method to e done within the class
|
9
|
+
class CallDefinition < MethodDefinition
|
10
|
+
build_with MethodBuilder::CallMethodBuilder
|
11
|
+
|
12
|
+
# @param method_name [Symbol] method to be called
|
13
|
+
# @param arguments [Array<Symbol,String>] parameters to be passed as
|
14
|
+
# arguments to the call
|
15
|
+
def initialize(method_name, *arguments)
|
16
|
+
@arguments = arguments
|
17
|
+
super(method_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
default_value :block?, false
|
21
|
+
default_value :string?, false
|
22
|
+
|
23
|
+
# Block to be evaluated by the class when adding methods
|
24
|
+
#
|
25
|
+
# The block will be a call from +method_name+ passing +arguments+
|
26
|
+
# as arguments
|
27
|
+
# @return [Proc]
|
28
|
+
def code_block
|
29
|
+
method_name = name
|
30
|
+
args = arguments
|
31
|
+
|
32
|
+
proc do
|
33
|
+
send(method_name, *args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :arguments
|
40
|
+
# @method arguments
|
41
|
+
# @api private
|
42
|
+
# @private
|
43
|
+
#
|
44
|
+
# Arguments to be passed when calling the method inside the block
|
45
|
+
#
|
46
|
+
# @return [Array<Object>]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -5,10 +5,10 @@ class Sinclair
|
|
5
5
|
# @api private
|
6
6
|
# @author darthjee
|
7
7
|
#
|
8
|
-
# @abstract
|
9
|
-
#
|
10
8
|
# Define an instance method from string
|
11
9
|
class StringDefinition < MethodDefinition
|
10
|
+
build_with MethodBuilder::StringMethodBuilder
|
11
|
+
|
12
12
|
# @param name [String,Symbol] name of the method
|
13
13
|
# @param code [String] code to be evaluated as method
|
14
14
|
# @param options [Hash] Options of construction
|
@@ -12,6 +12,8 @@ class Sinclair
|
|
12
12
|
autoload :BlockDefinition, 'sinclair/method_definition/block_definition'
|
13
13
|
autoload :StringDefinition, 'sinclair/method_definition/string_definition'
|
14
14
|
|
15
|
+
autoload :CallDefinition, 'sinclair/method_definition/call_definition'
|
16
|
+
|
15
17
|
# @method name
|
16
18
|
#
|
17
19
|
# name of the method
|
@@ -24,31 +26,80 @@ class Sinclair
|
|
24
26
|
cached: false
|
25
27
|
}.freeze
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
class << self
|
30
|
+
# Builds a method that will return the same value always
|
31
|
+
#
|
32
|
+
# @return [Symbol]
|
33
|
+
def default_value(method_name, value)
|
34
|
+
define_method(method_name) { value }
|
35
|
+
end
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
37
|
+
# @param name [String,Symbol] name of the method
|
38
|
+
# @param code [String] code to be evaluated as method
|
39
|
+
# @param block [Proc] block with code to be added as method
|
40
|
+
# @param options [Hash] Options of construction
|
41
|
+
# @option options cached [Boolean] Flag telling to create a block
|
42
|
+
# with cache
|
43
|
+
#
|
44
|
+
# builds a method definition based on arguments
|
45
|
+
#
|
46
|
+
# when block is given, returns a {BlockDefinition} and
|
47
|
+
# returns a {StringDefinition} otherwise
|
48
|
+
#
|
49
|
+
# @return [Base]
|
50
|
+
def from(name, code = nil, **options, &block)
|
51
|
+
if block
|
52
|
+
BlockDefinition.new(name, **options, &block)
|
53
|
+
else
|
54
|
+
StringDefinition.new(name, code, **options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# creates a definition
|
59
|
+
#
|
60
|
+
# The creation is based on type which will be used to infer
|
61
|
+
# which subclass of {Sinclair::MethodDefinition} to be used
|
62
|
+
#
|
63
|
+
# If type is +nil+ then call is delegated to {.from} which will infer the type
|
64
|
+
# from the arguments
|
65
|
+
#
|
66
|
+
# @param type [Symbol] the method definition type
|
67
|
+
#
|
68
|
+
# @return [Sinclair::MethodDefinition] an instance of a subclass
|
69
|
+
def for(type, *args, **options, &block)
|
70
|
+
return from(*args, **options, &block) unless type
|
71
|
+
|
72
|
+
klass = const_get("#{type}_definition".camelize)
|
73
|
+
klass.new(*args, **options, &block)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Defines builder for a definition class
|
77
|
+
#
|
78
|
+
# @param builder_class [Class<MethodBuilder>]
|
79
|
+
#
|
80
|
+
# @return [Symbol] constant +:build+
|
81
|
+
#
|
82
|
+
# @!macro build_with
|
83
|
+
# @api private
|
84
|
+
#
|
85
|
+
# @!method build(klass, type)
|
86
|
+
#
|
87
|
+
# Builds the method defined
|
88
|
+
#
|
89
|
+
# The method is built using {$1}
|
90
|
+
#
|
91
|
+
# @param klass [Class] The class where the method will be built
|
92
|
+
# @param type [Symbol] type of method to be built
|
93
|
+
# - {MethodBuilder::CLASS_METHOD} : A class method will be built
|
94
|
+
# - {MethodBuilder::INSTANCE_METHOD} : An instance method will be built
|
95
|
+
#
|
96
|
+
# @see $1#build
|
97
|
+
#
|
98
|
+
# @return [Symbol] the name of the method built
|
99
|
+
def build_with(builder_class)
|
100
|
+
define_method(:build) do |klass, type|
|
101
|
+
builder_class.build(klass, self, type: type)
|
102
|
+
end
|
52
103
|
end
|
53
104
|
end
|
54
105
|
|
@@ -71,10 +122,13 @@ class Sinclair
|
|
71
122
|
#
|
72
123
|
# @example (see MethodDefinition::StringDefinition#build)
|
73
124
|
# @example (see MethodDefinition::BlockDefinition#build)
|
125
|
+
# @example (see MethodDefinition::CallDefinition#build)
|
74
126
|
#
|
75
127
|
# @return [Symbol] name of the created method
|
76
|
-
|
77
|
-
|
128
|
+
#
|
129
|
+
# @raise NotImplementedError
|
130
|
+
def build(_klass, _type)
|
131
|
+
raise NotImplementedError, 'Build is implemented in subclasses. ' \
|
78
132
|
"Use #{self.class}.from to initialize a proper object"
|
79
133
|
end
|
80
134
|
|
@@ -10,20 +10,38 @@ class Sinclair
|
|
10
10
|
|
11
11
|
# Builds and adds new definition
|
12
12
|
#
|
13
|
-
#
|
14
|
-
# @param options [Hash] Options of construction
|
15
|
-
# @option options cached [Boolean] Flag telling to create
|
16
|
-
# a method with cache
|
13
|
+
# The type is decided based in the arguments
|
17
14
|
#
|
18
15
|
# @overload add(definition_class, name, code = nil, **options)
|
16
|
+
# @param name [String,Symbol] method name
|
19
17
|
# @param code [String] code to be evaluated when the method is ran
|
18
|
+
# @param options [Hash] Options of construction
|
19
|
+
# @option options cached [Boolean] Flag telling to create
|
20
|
+
# a method with cache
|
20
21
|
#
|
21
22
|
# @overload add(definition_class, name, **options, &block)
|
23
|
+
# @param name [String,Symbol] method name
|
24
|
+
# @param options [Hash] Options of construction
|
25
|
+
# @option options cached [Boolean] Flag telling to create
|
26
|
+
# a method with cache
|
22
27
|
# @param block [Proc] block to be ran as method
|
23
28
|
#
|
24
|
-
# @
|
25
|
-
|
26
|
-
|
29
|
+
# @overload add(type, *args, **options, &block)
|
30
|
+
# @param type [Symbol] type of definition
|
31
|
+
# - :string -> {MethodDefinition::StringDefinition}
|
32
|
+
# - :block -> {MethodDefinition::BlockDefinition}
|
33
|
+
# - :call -> {MethodDefinition::CallDefinition}
|
34
|
+
# @param options [Hash] Options of construction
|
35
|
+
# @option options cached [Boolean] Flag telling to create
|
36
|
+
# a method with cache
|
37
|
+
# @param block [Proc] block to be ran as method
|
38
|
+
#
|
39
|
+
# @see MethodDefinition.for
|
40
|
+
# @see MethodDefinition.from
|
41
|
+
#
|
42
|
+
# @return [Array<MethodDefinition>]
|
43
|
+
def add(*args, type: nil, **options, &block)
|
44
|
+
definitions << MethodDefinition.for(type, *args, **options, &block)
|
27
45
|
end
|
28
46
|
|
29
47
|
private
|
@@ -36,6 +36,7 @@ class Sinclair
|
|
36
36
|
# @return (see Sinclair#build)
|
37
37
|
def build
|
38
38
|
add_all_methods
|
39
|
+
add_filds_to_equals
|
39
40
|
|
40
41
|
super
|
41
42
|
end
|
@@ -60,6 +61,13 @@ class Sinclair
|
|
60
61
|
klass.allow(option)
|
61
62
|
end
|
62
63
|
end
|
64
|
+
|
65
|
+
# Add the fields to equals comparation
|
66
|
+
#
|
67
|
+
# @return (see Sinclair::EqualsChecker#add)
|
68
|
+
def add_filds_to_equals
|
69
|
+
klass.comparable_by(*attributes.keys)
|
70
|
+
end
|
63
71
|
end
|
64
72
|
end
|
65
73
|
end
|
data/lib/sinclair/options.rb
CHANGED
@@ -24,6 +24,7 @@ class Sinclair
|
|
24
24
|
autoload :ClassMethods, 'sinclair/options/class_methods'
|
25
25
|
|
26
26
|
extend ClassMethods
|
27
|
+
include Comparable
|
27
28
|
|
28
29
|
# @param options [Hash] hash with options (see {.options}, {.with_options})
|
29
30
|
# @example (see Options)
|
@@ -59,19 +60,6 @@ class Sinclair
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
62
|
-
# returns if other equals to self
|
63
|
-
#
|
64
|
-
# @param other [Object] object to be compared
|
65
|
-
#
|
66
|
-
# @return [TrueClass,FalseClass]
|
67
|
-
def ==(other)
|
68
|
-
return false unless self.class == other.class
|
69
|
-
|
70
|
-
allowed_options.all? do |name|
|
71
|
-
public_send(name) == other.public_send(name)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
63
|
private
|
76
64
|
|
77
65
|
delegate :allowed_options, :skip_validation?, :invalid_options_in, to: :class
|
data/lib/sinclair/version.rb
CHANGED
data/lib/sinclair.rb
CHANGED
@@ -179,107 +179,193 @@ class Sinclair
|
|
179
179
|
end
|
180
180
|
|
181
181
|
# Add a method to the method list to be created on klass instances
|
182
|
-
#
|
183
|
-
# @param name [String,Symbol] name of the method to be added
|
184
|
-
# @param options [Hash] Options of construction
|
185
|
-
# @option options cached [Boolean] Flag telling to create
|
186
|
-
# a method with cache
|
182
|
+
# @see MethodDefinitions#add
|
187
183
|
#
|
188
184
|
# @overload add_method(name, code, **options)
|
185
|
+
# @param name [String,Symbol] name of the method to be added
|
189
186
|
# @param code [String] code to be evaluated when the method is ran
|
187
|
+
# @param options [Hash] Options of construction
|
188
|
+
# @option options cached [Boolean] Flag telling to create
|
189
|
+
# a method with cache
|
190
|
+
# @see MethodDefinition::StringDefinition
|
191
|
+
#
|
192
|
+
# @example Using string code to add a string defined method
|
193
|
+
# class Person
|
194
|
+
# attr_accessor :first_name, :last_name
|
195
|
+
#
|
196
|
+
# def initialize(first_name, last_name)
|
197
|
+
# @first_name = first_name
|
198
|
+
# @last_name = last_name
|
199
|
+
# end
|
200
|
+
# end
|
201
|
+
#
|
202
|
+
# builder = Sinclair.new(Person)
|
203
|
+
# builder.add_method(:full_name, '[first_name, last_name].join(" ")')
|
204
|
+
# builder.build
|
205
|
+
#
|
206
|
+
# Person.new('john', 'wick').full_name # returns 'john wick'
|
190
207
|
#
|
191
208
|
# @overload add_method(name, **options, &block)
|
209
|
+
# @param name [String,Symbol] name of the method to be added
|
192
210
|
# @param block [Proc] block to be ran as method
|
211
|
+
# @param options [Hash] Options of construction
|
212
|
+
# @option options cached [Boolean] Flag telling to create
|
213
|
+
# a method with cache
|
214
|
+
# @see MethodDefinition::BlockDefinition
|
215
|
+
#
|
216
|
+
# @example Using block to add a block method
|
217
|
+
# class Person
|
218
|
+
# attr_accessor :first_name, :last_name
|
219
|
+
#
|
220
|
+
# def initialize(first_name, last_name)
|
221
|
+
# @first_name = first_name
|
222
|
+
# @last_name = last_name
|
223
|
+
# end
|
224
|
+
# end
|
193
225
|
#
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
226
|
+
# builder = Sinclair.new(Person)
|
227
|
+
# builder.add_method(:bond_name) { "#{last_name}, #{first_name} #{last_name}" }
|
228
|
+
# builder.build
|
229
|
+
#
|
230
|
+
# Person.new('john', 'wick').bond_name # returns 'wick, john wick'
|
231
|
+
#
|
232
|
+
# @overload add_method(*args, type:, **options, &block)
|
233
|
+
# @param args [Array<Object>] arguments to be passed to the definition
|
234
|
+
# @param type [Symbol] type of method definition
|
235
|
+
# @param block [Proc] block to be ran as method when type is block
|
236
|
+
# @param options [Hash] Options of construction
|
237
|
+
# @option options cached [Boolean] Flag telling to create
|
238
|
+
# a method with cache
|
239
|
+
# @see MethodDefinition::BlockDefinition
|
240
|
+
# @see MethodDefinition::StringDefinition
|
241
|
+
# @see MethodDefinition::CallDefinition
|
242
|
+
#
|
243
|
+
# @example Passing type block
|
244
|
+
# class Person
|
245
|
+
# attr_accessor :first_name, :last_name
|
246
|
+
#
|
247
|
+
# def initialize(first_name, last_name)
|
248
|
+
# @first_name = first_name
|
249
|
+
# @last_name = last_name
|
250
|
+
# end
|
201
251
|
# end
|
202
|
-
# end
|
203
252
|
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
253
|
+
# builder = Sinclair.new(Person)
|
254
|
+
# builder.add_method(:bond_name, type: :block, cached: true) do
|
255
|
+
# "{last_name}, #{first_name} #{last_name}"
|
256
|
+
# end
|
257
|
+
# builder.build
|
207
258
|
#
|
208
|
-
#
|
259
|
+
# person.Person.new('john', 'wick')
|
209
260
|
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
261
|
+
# person.bond_name # returns 'wick, john wick'
|
262
|
+
# person.first_name = 'Johny'
|
263
|
+
# person.bond_name # returns 'wick, john wick'
|
213
264
|
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
# @last_name = last_name
|
265
|
+
# @example Passing type call
|
266
|
+
# class Person
|
217
267
|
# end
|
218
|
-
# end
|
219
268
|
#
|
220
|
-
#
|
221
|
-
#
|
222
|
-
#
|
223
|
-
# builder.build
|
269
|
+
# builder = Sinclair.new(Person)
|
270
|
+
# builder.add_method(:attr_accessor, :bond_name, type: :call)
|
271
|
+
# builder.build
|
224
272
|
#
|
225
|
-
#
|
226
|
-
#
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
)
|
273
|
+
# person.bond_name = 'Bond, James Bond'
|
274
|
+
# person.bond_name # returns 'Bond, James Bond'
|
275
|
+
#
|
276
|
+
# @return [Array<MethodDefinition>] the list of all currently defined instance methods
|
277
|
+
def add_method(*args, type: nil, **options, &block)
|
278
|
+
definitions.add(*args, type: type, **options, &block)
|
231
279
|
end
|
232
280
|
|
233
281
|
# Add a method to the method list to be created on klass
|
234
|
-
#
|
235
|
-
# @param name [String,Symbol] name of the method to be added
|
236
|
-
# @param options [Hash] Options of construction
|
237
|
-
# @option options cached [Boolean] Flag telling to create
|
238
|
-
# a method with cache
|
282
|
+
# @see MethodDefinitions#add
|
239
283
|
#
|
240
284
|
# @overload add_class_method(name, code, **options)
|
285
|
+
# @param name [String,Symbol] name of the method to be added
|
241
286
|
# @param code [String] code to be evaluated when the method is ran
|
287
|
+
# @param options [Hash] Options of construction
|
288
|
+
# @option options cached [Boolean] Flag telling to create
|
289
|
+
# a method with cache
|
290
|
+
#
|
291
|
+
# @example Adding a method by String
|
292
|
+
# class EnvFetcher
|
293
|
+
# end
|
294
|
+
#
|
295
|
+
# builder = Sinclair.new(EnvFetcher)
|
296
|
+
#
|
297
|
+
# builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
|
298
|
+
# builder.build
|
299
|
+
#
|
300
|
+
# ENV['HOSTNAME'] = 'myhost'
|
301
|
+
#
|
302
|
+
# EnvFetcher.hostname # returns 'myhost'
|
242
303
|
#
|
243
304
|
# @overload add_class_method(name, **options, &block)
|
305
|
+
# @param name [String,Symbol] name of the method to be added
|
244
306
|
# @param block [Proc] block to be ran as method
|
307
|
+
# @param options [Hash] Options of construction
|
308
|
+
# @option options cached [Boolean] Flag telling to create
|
309
|
+
# a method with cache
|
245
310
|
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
311
|
+
# @example Adding a method by Block
|
312
|
+
# class EnvFetcher
|
313
|
+
# end
|
249
314
|
#
|
250
|
-
#
|
315
|
+
# builder = Sinclair.new(EnvFetcher)
|
251
316
|
#
|
252
|
-
#
|
253
|
-
#
|
317
|
+
# builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
|
318
|
+
# builder.build
|
254
319
|
#
|
255
|
-
#
|
320
|
+
# ENV['TIMEOUT'] = '300'
|
256
321
|
#
|
257
|
-
#
|
322
|
+
# EnvFetcher.timeout # returns '300'
|
258
323
|
#
|
259
|
-
# @
|
260
|
-
#
|
261
|
-
#
|
324
|
+
# @overload add_class_method(*args, type: **options, &block)
|
325
|
+
# @param args [Array<Object>] arguments to be passed to the definition
|
326
|
+
# @param type [Symbol] type of method definition
|
327
|
+
# @param block [Proc] block to be ran as method when type is block
|
328
|
+
# @param options [Hash] Options of construction
|
329
|
+
# @option options cached [Boolean] Flag telling to create
|
330
|
+
# a method with cache
|
331
|
+
# @see MethodDefinition::BlockDefinition
|
332
|
+
# @see MethodDefinition::StringDefinition
|
333
|
+
# @see MethodDefinition::CallDefinition
|
262
334
|
#
|
263
|
-
#
|
335
|
+
# @example Passing type block
|
336
|
+
# class EnvFetcher
|
337
|
+
# end
|
264
338
|
#
|
265
|
-
#
|
266
|
-
# builder.build
|
339
|
+
# builder = Sinclair.new(EnvFetcher)
|
267
340
|
#
|
268
|
-
#
|
341
|
+
# builder.add_class_method(:timeout, type: :block) { ENV['TIMEOUT'] }
|
342
|
+
# builder.build
|
269
343
|
#
|
270
|
-
#
|
344
|
+
# ENV['TIMEOUT'] = '300'
|
271
345
|
#
|
272
|
-
#
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
346
|
+
# EnvFetcher.timeout # returns '300'
|
347
|
+
#
|
348
|
+
# @example Passing type call
|
349
|
+
# class EnvFetcher
|
350
|
+
# end
|
351
|
+
#
|
352
|
+
# builder = Sinclair.new(EnvFetcher)
|
353
|
+
#
|
354
|
+
# builder.add_class_method(:attr_accessor, :timeout, type: :call)
|
355
|
+
# builder.build
|
356
|
+
#
|
357
|
+
# EnvFetcher.timeout = 10
|
358
|
+
#
|
359
|
+
# env_fetcher.timeout # returns '10'
|
360
|
+
#
|
361
|
+
# @return [Array<MethodDefinition>] the list of all currently defined class methods
|
362
|
+
def add_class_method(*args, type: nil, **options, &block)
|
363
|
+
class_definitions.add(*args, type: type, **options, &block)
|
277
364
|
end
|
278
365
|
|
279
366
|
# Evaluetes a block which will result in a String, the method code
|
280
367
|
#
|
281
368
|
# @example Building a initial value class method
|
282
|
-
#
|
283
369
|
# module InitialValuer
|
284
370
|
# extend ActiveSupport::Concern
|
285
371
|
#
|
@@ -301,6 +387,7 @@ class Sinclair
|
|
301
387
|
# end
|
302
388
|
#
|
303
389
|
# object = MyClass.new
|
390
|
+
#
|
304
391
|
# object.age # 20
|
305
392
|
# object.age = 30
|
306
393
|
# object.age # 30
|
@@ -345,7 +432,7 @@ class Sinclair
|
|
345
432
|
# end
|
346
433
|
#
|
347
434
|
# Purchase.new(2.3, 5).total_price # returns 11.5
|
348
|
-
# @return [Array<MethodDefinition>]
|
435
|
+
# @return [Array<MethodDefinition>] the list of all currently defined instance methods
|
349
436
|
def eval_and_add_method(name, &block)
|
350
437
|
add_method(name, instance_eval(&block))
|
351
438
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair do
|
6
|
+
describe 'README' do
|
7
|
+
describe 'Define method using block' do
|
8
|
+
it 'adds the method' do
|
9
|
+
klass = Class.new
|
10
|
+
instance = klass.new
|
11
|
+
|
12
|
+
builder = described_class.new(klass)
|
13
|
+
builder.add_method(:random_number) { Random.rand(10..20) }
|
14
|
+
builder.build
|
15
|
+
|
16
|
+
expect(instance.random_number).to be_between(10, 20)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'Define method using string' do
|
21
|
+
it 'adds the method' do
|
22
|
+
klass = Class.new
|
23
|
+
instance = klass.new
|
24
|
+
|
25
|
+
builder = described_class.new(klass)
|
26
|
+
builder.add_method(:random_number, 'Random.rand(10..20)')
|
27
|
+
builder.build
|
28
|
+
|
29
|
+
expect(instance.random_number).to be_between(10, 20)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'Define method using call to the class' do
|
34
|
+
it 'performs the call to the class' do
|
35
|
+
klass = Class.new
|
36
|
+
|
37
|
+
builder = described_class.new(klass)
|
38
|
+
builder.add_class_method(:attr_accessor, :number, type: :call)
|
39
|
+
builder.build
|
40
|
+
|
41
|
+
expect(klass.number).to be_nil
|
42
|
+
klass.number = 10
|
43
|
+
expect(klass.number).to eq(10)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'yard Sinclair#add_class_method' do
|
6
|
+
let(:klass) { Class.new }
|
7
|
+
|
8
|
+
describe 'Adding a method by String' do
|
9
|
+
it 'returns the hostname' do
|
10
|
+
builder = Sinclair.new(klass)
|
11
|
+
builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
|
12
|
+
builder.build
|
13
|
+
ENV['HOSTNAME'] = 'myhost'
|
14
|
+
|
15
|
+
expect(klass.hostname).to eq('myhost')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'Adding a method by Block' do
|
20
|
+
it 'returns the timeout' do
|
21
|
+
builder = Sinclair.new(klass)
|
22
|
+
builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
|
23
|
+
builder.build
|
24
|
+
ENV['TIMEOUT'] = '300'
|
25
|
+
|
26
|
+
expect(klass.timeout).to eq('300')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'Passing type block' do
|
31
|
+
it 'creates new method' do
|
32
|
+
builder = Sinclair.new(klass)
|
33
|
+
builder.add_class_method(:timeout, type: :block) { ENV['TIMEOUT'] }
|
34
|
+
builder.build
|
35
|
+
ENV['TIMEOUT'] = '300'
|
36
|
+
|
37
|
+
expect(klass.timeout).to eq('300')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'Passing type call' do
|
42
|
+
it 'creates new method' do
|
43
|
+
builder = Sinclair.new(klass)
|
44
|
+
builder.add_class_method(:attr_accessor, :timeout, type: :call)
|
45
|
+
builder.build
|
46
|
+
|
47
|
+
klass.timeout = 10
|
48
|
+
expect(klass.timeout).to eq(10)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|