opt_struct 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33f00177f26d90bc4c9407bfb63860b7ef223f73545311fd26e0e64039f9da92
4
- data.tar.gz: 6d5a5f91b1955e81607abb22c1704b36c3dbb9870a76fa6b26e494e19ccb3b4b
3
+ metadata.gz: 824012017028badde180165fa6280f398cbf138f09f8600319625e92fbaf67ed
4
+ data.tar.gz: 2c612d601c220eb88aaaf656917cd06d0edc7a87b70f84c67cda6b17e6cbbe94
5
5
  SHA512:
6
- metadata.gz: e11a757d9319851bddcc69052076996d618fe2f281822abd281fcfa4cefda3a4d2cda3c424e9ef3882800f76ff7435ddc327f71bfab69742e8ca5dfae98e1003
7
- data.tar.gz: f9174dce367fee3f1fea9bed17c8c004e1b6a8b73d4597e3bcb6bfb02d08d3e36b0b76e3bb0989d66e05983f4d895c6b4e0392a08555edf71887053548972782
6
+ metadata.gz: f7cf9e8c1d9e0b9c40a2f08c1f32784fa61b38a14edac39f4bef3f887845827a57f9b813e2f8df6dbb0436734c8f5895d7b25f45adb2bff3fa82eb7e87766fee
7
+ data.tar.gz: aea1084efba08f15951e7d8629c1a8211d66bddd720dfee19a1c1ec5a8eb52d6c73f047ac4ae8c5b7a969912113b0093249f48f991415ca932170d64e69b956d
data/lib/opt_struct.rb CHANGED
@@ -3,10 +3,11 @@ require "opt_struct/module_methods"
3
3
  require "opt_struct/instance_methods"
4
4
 
5
5
  module OptStruct
6
+ RESERVED_WORDS = %i(class defaults options fetch check_required_args check_required_keys).freeze
6
7
 
7
- def self._inject_struct(target, source, args = [], defaults = {}, &callback)
8
+ def self._inject_struct(target, source, args = [], **defaults, &callback)
8
9
  structs = Array(source.instance_variable_get(:@_opt_structs)).dup
9
- if args.any? || defaults.any? || callback
10
+ if args.any? || defaults.any? || block_given?
10
11
  structs << [args, defaults, callback]
11
12
  end
12
13
  target.instance_variable_set(:@_opt_structs, structs)
@@ -18,7 +19,7 @@ module OptStruct
18
19
  end
19
20
  structs.each do |s_args, s_defaults, s_callback|
20
21
  target.expect_arguments *s_args if s_args.any?
21
- target.options s_defaults if s_defaults.any?
22
+ target.options **s_defaults if s_defaults.any?
22
23
  target.class_exec(&s_callback) if s_callback
23
24
  end
24
25
  else
@@ -38,10 +39,10 @@ module OptStruct
38
39
  end
39
40
 
40
41
  def self.new(*args, **defaults, &callback)
41
- _inject_struct(Class.new, self, args.map(&:to_sym), defaults, &callback)
42
+ _inject_struct(Class.new, self, args.map(&:to_sym), **defaults, &callback)
42
43
  end
43
44
 
44
45
  def self.build(*args, **defaults, &callback)
45
- _inject_struct(Module.new, self, args.map(&:to_sym), defaults, &callback)
46
+ _inject_struct(Module.new, self, args.map(&:to_sym), **defaults, &callback)
46
47
  end
47
48
  end
@@ -1,68 +1,82 @@
1
1
  module OptStruct
2
2
  module ClassMethods
3
3
  def inherited(subclass)
4
- instance_variables.each do |v|
5
- ivar = instance_variable_get(v)
6
- subclass.send(:instance_variable_set, v, ivar.dup) if ivar
4
+ opt_struct_class_constants.each do |c|
5
+ subclass.const_set(c, const_get(c)) if const_defined?(c)
7
6
  end
8
7
  end
9
8
 
9
+ # overwritten if `required` is called
10
10
  def required_keys
11
- @required_keys ||= []
11
+ [].freeze
12
12
  end
13
13
 
14
- def required(*keys)
15
- required_keys.concat keys
16
- option_accessor *keys
14
+ def required(*keys, **options)
15
+ add_required_keys *keys
16
+ option_accessor *keys, **options
17
17
  end
18
18
 
19
- def option_reader(*keys)
19
+ def option_reader(*keys, **options)
20
20
  keys.each do |key|
