hierarchical_config 0.11 → 0.13
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 +5 -5
- data/.github/workflows/ruby.yml +52 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +68 -0
- data/.ruby-version +1 -0
- data/Gemfile +15 -2
- data/Gemfile.2.4 +19 -0
- data/Gemfile.2.4.lock +117 -0
- data/Gemfile.lock +124 -25
- data/README.md +0 -2
- data/bin/console +3 -3
- data/bin/tapioca +29 -0
- data/hierarchical_config.gemspec +14 -13
- data/lib/hierarchical_config/version.rb +3 -1
- data/lib/hierarchical_config.rb +164 -102
- data/sorbet/config +2 -0
- data/sorbet/rbi/annotations/activesupport.rbi +128 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/gems/activesupport@7.0.4.2.rbi +16155 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
- data/sorbet/rbi/gems/binding_of_caller@1.0.0.rbi +55 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +3426 -0
- data/sorbet/rbi/gems/concurrent-ruby@1.2.2.rbi +11545 -0
- data/sorbet/rbi/gems/debug_inspector@1.1.0.rbi +23 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1083 -0
- data/sorbet/rbi/gems/i18n@1.12.0.rbi +2296 -0
- data/sorbet/rbi/gems/interception@0.5.rbi +138 -0
- data/sorbet/rbi/gems/json@2.6.3.rbi +1541 -0
- data/sorbet/rbi/gems/method_source@1.0.0.rbi +272 -0
- data/sorbet/rbi/gems/minitest@5.17.0.rbi +1457 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
- data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
- data/sorbet/rbi/gems/parser@3.2.1.0.rbi +7252 -0
- data/sorbet/rbi/gems/pry-rescue@1.5.2.rbi +186 -0
- data/sorbet/rbi/gems/pry-stack_explorer@0.6.1.rbi +295 -0
- data/sorbet/rbi/gems/pry@0.14.2.rbi +10081 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +402 -0
- data/sorbet/rbi/gems/rake@13.0.6.rbi +3018 -0
- data/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
- data/sorbet/rbi/gems/regexp_parser@2.7.0.rbi +3580 -0
- data/sorbet/rbi/gems/rexml@3.2.5.rbi +4717 -0
- data/sorbet/rbi/gems/rspec-core@3.12.1.rbi +10845 -0
- data/sorbet/rbi/gems/rspec-expectations@3.12.2.rbi +8100 -0
- data/sorbet/rbi/gems/rspec-mocks@3.12.3.rbi +5299 -0
- data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1611 -0
- data/sorbet/rbi/gems/rspec@3.12.0.rbi +82 -0
- data/sorbet/rbi/gems/rubocop-ast@1.27.0.rbi +6998 -0
- data/sorbet/rbi/gems/rubocop-performance@1.16.0.rbi +3004 -0
- data/sorbet/rbi/gems/rubocop@1.46.0.rbi +54549 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +1239 -0
- data/sorbet/rbi/gems/spoom@1.1.15.rbi +2383 -0
- data/sorbet/rbi/gems/tapioca@0.11.1.rbi +3255 -0
- data/sorbet/rbi/gems/thor@1.2.1.rbi +3956 -0
- data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +5917 -0
- data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +65 -0
- data/sorbet/rbi/gems/unparser@0.6.7.rbi +4524 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +2555 -0
- data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +441 -0
- data/sorbet/rbi/gems/yard@0.9.28.rbi +17841 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- metadata +74 -50
- data/.travis.yml +0 -6
data/lib/hierarchical_config.rb
CHANGED
@@ -1,84 +1,174 @@
|
|
1
|
-
|
1
|
+
# typed: strict
|
2
|
+
|
2
3
|
require 'yaml'
|
3
4
|
require 'erb'
|
4
5
|
require 'set'
|
6
|
+
require 'sorbet-runtime'
|
7
|
+
require 'active_support'
|
8
|
+
require 'active_support/core_ext/hash/keys'
|
5
9
|
|
6
|
-
require
|
10
|
+
require 'hierarchical_config/version'
|
7
11
|
|
8
12
|
module HierarchicalConfig
|
9
13
|
REQUIRED = :REQUIRED
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
14
|
+
T.unsafe(YAML).add_domain_type(nil, 'REQUIRED'){REQUIRED}
|
15
|
+
|
16
|
+
ClassOrModule = T.type_alias{T.any(Class, Module)}
|
17
|
+
|
18
|
+
module ConfigStruct
|
19
|
+
extend T::Sig
|
20
|
+
include Kernel
|
21
|
+
|
22
|
+
sig{returns(T::Hash[Symbol, T.untyped])}
|
23
|
+
def to_hash
|
24
|
+
Hash[self.class.props.keys.map{|key| [key, item_to_hash(send(key))]}] # rubocop:disable Style/HashConversion
|
25
|
+
end
|
26
|
+
|
27
|
+
sig{params(key: T.any(String, Symbol)).returns(T.untyped)}
|
28
|
+
def [](key)
|
29
|
+
send(key)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
sig{params(item: BasicObject).returns(T.any(BasicObject, T::Hash[T.untyped, T.untyped]))}
|
35
|
+
def item_to_hash(item)
|
36
|
+
case item
|
37
|
+
when ConfigStruct
|
38
|
+
item.to_hash
|
39
|
+
when Array
|
40
|
+
item.map{|i| item_to_hash(i)}
|
28
41
|
else
|
29
|
-
|
42
|
+
item
|
30
43
|
end
|
31
44
|
end
|
45
|
+
end
|
46
|
+
|
47
|
+
@@root_index = T.let(0, Integer) # rubocop:disable Style/ClassVars
|
32
48
|
|
33
|
-
|
34
|
-
|
49
|
+
class << self
|
50
|
+
extend T::Sig
|
51
|
+
|
52
|
+
sig{params(value: T.untyped, path: String).returns(T::Array[String])}
|
53
|
+
def detect_errors(value, path)
|
54
|
+
errors = T.let([], T::Array[String])
|
55
|
+
case value
|
56
|
+
when Hash
|
57
|
+
value.each do |key, item|
|
58
|
+
errors += detect_errors(item, "#{path}.#{key}")
|
59
|
+
end
|
60
|
+
when Array
|
61
|
+
value.each_with_index do |item, index|
|
62
|
+
errors += detect_errors(item, "#{path}[#{index}]")
|
63
|
+
end
|
64
|
+
when REQUIRED
|
65
|
+
errors << "#{path} is REQUIRED"
|
66
|
+
end
|
67
|
+
errors
|
35
68
|
end
|
36
69
|
|
37
|
-
|
70
|
+
sig{params(current_item: Object, name: String, parent_class: ClassOrModule).returns(T.any(Class, T::Types::Base))}
|
71
|
+
def build_types(current_item, name, parent_class)
|
72
|
+
case current_item
|
73
|
+
when Hash
|
74
|
+
new_type_name = ActiveSupport::Inflector.camelize(ActiveSupport::Inflector.underscore(name))
|
75
|
+
|
76
|
+
return Hash if current_item.keys.to_a.any?{|k| k =~ /^[0-9]/ || k =~ /[- ]/}
|
38
77
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
78
|
+
new_type =
|
79
|
+
if parent_class.const_defined?(new_type_name, false)
|
80
|
+
parent_class.const_get(new_type_name, false)
|
81
|
+
else
|
82
|
+
parent_class.const_set(new_type_name, Class.new(T::Struct).tap{|c| c.include ConfigStruct})
|
83
|
+
end
|
84
|
+
|
85
|
+
current_item.each do |key, value|
|
86
|
+
next if new_type.props.key?(key.to_sym)
|
87
|
+
|
88
|
+
new_type.const key.to_sym, build_types(value, key, new_type)
|
89
|
+
new_type.send(:define_method, "#{key}?") do
|
90
|
+
!!send(key)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
new_type
|
95
|
+
when Array
|
96
|
+
types = current_item.each_with_index.map do |item, index|
|
97
|
+
build_types(item, "#{name}_#{index}", parent_class)
|
98
|
+
end
|
99
|
+
case types.size
|
100
|
+
when 0
|
101
|
+
T.untyped
|
102
|
+
when 1
|
103
|
+
T::Array[types.first]
|
104
|
+
else
|
105
|
+
T::Array[T.unsafe(T).any(*types)]
|
106
|
+
end
|
107
|
+
else
|
108
|
+
current_item.class
|
44
109
|
end
|
45
110
|
end
|
46
111
|
|
47
|
-
|
112
|
+
sig{params(current_item: Object, name: String, parent_class: ClassOrModule).returns(T.untyped)}
|
113
|
+
def build_config(current_item, name, parent_class)
|
114
|
+
case current_item
|
115
|
+
when Hash
|
116
|
+
return current_item.symbolize_keys if current_item.keys.to_a.any?{|k| k =~ /^[0-9]/ || k =~ /[- ]/}
|
48
117
|
|
49
|
-
|
50
|
-
|
118
|
+
current_type = parent_class.const_get(ActiveSupport::Inflector.camelize(name))
|
119
|
+
current_type.new(Hash[current_item.map{|key, value| [key.to_sym, build_config(value, key, current_type)]}]) # rubocop:disable Style/HashConversion
|
51
120
|
when Array
|
52
|
-
|
53
|
-
|
54
|
-
|
121
|
+
current_item.each_with_index.map do |item, index|
|
122
|
+
build_config(item, "#{name}_#{index}", parent_class)
|
123
|
+
end.freeze
|
55
124
|
else
|
56
|
-
|
125
|
+
current_item.freeze
|
57
126
|
end
|
58
127
|
end
|
59
|
-
end
|
60
128
|
|
61
|
-
|
62
|
-
def
|
129
|
+
sig{returns(Class)}
|
130
|
+
def build_new_root
|
131
|
+
@@root_index += 1 # rubocop:disable Style/ClassVars
|
132
|
+
const_set("ConfigRoot#{@@root_index}", Class.new)
|
133
|
+
end
|
134
|
+
|
135
|
+
sig do
|
136
|
+
params(
|
137
|
+
name: String,
|
138
|
+
dir: String,
|
139
|
+
environment: String,
|
140
|
+
preprocess_with: T.nilable(Symbol),
|
141
|
+
root_class: ClassOrModule,
|
142
|
+
).returns(T::Struct)
|
143
|
+
end
|
144
|
+
def load_config(name, dir, environment, preprocess_with = :erb, root_class = build_new_root)
|
63
145
|
primary_config_file = "#{dir}/#{name}.yml"
|
64
146
|
overrides_config_file = "#{dir}/#{name}-overrides.yml"
|
65
147
|
|
66
|
-
config_hash = load_hash_for_env(
|
148
|
+
config_hash = load_hash_for_env(primary_config_file, environment, preprocess_with)
|
67
149
|
|
68
|
-
if File.
|
69
|
-
overrides_config_hash = load_hash_for_env(
|
70
|
-
config_hash = deep_merge(
|
150
|
+
if File.exist?(overrides_config_file)
|
151
|
+
overrides_config_hash = load_hash_for_env(overrides_config_file, environment, preprocess_with)
|
152
|
+
config_hash = deep_merge(config_hash, overrides_config_hash)
|
71
153
|
end
|
72
154
|
|
73
|
-
|
155
|
+
errors = detect_errors(config_hash, name)
|
156
|
+
raise errors.map{|error| "#{error} for #{environment}"}.inspect unless errors.empty?
|
74
157
|
|
75
|
-
|
158
|
+
build_types(config_hash, name, root_class)
|
76
159
|
|
77
|
-
config_hash
|
160
|
+
build_config(config_hash, name, root_class)
|
78
161
|
end
|
79
162
|
|
80
|
-
|
81
|
-
|
163
|
+
sig do
|
164
|
+
params(
|
165
|
+
file: String,
|
166
|
+
environment: String,
|
167
|
+
preprocess_with: T.nilable(Symbol),
|
168
|
+
).returns(T::Hash[String, BasicObject])
|
169
|
+
end
|
170
|
+
def load_hash_for_env(file, environment, preprocess_with)
|
171
|
+
file_contents = File.read(file)
|
82
172
|
yaml_contents = case preprocess_with
|
83
173
|
when :erb
|
84
174
|
ERB.new(file_contents).result
|
@@ -87,103 +177,75 @@ module HierarchicalConfig
|
|
87
177
|
else
|
88
178
|
raise "Unknown preprocessor <#{preprocess_with}>"
|
89
179
|
end
|
90
|
-
yaml_config = YAML
|
180
|
+
yaml_config = YAML.safe_load(yaml_contents)
|
91
181
|
|
92
182
|
ordered_stanza_labels = []
|
93
183
|
ordered_stanza_labels << 'defaults' if yaml_config.key? 'defaults'
|
94
|
-
ordered_stanza_labels += yaml_config.keys.grep(/^defaults\[.*#{environment}/).sort_by{
|
184
|
+
ordered_stanza_labels += yaml_config.keys.grep(/^defaults\[.*#{environment}/).sort_by{|a| a.count(',')}
|
95
185
|
ordered_stanza_labels << environment if yaml_config.key? environment
|
96
186
|
|
97
187
|
config = deep_merge_hashes_in_keys(ordered_stanza_labels, yaml_config)
|
98
188
|
|
99
189
|
env_config_labels = []
|
100
190
|
env_config_labels << 'env_vars' if yaml_config.key? 'env_vars'
|
101
|
-
env_config_labels += yaml_config.keys.grep(/^env_vars\[.*#{environment}/).sort_by{
|
191
|
+
env_config_labels += yaml_config.keys.grep(/^env_vars\[.*#{environment}/).sort_by{|a| a.count(',')}
|
102
192
|
|
103
193
|
env_config = deep_merge_hashes_in_keys(env_config_labels, yaml_config)
|
104
194
|
env_config = fill_in_env_vars(env_config)
|
105
195
|
|
106
196
|
deep_merge(config, env_config)
|
107
|
-
|
108
197
|
rescue StandardError => e
|
109
198
|
raise <<-ERROR
|
110
199
|
Error loading config from file #{file}.
|
111
|
-
#{
|
112
|
-
#{
|
200
|
+
#{$ERROR_INFO.inspect}
|
201
|
+
#{$ERROR_POSITION}
|
202
|
+
#{e}
|
113
203
|
ERROR
|
114
204
|
end
|
115
205
|
|
116
206
|
private
|
117
207
|
|
208
|
+
sig do
|
209
|
+
params(keys: T::Array[String],
|
210
|
+
root_hash: T::Hash[String,
|
211
|
+
T::Hash[String, T.untyped]]).returns(T::Hash[T.untyped, T.untyped])
|
212
|
+
end
|
118
213
|
def deep_merge_hashes_in_keys(keys, root_hash)
|
119
214
|
keys.inject({}) do |acc, label|
|
120
|
-
deep_merge(
|
215
|
+
deep_merge(acc, T.must(root_hash[label]))
|
121
216
|
end
|
122
217
|
end
|
123
218
|
|
219
|
+
sig{params(hash: T::Hash[T.untyped, T.untyped]).returns(T::Hash[T.untyped, T.untyped])}
|
124
220
|
def fill_in_env_vars(hash)
|
125
221
|
r = {}
|
126
|
-
hash.each do |key,value|
|
222
|
+
hash.each do |key, value|
|
127
223
|
if value.is_a? Hash
|
128
224
|
leaf_hash = fill_in_env_vars(value)
|
129
|
-
r[key]=leaf_hash unless leaf_hash.keys.empty?
|
225
|
+
r[key] = leaf_hash unless leaf_hash.keys.empty?
|
130
226
|
elsif !value.nil? && ENV.key?(value)
|
131
|
-
r[key]=ENV
|
227
|
+
r[key] = ENV.fetch(value, nil)
|
132
228
|
end
|
133
229
|
end
|
134
230
|
r
|
135
231
|
end
|
136
232
|
|
137
233
|
# merges two hashes with nested hashes if present
|
138
|
-
|
234
|
+
sig do
|
235
|
+
params(hash1: T::Hash[T.untyped, T.untyped],
|
236
|
+
hash2: T::Hash[T.untyped, T.untyped]).returns(T::Hash[T.untyped, T.untyped])
|
237
|
+
end
|
238
|
+
def deep_merge(hash1, hash2)
|
139
239
|
hash1 = hash1.dup
|
140
|
-
(
|
141
|
-
if hash1.key?(
|
142
|
-
hash1[key].is_a?(
|
143
|
-
|
144
|
-
elsif hash2.key?(
|
240
|
+
(hash1.keys + hash2.keys).each do |key|
|
241
|
+
if hash1.key?(key) && hash2.key?(key) &&
|
242
|
+
hash1[key].is_a?(Hash) && hash2[key].is_a?(Hash)
|
243
|
+
hash1[key] = deep_merge(hash1[key], hash2[key])
|
244
|
+
elsif hash2.key?(key)
|
145
245
|
hash1[key] = hash2[key]
|
146
246
|
end
|
147
247
|
end
|
148
248
|
hash1
|
149
249
|
end
|
150
|
-
|
151
|
-
# Mutator method that does three things:
|
152
|
-
# * checks if any of the keys were required and not set. Upon finding
|
153
|
-
# it adds key to the error set
|
154
|
-
# * recursively sets open structs for deep hashes
|
155
|
-
# * recursively freezes config objects
|
156
|
-
def lock_down_and_ostructify!( _hash, path, environment)
|
157
|
-
hash = Hash[_hash.map{|k,v|[k.to_s, v]}] #stringify keys
|
158
|
-
errors = []
|
159
|
-
hash.each do | key, value |
|
160
|
-
hash[key], child_errors = lock_down_and_ostructify_item!(value, path + '.' + key, environment)
|
161
|
-
errors += child_errors
|
162
|
-
end
|
163
|
-
return OpenStruct.new(hash).freeze, errors
|
164
|
-
end
|
165
|
-
|
166
|
-
def lock_down_and_ostructify_item!(value, path, environment)
|
167
|
-
errors = []
|
168
|
-
return_value = case value
|
169
|
-
when Hash
|
170
|
-
child_hash, child_errors = lock_down_and_ostructify!( value, path, environment )
|
171
|
-
errors += child_errors
|
172
|
-
child_hash
|
173
|
-
when Array
|
174
|
-
value.each_with_index.map do |item, index|
|
175
|
-
child_item, child_errors = lock_down_and_ostructify_item!( item, "#{path}[#{index}]", environment )
|
176
|
-
errors += child_errors
|
177
|
-
child_item
|
178
|
-
end.freeze
|
179
|
-
when REQUIRED
|
180
|
-
errors << "#{path} is REQUIRED for #{environment}"
|
181
|
-
nil
|
182
|
-
else
|
183
|
-
value.freeze
|
184
|
-
end
|
185
|
-
|
186
|
-
return return_value, errors
|
187
|
-
end
|
188
250
|
end
|
189
251
|
end
|
data/sorbet/config
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
# DO NOT EDIT MANUALLY
|
4
|
+
# This file was pulled from a central RBI files repository.
|
5
|
+
# Please run `bin/tapioca annotations` to update it.
|
6
|
+
|
7
|
+
module ActiveSupport::Testing::Declarative
|
8
|
+
sig { params(name: String, block: T.proc.bind(T.untyped).void).void }
|
9
|
+
def test(name, &block); end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ActiveSupport::EnvironmentInquirer
|
13
|
+
sig { returns(T::Boolean) }
|
14
|
+
def development?; end
|
15
|
+
|
16
|
+
sig { returns(T::Boolean) }
|
17
|
+
def production?; end
|
18
|
+
|
19
|
+
sig { returns(T::Boolean) }
|
20
|
+
def test?; end
|
21
|
+
|
22
|
+
# @method_missing: delegated to String through ActiveSupport::StringInquirer
|
23
|
+
sig { returns(T::Boolean) }
|
24
|
+
def staging?; end
|
25
|
+
end
|
26
|
+
|
27
|
+
module ActiveSupport::Testing::SetupAndTeardown::ClassMethods
|
28
|
+
sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.untyped).void)).void }
|
29
|
+
def setup(*args, &block); end
|
30
|
+
|
31
|
+
sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.untyped).void)).void }
|
32
|
+
def teardown(*args, &block); end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ActiveSupport::TestCase
|
36
|
+
sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.attached_class).void)).void }
|
37
|
+
def self.setup(*args, &block); end
|
38
|
+
|
39
|
+
sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.attached_class).void)).void }
|
40
|
+
def self.teardown(*args, &block); end
|
41
|
+
|
42
|
+
sig { params(name: String, block: T.proc.bind(T.attached_class).void).void }
|
43
|
+
def self.test(name, &block); end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Object
|
47
|
+
sig { returns(T::Boolean) }
|
48
|
+
def blank?; end
|
49
|
+
|
50
|
+
sig { returns(T::Boolean) }
|
51
|
+
def present?; end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Hash
|
55
|
+
sig { returns(T::Boolean) }
|
56
|
+
def extractable_options?; end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Array
|
60
|
+
sig { params(position: Integer).returns(T.self_type) }
|
61
|
+
def from(position); end
|
62
|
+
|
63
|
+
sig { params(position: Integer).returns(T.self_type) }
|
64
|
+
def to(position); end
|
65
|
+
|
66
|
+
sig { params(elements: T.untyped).returns(T::Array[T.untyped]) }
|
67
|
+
def including(*elements); end
|
68
|
+
|
69
|
+
sig { params(elements: T.untyped).returns(T.self_type) }
|
70
|
+
def excluding(*elements); end
|
71
|
+
|
72
|
+
sig { params(elements: T.untyped).returns(T.self_type) }
|
73
|
+
def without(*elements); end
|
74
|
+
|
75
|
+
sig { returns(T.nilable(Elem)) }
|
76
|
+
def second; end
|
77
|
+
|
78
|
+
sig { returns(T.nilable(Elem)) }
|
79
|
+
def third; end
|
80
|
+
|
81
|
+
sig { returns(T.nilable(Elem)) }
|
82
|
+
def fourth; end
|
83
|
+
|
84
|
+
sig { returns(T.nilable(Elem)) }
|
85
|
+
def fifth; end
|
86
|
+
|
87
|
+
sig { returns(T.nilable(Elem)) }
|
88
|
+
def forty_two; end
|
89
|
+
|
90
|
+
sig { returns(T.nilable(Elem)) }
|
91
|
+
def third_to_last; end
|
92
|
+
|
93
|
+
sig { returns(T.nilable(Elem)) }
|
94
|
+
def second_to_last; end
|
95
|
+
|
96
|
+
sig { params(options: T::Hash[T.untyped, T.untyped]).returns(String) }
|
97
|
+
def to_sentence(options = {}); end
|
98
|
+
|
99
|
+
sig { params(format: Symbol).returns(String) }
|
100
|
+
def to_fs(format = :default); end
|
101
|
+
|
102
|
+
sig { params(format: Symbol).returns(String) }
|
103
|
+
def to_formatted_s(format = :default); end
|
104
|
+
|
105
|
+
sig { returns(String) }
|
106
|
+
def to_xml; end
|
107
|
+
|
108
|
+
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
109
|
+
def extract_options!; end
|
110
|
+
|
111
|
+
sig { type_parameters(:FillType).params(number: Integer, fill_with: T.type_parameter(:FillType), block: T.nilable(T.proc.params(group: T::Array[T.any(Elem, T.type_parameter(:FillType))]).void)).returns(T::Array[T::Array[T.any(Elem, T.type_parameter(:FillType))]]) }
|
112
|
+
def in_groups(number, fill_with = T.unsafe(nil), &block); end
|
113
|
+
|
114
|
+
sig { type_parameters(:FillType).params(number: Integer, fill_with: T.type_parameter(:FillType), block: T.nilable(T.proc.params(group: T::Array[T.any(Elem, T.type_parameter(:FillType))]).void)).returns(T::Array[T::Array[T.any(Elem, T.type_parameter(:FillType))]]) }
|
115
|
+
def in_groups_of(number, fill_with = T.unsafe(nil), &block); end
|
116
|
+
|
117
|
+
sig { params(value: T.untyped, block: T.nilable(T.proc.params(element: Elem).returns(T.untyped))).returns(T::Array[T::Array[Elem]]) }
|
118
|
+
def split(value = nil, &block); end
|
119
|
+
|
120
|
+
sig { params(object: T.untyped).returns(T::Array[T.untyped]) }
|
121
|
+
def self.wrap(object); end
|
122
|
+
|
123
|
+
sig { returns(T.untyped) }
|
124
|
+
def extract!; end
|
125
|
+
|
126
|
+
sig { returns(ActiveSupport::ArrayInquirer) }
|
127
|
+
def inquiry; end
|
128
|
+
end
|