sinclair 3.0.0 → 3.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d9505060c3b7a018a408ea37b59af41203747d280336fd5f1f6bb148f329af6
4
- data.tar.gz: 9967733ebc9f4ba73d553816a20530ff9399d3045cf0485f7412b0116924a2c8
3
+ metadata.gz: f788dd288f95c7d9ef8620ae943ecaefee7cf4a92a78775ef192e9b2a9a2db3c
4
+ data.tar.gz: 5147eaed065d2379d4fc2f89da54f03c58e866d0424fb87305a7b793531bc0ec
5
5
  SHA512:
6
- metadata.gz: 66bf1c943c5b9c9e6facfb8c5eecd92b86de5385f0fbb701715e62329ad5e82912272182baf4dce83f7517c8aae7b340aed8ce12e0315e0aefb805db3cfc90c7
7
- data.tar.gz: e1166a305873c0e5184a9d8043166f27e1f2ecae5be57d031fea48f5d7ec0f2c79c0d8f1acefdf1db30d54ad8579ea220d6cd64be160ae5d0f6505379291d96a
6
+ metadata.gz: df2085b864fc83862f28142ae6b7ad665e8e591eeb749cd13ccaf9f00d2753f13a8c17031cd4487afa2c122dbbe58e01cc7acc3ab01e1a04a0abdf2ae96fe1bf
7
+ data.tar.gz: a016558c3dd413674e3573d5db481c55c11a1e95c4388e3013a740668c11b45b84c6d35abc142a5cb7498e06d487e517143ea12cdacf2dd033b1a41acf7e7d7f
data/README.md CHANGED
@@ -15,13 +15,13 @@ create custom comparators, configure your application, create powerfull options,
15
15
 
16
16
  Employing Sinclair in your applications helps you streamline your development workflow and enhance your development process through more efficient, cleaner code
17
17
 