21
- define_method(key) { options[key] }
21
+ class_eval <<~RUBY
22
+ #{options[:private] ? "private" : ""} def #{key}
23
+ options[:#{key}]
24
+ end
25
+ RUBY
22
26
  end
23
27
  end
24
28
 
25
- def option_writer(*keys)
29
+ def option_writer(*keys, **options)
26
30
  keys.each do |key|
27
- define_method("#{key}=") { |value| options[key] = value }
31
+ class_eval <<~RUBY
32
+ #{options[:private] ? "private" : ""} def #{key}=(value)
33
+ options[:#{key}] = value
34
+ end
35
+ RUBY
28
36
  end
29
37
  end
30
38
 
31
- def option_accessor(*keys)
39
+ def option_accessor(*keys, **options)
32
40
  check_reserved_words(keys)
33
- option_reader *keys
34
- option_writer *keys
41
+ option_reader *keys, **options
42
+ option_writer *keys, **options
35
43
  end
36
44
 
37
- def option(key, default = nil, **options)
45
+ def option(key, default = nil, required: false, **options)
38
46
  default = options[:default] if options.key?(:default)
39
- defaults[key] = default
40
- required_keys << key if options[:required]
41
- option_accessor key
47
+ add_defaults key => default
48
+ add_required_keys key if required
49
+ option_accessor key, **options
42
50
  end
43
51
 
44
52
  def options(*keys, **keys_defaults)
45
53
  option_accessor *keys if keys.any?
46
54
  if keys_defaults.any?
47
- defaults.merge!(keys_defaults)
55
+ add_defaults keys_defaults
48
56
  option_accessor *(keys_defaults.keys - expected_arguments)
49
57
  end
50
58
  end
51
59
 
52
60
  def defaults
53
- @defaults ||= {}
61
+ const_defined?(:OPT_DEFAULTS) ? const_get(:OPT_DEFAULTS) : {}
62
+ end
63
+
64
+ # overwritten if `expect_arguments` is called
65
+ def expected_arguments
66
+ [].freeze
54
67
  end
55
68
 
56
69
  def expect_arguments(*arguments)
57
70
  required(*arguments)
58
- expected_arguments.concat(arguments)
71
+ combined = expected_arguments + arguments
72
+ class_eval <<~EVAL
73
+ def self.expected_arguments
74
+ #{combined.inspect}.freeze
75
+ end
76
+ EVAL
59
77
  end
60
78
  alias_method :expect_argument, :expect_arguments
61
79
 
62
- def expected_arguments
63
- @expected_arguments ||= []
64
- end
65
-
66
80
  def init(meth = nil, &blk)
67
81
  add_callback(:init, meth || blk)
68
82
  end
@@ -76,23 +90,60 @@ module OptStruct
76
90
  add_callback(:around_init, meth || blk)
77
91
  end
78
92
 
79
- def add_callback(name, callback)
80
- @_callbacks ||= {}
81
- @_callbacks[name] ||= []
82
- @_callbacks[name] << callback
93
+ def all_callbacks
94
+ const_defined?(:OPT_CALLBACKS) ? const_get(:OPT_CALLBACKS) : {}.freeze
83
95
  end
84
96
 
85
- def all_callbacks
86
- @_callbacks
97
+ def shareable?
98
+ const_defined?(:SHAREABLE) && const_get(:SHAREABLE)
99
+ end
100
+
101
+ def shareable!
102
+ return if shareable?
103
+ const_set(:SHAREABLE, true)
87
104
  end
88
105
 
89
106
  private
90
107
 
91
- RESERVED_WORDS = %i(class defaults options fetch check_required_args check_required_keys)
108
+ def share(value)
109
+ return value unless shareable?
110
+ defined?(Ractor) ? Ractor.make_shareable(value) : value
111
+ end
112
+
113
+ def add_required_keys(*keys)
114
+ combined = required_keys + keys
115
+ class_eval <<~RUBY
116
+ def self.required_keys
117
+ #{combined.inspect}.freeze
118
+ end
119
+ RUBY
120
+ end
121
+
122
+ def add_defaults(defaults_to_add)
123
+ freezer = defaults.dup
124
+ defaults_to_add.each { |k, v| freezer[k] = share(v) }
125
+ remove_const(:OPT_DEFAULTS) if const_defined?(:OPT_DEFAULTS)
126
+ const_set(:OPT_DEFAULTS, freezer.freeze)
127
+ end
128
+
129
+ def add_callback(name, callback)
130
+ if const_defined?(:OPT_CALLBACKS)
131
+ callbacks_for_name = (all_callbacks[name] || []) + [callback]
132
+ callbacks_hash = all_callbacks.merge(name => callbacks_for_name).freeze
133
+ remove_const(:OPT_CALLBACKS)
134
+ const_set(:OPT_CALLBACKS, callbacks_hash)
135
+ else
136
+ const_set(:OPT_CALLBACKS, { name => [ callback ] })
137
+ end
138
+ end
139
+
140
+ def opt_struct_class_constants
141
+ [:OPT_DEFAULTS, :OPT_CALLBACKS]
142
+ end
92
143
 
93
144
  def check_reserved_words(words)
94
145
  Array(words).each do |word|
95
- if RESERVED_WORDS.member?(word)
146
+ if OptStruct::RESERVED_WORDS.member?(word)
96
147
  raise ArgumentError, "Use of reserved word is not permitted: #{word.inspect}"
97
148
  end
98
149
  end
@@ -22,8 +22,8 @@ module OptStruct
22
22
  options
23
23
  expect_arguments
24
24
  ).each do |class_method|
25
- define_method(class_method) do |*args|
26
- @_opt_structs << [[], {}, -> { send(class_method, *args) }]
25
+ define_method(class_method) do |*args, **options|
26
+ @_opt_structs << [[], {}, -> { send(class_method, *args, **options) }]
27
27
  end
28
28
  end
29
29
  end
@@ -1,3 +1,3 @@
1
1
  module OptStruct
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opt_struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Zulauf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-09 00:00:00.000000000 Z
11
+ date: 2021-03-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Struct with support for keyword params and mixin support
14
14
  email:
@@ -43,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
43
  - !ruby/object:Gem::Version
44
44
  version: '0'
45
45
  requirements: []
46
- rubygems_version: 3.0.3
46
+ rubygems_version: 3.1.4
47
47
  signing_key:
48
48
  specification_version: 4
49
49
  summary: The Option Struct