18
- Current Release: [3.0.0](https://github.com/darthjee/sinclair/tree/3.0.0)
18
+ Current Release: [3.0.1](https://github.com/darthjee/sinclair/tree/3.0.1)
19
19
 
20
- [Next release](https://github.com/darthjee/sinclair/compare/3.0.0...master)
20
+ [Next release](https://github.com/darthjee/sinclair/compare/3.0.1...master)
21
21
 
22
22
  Yard Documentation
23
23
  -------------------
24
- [https://www.rubydoc.info/gems/sinclair/3.0.0](https://www.rubydoc.info/gems/sinclair/3.0.0)
24
+ [https://www.rubydoc.info/gems/sinclair/3.0.1](https://www.rubydoc.info/gems/sinclair/3.0.1)
25
25
 
26
26
  Installation
27
27
  ---------------
@@ -11,9 +11,10 @@ class Sinclair
11
11
  # The block is executed adding the methods and after the builder
12
12
  # runs build building all the methods
13
13
  #
14
- # @param (see Sinclair#initialize)
15
- # @param block [Proc] block to be executed by the builder
16
- # in order to add the methods before running build
14
+ # @overload build(*args, **options, &block)
15
+ # @param (see Sinclair#initialize)
16
+ # @param block [Proc] block to be executed by the builder
17
+ # in order to add the methods before running build
17
18
  #
18
19
  # @yield an instance of a builder ({Sinclair})
19
20
  #
@@ -38,15 +38,15 @@ class Sinclair
38
38
  private
39
39
 
40
40
  # @private
41
- #
42
41
  # Method called for methods missing
43
42
  #
44
43
  # When a method is missing, it is expected that it is the
45
44
  # name of a variable to be set on config (as long as it was
46
45
  # defined in the config_attributes_array)
47
46
  #
48
- # @param method_name [Symbol] name of the method called
49
- # @param args [Array<Object>] arguments of the call
47
+ # @overload method_missing(method_name, *args)
48
+ # @param method_name [Symbol] name of the method called
49
+ # @param args [Array<Object>] arguments of the call
50
50
  #
51
51
  # @return [Object]
52
52
  def method_missing(method_name, *)
@@ -36,12 +36,15 @@ class Sinclair
36
36
  define_method(method_name) { value }
37
37
  end
38
38
 
39
- # @param name [String,Symbol] name of the method
40
- # @param code [String] code to be evaluated as method
41
- # @param block [Proc] block with code to be added as method
42
- # @param options [Hash] Options of construction
43
- # @option options cached [Boolean] Flag telling to create a block
44
- # with cache
39
+ # @overload from(name, code = nil, **options, &block)
40
+ # @param name [String,Symbol] name of the method
41
+ # @param code [String] code to be evaluated as method
42
+ # @param block [Proc] block with code to be added as method
43
+ # @param options [Hash] Options of construction
44
+ # @option options cached [Boolean, Symbol] Flag informing if value
45
+ # is cached or not.
46
+ # If +true+ the value is cached unless it is +nil+ or +false+.
47
+ # If +:full+ the value is cached even if it is +nil+ or +false+
45
48
  #
46
49
  # builds a method definition based on arguments
47
50
  #
@@ -107,8 +110,10 @@ class Sinclair
107
110
 
108
111
  # @param name [String,Symbol] name of the method
109
112
  # @param options [Hash] Options of construction
110
- # @option options cached [Boolean] Flag telling to create
111
- # a method with cache
113
+ # @option options cached [Boolean, Symbol] Flag informing if value
114
+ # is cached or not.
115
+ # If +true+ the value is cached unless it is +nil+ or +false+.
116
+ # If +:full+ the value is cached even if it is +nil+ or +false+
112
117
  def initialize(name, **options)
113
118
  @name = name
114
119
  @options = DEFAULT_OPTIONS.merge(options)
@@ -21,6 +21,10 @@ class Sinclair
21
21
  #
22
22
  # @option options type [Symbol] type to cast the value fetched
23
23
  # @option options default [Object] Default value
24
+ # @option options cached [Boolean, Symbol] Flag informing if value
25
+ # is cached or not.
26
+ # If +true+ the value is cached unless it is +nil+ or +false+.
27
+ # If +:full+ the value is cached even if it is +nil+ or +false+.
24
28
  def initialize(klass, *settings_name, **options)
25
29
  super(klass, **options)
26
30
 
@@ -89,13 +93,14 @@ class Sinclair
89
93
  #
90
94
  # @return (see Sinclair#add_class_method)
91
95
  def add_setting_method(name)
92
- options = call_options
93
- block = read_block
94
- caster = caster_class.caster_for(type)
95
- default = options_object.default
96
-
97
- add_class_method(name, cached: :full) do
98
- value = instance_exec(name, **options, &block)
96
+ read_options = call_options
97
+ block = read_block
98
+ caster = caster_class.caster_for(type)
99
+ default = options_object.default
100
+ cached = options.key?(:cached) ? options[:cached] : :full
101
+
102
+ add_class_method(name, cached:) do
103
+ value = instance_exec(name, **read_options, &block)
99
104
 
100
105
  value ? caster.cast(value) : default
101
106
  end
@@ -56,6 +56,8 @@ class Sinclair
56
56
  cast_with(:integer, &:to_i)
57
57
  cast_with(:string, &:to_s)
58
58
  cast_with(:float, &:to_f)
59
+ cast_with(:seconds) { |value| value.to_i.seconds }
60
+ cast_with(:boolean) { |value| value.to_s.downcase == 'true' }
59
61
  end
60
62
  end
61
63
  end
@@ -92,7 +92,16 @@ class Sinclair
92
92
  # to be added
93
93
  # @param options [Hash<Symbol, Object>] setting exposition options
94
94
  # @option options type [Symbol] type to cast the value fetched
95
+ # - integer: converts to Integer
96
+ # - string: converts to String
97
+ # - float: converts to Float
98
+ # - seconds: converts to ActiveSupport::Duration in seconds
99
+ # - boolean: converts to Boolean (true/false)
95
100
  # @option options default [Object] Default value
101
+ # @option options cached [Boolean, Symbol] Flag informing if value
102
+ # is cached or not.
103
+ # If +true+ the value is cached unless it is +nil+ or +false+.
104
+ # If +:full+ the value is cached even if it is +nil+ or +false+.
96
105
  #
97
106
  # @see with_settings
98
107
  # @return (see Sinclair#build)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Sinclair
4
- VERSION = '3.0.0'
4
+ VERSION = '3.0.1'
5
5
  end
data/lib/sinclair.rb CHANGED
@@ -205,8 +205,10 @@ class Sinclair
205
205
  # @param name [String,Symbol] name of the method to be added
206
206
  # @param code [String] code to be evaluated when the method is ran
207
207
  # @param options [Hash] Options of construction
208
- # @option options cached [Boolean] Flag telling to create
209
- # a method with cache
208
+ # @option options cached [Boolean, Symbol] Flag informing if value
209
+ # is cached or not.
210
+ # If +true+ the value is cached unless it is +nil+ or +false+.
211
+ # If +:full+ the value is cached even if it is +nil+ or +false+
210
212
  # @see MethodDefinition::StringDefinition
211
213
  #
212
214
  # @example Using string code to add a string defined method
@@ -229,8 +231,10 @@ class Sinclair
229
231
  # @param name [String,Symbol] name of the method to be added
230
232
  # @param block [Proc] block to be ran as method
231
233
  # @param options [Hash] Options of construction
232
- # @option options cached [Boolean] Flag telling to create
233
- # a method with cache
234
+ # @option options cached [Boolean, Symbol] Flag informing if value
235
+ # is cached or not.
236
+ # If +true+ the value is cached unless it is +nil+ or +false+.
237
+ # If +:full+ the value is cached even if it is +nil+ or +false+
234
238
  # @see MethodDefinition::BlockDefinition
235
239
  #
236
240
  # @example Using block to add a block method
@@ -254,8 +258,10 @@ class Sinclair
254
258
  # @param type [Symbol] type of method definition
255
259
  # @param block [Proc] block to be ran as method when type is block
256
260
  # @param options [Hash] Options of construction
257
- # @option options cached [Boolean] Flag telling to create
258
- # a method with cache
261
+ # @option options cached [Boolean, Symbol] Flag informing if value
262
+ # is cached or not.
263
+ # If +true+ the value is cached unless it is +nil+ or +false+.
264
+ # If +:full+ the value is cached even if it is +nil+ or +false+
259
265
  # @see MethodDefinition::BlockDefinition
260
266
  # @see MethodDefinition::StringDefinition
261
267
  # @see MethodDefinition::CallDefinition
@@ -305,8 +311,10 @@ class Sinclair
305
311
  # @param name [String,Symbol] name of the method to be added
306
312
  # @param code [String] code to be evaluated when the method is ran
307
313
  # @param options [Hash] Options of construction
308
- # @option options cached [Boolean] Flag telling to create
309
- # a method with cache
314
+ # @option options cached [Boolean, Symbol] Flag informing if value
315
+ # is cached or not.
316
+ # If +true+ the value is cached unless it is +nil+ or +false+.
317
+ # If +:full+ the value is cached even if it is +nil+ or +false+
310
318
  #
311
319
  # @example Adding a method by String
312
320
  # class EnvFetcher
@@ -325,8 +333,10 @@ class Sinclair
325
333
  # @param name [String,Symbol] name of the method to be added
326
334
  # @param block [Proc] block to be ran as method
327
335
  # @param options [Hash] Options of construction
328
- # @option options cached [Boolean] Flag telling to create
329
- # a method with cache
336
+ # @option options cached [Boolean, Symbol] Flag informing if value
337
+ # is cached or not.
338
+ # If +true+ the value is cached unless it is +nil+ or +false+.
339
+ # If +:full+ the value is cached even if it is +nil+ or +false+
330
340
  #
331
341
  # @example Adding a method by Block
332
342
  # class EnvFetcher
@@ -346,8 +356,10 @@ class Sinclair
346
356
  # @param type [Symbol] type of method definition
347
357
  # @param block [Proc] block to be ran as method when type is block
348
358
  # @param options [Hash] Options of construction
349
- # @option options cached [Boolean] Flag telling to create
350
- # a method with cache
359
+ # @option options cached [Boolean, Symbol] Flag informing if value
360
+ # is cached or not.
361
+ # If +true+ the value is cached unless it is +nil+ or +false+.
362
+ # If +:full+ the value is cached even if it is +nil+ or +false+
351
363
  # @see MethodDefinition::BlockDefinition
352
364
  # @see MethodDefinition::StringDefinition
353
365
  # @see MethodDefinition::CallDefinition
@@ -13,7 +13,9 @@ describe Sinclair::ChainSettable do
13
13
  source :app_client, env_setting
14
14
  source :my_app_client, Class.new(MyAppClient)
15
15
 
16
- setting_with_options :username, :password, :host, :port, **options
16
+ setting_with_options :username, :password,
17
+ :host, :port, :domain,
18
+ :secret, **options
17
19
  end
18
20
  end
19
21
 
@@ -21,12 +23,15 @@ describe Sinclair::ChainSettable do
21
23
  let(:options_hash) { {} }
22
24
  let(:username) { 'my_login' }
23
25
  let(:password) { Random.rand(10_000).to_s }
26
+ let(:prefix) { '' }
24
27
 
25
28
  context 'when the first setting finds the data' do
26
29
  let(:username_key) { 'USERNAME' }
27
30
  let(:password_key) { 'PASSWORD' }
28
31
  let(:host_key) { 'HOST' }
29
32
  let(:port_key) { 'PORT' }
33
+ let(:domain_key) { 'DOMAIN' }
34
+ let(:secret_key) { 'SECRET' }
30
35
 
31
36
  it_behaves_like 'settings reading'
32
37
  end
@@ -36,6 +41,9 @@ describe Sinclair::ChainSettable do
36
41
  let(:password_key) { 'MY_APP_PASSWORD' }
37
42
  let(:host_key) { 'MY_APP_HOST' }
38
43
  let(:port_key) { 'MY_APP_PORT' }
44
+ let(:domain_key) { 'MY_APP_DOMAIN' }
45
+ let(:secret_key) { 'MY_APP_SECRET' }
46
+ let(:prefix) { 'MY_APP_' }
39
47
 
40
48
  it_behaves_like 'settings reading'
41
49
  end
@@ -12,6 +12,8 @@ describe Sinclair::EnvSettable do
12
12
  let(:password_key) { 'PASSWORD' }
13
13
  let(:host_key) { 'HOST' }
14
14
  let(:port_key) { 'PORT' }
15
+ let(:domain_key) { 'DOMAIN' }
16
+ let(:secret_key) { 'SECRET' }
15
17
 
16
18
  it_behaves_like 'settings reading'
17
19
 
@@ -22,6 +24,8 @@ describe Sinclair::EnvSettable do
22
24
  let(:password_key) { 'MY_APP_PASSWORD' }
23
25
  let(:host_key) { 'MY_APP_HOST' }
24
26
  let(:port_key) { 'MY_APP_PORT' }
27
+ let(:domain_key) { 'MY_APP_DOMAIN' }
28
+ let(:secret_key) { 'MY_APP_SECRET' }
25
29
 
26
30
  it_behaves_like 'settings reading'
27
31
  end
@@ -31,6 +31,8 @@ describe Sinclair::Settable::Builder do
31
31
  let(:password_key) { 'PASSWORD' }
32
32
  let(:host_key) { 'HOST' }
33
33
  let(:port_key) { 'PORT' }
34
+ let(:domain_key) { 'DOMAIN' }
35
+ let(:secret_key) { 'SECRET' }
34
36
 
35
37
  it_behaves_like 'settings reading'
36
38
  end
@@ -41,6 +43,8 @@ describe Sinclair::Settable::Builder do
41
43
  let(:password_key) { 'MY_APP_PASSWORD' }
42
44
  let(:host_key) { 'MY_APP_HOST' }
43
45
  let(:port_key) { 'MY_APP_PORT' }
46
+ let(:domain_key) { 'MY_APP_DOMAIN' }
47
+ let(:secret_key) { 'MY_APP_SECRET' }
44
48
 
45
49
  it_behaves_like 'settings reading'
46
50
  end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::Settable::Caster do
6
+ describe '.cast' do
7
+ context 'when casting to integer' do
8
+ it 'converts string to integer' do
9
+ expect(described_class.cast('10', :integer)).to eq(10)
10
+ end
11
+
12
+ it 'converts float to integer' do
13
+ expect(described_class.cast(10.5, :integer)).to eq(10)
14
+ end
15
+ end
16
+
17
+ context 'when casting to string' do
18
+ it 'converts integer to string' do
19
+ expect(described_class.cast(10, :string)).to eq('10')
20
+ end
21
+
22
+ it 'converts symbol to string' do
23
+ expect(described_class.cast(:symbol, :string)).to eq('symbol')
24
+ end
25
+ end
26
+
27
+ context 'when casting to float' do
28
+ it 'converts string to float' do
29
+ expect(described_class.cast('10.5', :float)).to eq(10.5)
30
+ end
31
+
32
+ it 'converts integer to float' do
33
+ expect(described_class.cast(10, :float)).to eq(10.0)
34
+ end
35
+ end
36
+
37
+ context 'when casting to seconds' do
38
+ it 'converts string to seconds duration' do
39
+ expect(described_class.cast('300', :seconds)).to eq(300.seconds)
40
+ end
41
+
42
+ it 'converts integer to seconds duration' do
43
+ expect(described_class.cast(60, :seconds)).to eq(60.seconds)
44
+ end
45
+ end
46
+
47
+ context 'when casting to boolean' do
48
+ it 'converts string "true" to boolean true' do
49
+ expect(described_class.cast('true', :boolean)).to be true
50
+ end
51
+
52
+ it 'converts string "TRUE" to boolean true' do
53
+ expect(described_class.cast('TRUE', :boolean)).to be true
54
+ end
55
+
56
+ it 'converts string "false" to boolean false' do
57
+ expect(described_class.cast('false', :boolean)).to be false
58
+ end
59
+
60
+ it 'converts string "FALSE" to boolean false' do
61
+ expect(described_class.cast('FALSE', :boolean)).to be false
62
+ end
63
+
64
+ it 'converts any other string to boolean false' do
65
+ expect(described_class.cast('anything', :boolean)).to be false
66
+ end
67
+
68
+ it 'converts nil to boolean false' do
69
+ expect(described_class.cast(nil, :boolean)).to be false
70
+ end
71
+ end
72
+
73
+ context 'when casting with unknown type' do
74
+ it 'returns the original value' do
75
+ expect(described_class.cast('value', :unknown)).to eq('value')
76
+ end
77
+ end
78
+ end
79
+ end
@@ -13,6 +13,8 @@ describe Sinclair::Settable do
13
13
  let(:password_key) { 'PASSWORD' }
14
14
  let(:host_key) { 'HOST' }
15
15
  let(:port_key) { 'PORT' }
16
+ let(:domain_key) { 'DOMAIN' }
17
+ let(:secret_key) { 'SECRET' }
16
18
 
17
19
  it_behaves_like 'settings reading'
18
20
 
@@ -23,6 +25,8 @@ describe Sinclair::Settable do
23
25
  let(:password_key) { 'MY_APP_PASSWORD' }
24
26
  let(:host_key) { 'MY_APP_HOST' }
25
27
  let(:port_key) { 'MY_APP_PORT' }
28
+ let(:domain_key) { 'MY_APP_DOMAIN' }
29
+ let(:secret_key) { 'MY_APP_SECRET' }
26
30
 
27
31
  it_behaves_like 'settings reading'
28
32
  end
@@ -38,6 +42,8 @@ describe Sinclair::Settable do
38
42
  let(:password_key) { :password }
39
43
  let(:host_key) { :host }
40
44
  let(:port_key) { :port }
45
+ let(:domain_key) { :domain }
46
+ let(:secret_key) { :secret }
41
47
 
42
48
  it_behaves_like 'settings reading' do
43
49
  let(:env_hash) { HashAppClient::HASH }
@@ -5,4 +5,6 @@ class AppClient
5
5
 
6
6
  with_settings :username, :password, host: 'my-host.com'
7
7
  setting_with_options :port, type: :integer
8
+ setting_with_options :domain, cached: true
9
+ setting_with_options :secret, cached: false
8
10
  end
@@ -11,4 +11,6 @@ class HashAppClient
11
11
 
12
12
  with_settings :username, :password, host: 'my-host.com'
13
13
  setting_with_options :port, type: :integer
14
+ setting_with_options :domain, cached: true
15
+ setting_with_options :secret, cached: false
14
16
  end
@@ -7,4 +7,6 @@ class MyAppClient
7
7
 
8
8
  with_settings :username, :password, host: 'my-host.com'
9
9
  setting_with_options :port, type: :integer
10
+ setting_with_options :domain, cached: true
11
+ setting_with_options :secret, cached: false
10
12
  end
@@ -5,4 +5,6 @@ class NonDefaultAppClient
5
5
 
6
6
  with_settings :username, :password, :host
7
7
  setting_with_options :port, type: :integer
8
+ setting_with_options :domain, cached: true
9
+ setting_with_options :secret, cached: false
8
10
  end
@@ -4,6 +4,11 @@ shared_examples 'settings reading' do
4
4
  let(:env_hash) { ENV }
5
5
 
6
6
  context 'when the key is not set' do
7
+ after do
8
+ env_hash.delete(username_key)
9
+ env_hash.delete(password_key)
10
+ end
11
+
7
12
  it 'retrieves username from env' do
8
13
  expect(settable.username).to be_nil
9
14
  end
@@ -11,6 +16,16 @@ shared_examples 'settings reading' do
11
16
  it 'retrieves password from env' do
12
17
  expect(settable.password).to be_nil
13
18
  end
19
+
20
+ it 'cache username from env' do
21
+ expect { env_hash[username_key] = SecureRandom.hex }
22
+ .not_to(change(settable, :username))
23
+ end
24
+
25
+ it 'cache password from env' do
26
+ expect { env_hash[password_key] = SecureRandom.hex }
27
+ .not_to(change(settable, :password))
28
+ end
14
29
  end
15
30
 
16
31
  context 'when the key is set' do
@@ -31,14 +46,35 @@ shared_examples 'settings reading' do
31
46
  it 'retrieves password from env' do
32
47
  expect(settable.password).to eq(password)
33
48
  end
49
+
50
+ it 'cache username from env' do
51
+ expect { env_hash[username_key] = SecureRandom.hex }
52
+ .not_to(change(settable, :username))
53
+ end
54
+
55
+ it 'cache password from env' do
56
+ expect { env_hash[password_key] = SecureRandom.hex }
57
+ .not_to(change(settable, :password))
58
+ end
34
59
  end
35
60
 
36
61
  context 'when defining defaults' do
37
62
  let(:settings) { %i[host] }
38
63
  let(:options) { { prefix:, default: 'my-host.com' } }
39
64
 
40
- it 'returns default value' do
41
- expect(settable.host).to eq('my-host.com')
65
+ after do
66
+ env_hash.delete(host_key)
67
+ end
68
+
69
+ context 'when not setting the env variable' do
70
+ it 'returns default value' do
71
+ expect(settable.host).to eq('my-host.com')
72
+ end
73
+
74
+ it 'caches default value' do
75
+ expect { env_hash[host_key] = SecureRandom.hex }
76
+ .not_to(change(settable, :host))
77
+ end
42
78
  end
43
79
 
44
80
  context 'when setting the env variable' do
@@ -48,13 +84,14 @@ shared_examples 'settings reading' do
48
84
  env_hash[host_key] = other_host
49
85
  end
50
86
 
51
- after do
52
- env_hash.delete(host_key)
53
- end
54
-
55
87
  it 'retrieves host from env' do
56
88
  expect(settable.host).to eq(other_host)
57
89
  end
90
+
91
+ it 'caches env value' do
92
+ expect { env_hash[host_key] = SecureRandom.hex }
93
+ .not_to(change(settable, :host))
94
+ end
58
95
  end
59
96
  end
60
97
 
@@ -62,11 +99,21 @@ shared_examples 'settings reading' do
62
99
  let(:settings) { %i[port] }
63
100
  let(:options) { { prefix:, type: :integer } }
64
101
  let(:port) { Random.rand(10..100) }
102
+ let(:new_port) { Random.rand(1000..10_000) }
103
+
104
+ after do
105
+ env_hash.delete(port_key)
106
+ end
65
107
 
66
108
  context 'when the key is not set' do
67
109
  it 'retrieves port and cast to string' do
68
110
  expect(settable.port).to be_nil
69
111
  end
112
+
113
+ it 'caches port as nil' do
114
+ expect { env_hash[port_key] = new_port.to_s }
115
+ .not_to(change(settable, :port))
116
+ end
70
117
  end
71
118
 
72
119
  context 'when the key is set' do
@@ -74,13 +121,93 @@ shared_examples 'settings reading' do
74
121
  env_hash[port_key] = port.to_s
75
122
  end
76
123
 
77
- after do
78
- env_hash.delete(port_key)
79
- end
80
-
81
124
  it 'retrieves port and cast to string' do
82
125
  expect(settable.port).to eq(port)
83
126
  end
127
+
128
+ it 'caches port as integer' do
129
+ expect { env_hash[port_key] = new_port.to_s }
130
+ .not_to(change(settable, :port))
131
+ end
132
+ end
133
+ end
134
+
135
+ context 'when defining cache type as true' do
136
+ let(:settings) { %i[domain] }
137
+ let(:options) { { prefix:, cached: true } }
138
+ let(:options_hash) { options }
139
+ let(:domain) { 'example.com' }
140
+ let(:new_domain) { 'new-example.com' }
141
+
142
+ after do
143
+ env_hash.delete(domain_key)
144
+ end
145
+
146
+ context 'when the key is not set' do
147
+ it 'retrieves domain and cast to string' do
148
+ expect(settable.domain).to be_nil
149
+ end
150
+
151
+ it 'does not caches domain as nil' do
152
+ expect { env_hash[domain_key] = new_domain.to_s }
153
+ .to change(settable, :domain)
154
+ .from(nil).to(new_domain)
155
+ end
156
+ end
157
+
158
+ context 'when the key is set' do
159
+ before do
160
+ env_hash[domain_key] = domain.to_s
161
+ end
162
+
163
+ it 'retrieves domain and cast to string' do
164
+ expect(settable.domain).to eq(domain)
165
+ end
166
+
167
+ it 'caches domain as string' do
168
+ expect { env_hash[domain_key] = new_domain }
169
+ .not_to(change(settable, :domain))
170
+ end
171
+ end
172
+ end
173
+
174
+ context 'when defining cache false' do
175
+ let(:settings) { %i[secret] }
176
+ let(:options) { { prefix:, cached: false } }
177
+ let(:options_hash) { options }
178
+ let(:secret) { 'my_secret' }
179
+ let(:new_secret) { 'new_secret' }
180
+
181
+ after do
182
+ env_hash.delete(secret_key)
183
+ end
184
+
185
+ context 'when the key is not set' do
186
+ it 'retrieves secret and cast to string' do
187
+ expect(settable.secret).to be_nil
188
+ end
189
+
190
+ it 'does not caches secret as nil' do
191
+ expect { env_hash[secret_key] = new_secret.to_s }
192
+ .to change(settable, :secret)
193
+ .from(nil).to(new_secret)
194
+ end
195
+ end
196
+
197
+ context 'when the key is set' do
198
+ before do
199
+ env_hash[secret_key] = secret.to_s
200
+ end
201
+
202
+ it 'retrieves secret and cast to string' do
203
+ expect(settable.secret).to eq(secret)
204
+ end
205
+
206
+ it 'does not caches secret' do
207
+ expect { env_hash[secret_key] = new_secret }
208
+ .to change(settable, :secret)
209
+ .from(secret).to(new_secret)
210
+ end
84
211
  end
85
212
  end
86
213
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinclair
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - DarthJee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-09 00:00:00.000000000 Z
11
+ date: 2025-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -198,6 +198,7 @@ files:
198
198
  - spec/lib/sinclair/options_parser_spec.rb
199
199
  - spec/lib/sinclair/options_spec.rb
200
200
  - spec/lib/sinclair/settable/builder_spec.rb
201
+ - spec/lib/sinclair/settable/caster_spec.rb
201
202
  - spec/lib/sinclair/settable_spec.rb
202
203
  - spec/lib/sinclair_spec.rb
203
204
  - spec/spec_helper.rb