everythingrb 0.6.1 → 0.8.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.
data/README.md CHANGED
@@ -4,18 +4,33 @@
4
4
  ![Ruby Version](https://img.shields.io/badge/ruby-3.3.7-ruby)
5
5
  [![Tests](https://github.com/itsthedevman/everythingrb/actions/workflows/main.yml/badge.svg)](https://github.com/everythingrb/sortsmith/actions/workflows/main.yml)
6
6
 
7
- Super handy extensions to Ruby core classes that make your code more expressive, readable, and fun to write.
7
+ Super handy extensions to Ruby core classes that make your code more expressive, readable, and fun to write. Stop writing boilerplate and start writing code that *actually matters*!
8
+
9
+ ## Express Your Intent, Not Your Logic
10
+
11
+ We've all been there - writing the same tedious patterns over and over:
8
12
 
9
13
  ```ruby
14
+ # BEFORE
10
15
  users = [{ name: "Alice", role: "admin" }, { name: "Bob", role: "user" }]
16
+ admin_users = users.select { |u| u[:role] == "admin" }
17
+ admin_names = admin_users.map { |u| u[:name] }
18
+ result = admin_names.join(", ")
19
+ # => "Alice"
20
+ ```
11
21
 
12
- # Instead of this:
13
- admin_names = users.select { |u| u[:role] == "admin" }.map { |u| u[:name] }.join(", ")
22
+ With EverythingRB, you can write code that actually says what you mean:
14
23
 
15
- # Write this:
24
+ ```ruby
25
+ # AFTER
16
26
  users.join_map(", ") { |u| u[:name] if u[:role] == "admin" }
27
+ # => "Alice"
17
28
  ```
18
29
 
30
+ *Methods used: [`join_map`](https://itsthedevman.com/docs/everythingrb/Array.html#join_map-instance_method)*
31
+
32
+ Because life's too short to write all that boilerplate!
33
+
19
34
  ## Installation
20
35
 
21
36
  ```ruby
@@ -47,7 +62,7 @@ config.server.port # => 443
47
62
 
48
63
  ### Cherry-Pick Extensions
49
64
 
50
- If you only need specific extensions, you can load just what you want:
65
+ If you only need specific extensions (or you're a minimalist at heart):
51
66
 
52
67
  ```ruby
53
68
  require "everythingrb/prelude" # Required base module
@@ -64,111 +79,486 @@ require "everythingrb/string" # Just String extensions
64
79
 
65
80
  Available modules:
66
81
  - `array`: Array extensions (join_map, key_map, etc.)
67
- - `data`: Data extensions (to_deep_h)
82
+ - `boolean`: Boolean extensions (in_quotes, with_quotes)
83
+ - `data`: Data extensions (to_deep_h, in_quotes)
84
+ - `date`: Date and DateTime extensions (in_quotes)
68
85
  - `enumerable`: Enumerable extensions (join_map, group_by_key)
69
- - `hash`: Hash extensions (to_ostruct, deep_freeze, etc.)
86
+ - `hash`: Hash extensions (to_ostruct, transform_values(with_key: true), etc.)
87
+ - `kernel`: Kernel extensions (morph alias for then)
70
88
  - `module`: Extensions like attr_predicate
89
+ - `nil`: NilClass extensions (in_quotes)
90
+ - `numeric`: Numeric extensions (in_quotes)
71
91
  - `ostruct`: OpenStruct extensions (map, join_map, etc.)
72
- - `string`: String extensions (to_h, to_ostruct, etc.)
73
- - `struct`: Struct extensions (to_deep_h)
92
+ - `range`: Range extensions (in_quotes)
93
+ - `regexp`: Regexp extensions (in_quotes)
94
+ - `string`: String extensions (to_h, to_ostruct, to_camelcase, etc.)
95
+ - `struct`: Struct extensions (to_deep_h, in_quotes)
74
96
  - `symbol`: Symbol extensions (with_quotes)
97
+ - `time`: Time extensions (in_quotes)
75
98
 
76
99
  ## What's Included
77
100
 
78
- EverythingRB extends Ruby's core classes with intuitive methods that simplify common patterns.
79
-
80
101
  ### Data Structure Conversions
81
102
 
103
+ Stop writing complicated parsers and nested transformations:
104
+
105
+ ```ruby
106
+ # BEFORE
107
+ json_string = '{"user":{"name":"Alice","roles":["admin"]}}'
108
+ parsed = JSON.parse(json_string)
109
+ result = OpenStruct.new(
110
+ user: OpenStruct.new(
111
+ name: parsed["user"]["name"],
112
+ roles: parsed["user"]["roles"]
113
+ )
114
+ )
115
+ result.user.name # => "Alice"
116
+ ```
117
+
118
+ With EverythingRB, it's one elegant step:
119
+
120
+ ```ruby
121
+ # AFTER
122
+ '{"user":{"name":"Alice","roles":["admin"]}}'.to_ostruct.user.name # => "Alice"
123
+ ```
124
+
125
+ *Methods used: [`to_ostruct`](https://itsthedevman.com/docs/everythingrb/String.html#to_ostruct-instance_method)*
126
+
82
127
  Convert between data structures with ease:
83
128
 
84
129
  ```ruby
85
- # Convert hashes to more convenient structures
86
- config = { server: { host: "example.com", port: 443 } }.to_ostruct
130
+ # BEFORE
131
+ config_hash = { server: { host: "example.com", port: 443 } }
132
+ ServerConfig = Struct.new(:host, :port)
133
+ Config = Struct.new(:server)
134
+ config = Config.new(ServerConfig.new(config_hash[:server][:host], config_hash[:server][:port]))
135
+ ```
136
+
137
+ ```ruby
138
+ # AFTER
139
+ config = { server: { host: "example.com", port: 443 } }.to_struct
87
140
  config.server.host # => "example.com"
141
+ ```
142
+
143
+ *Methods used: [`to_struct`](https://itsthedevman.com/docs/everythingrb/Hash.html#to_struct-instance_method)*
88
144
 
89
- # Parse JSON directly to your preferred structure
90
- '{"user":{"name":"Alice"}}'.to_istruct.user.name # => "Alice"
145
+ Deep conversion to plain hashes is just as easy:
146
+
147
+ ```ruby
148
+ # BEFORE
149
+ data = OpenStruct.new(user: Data.define(:name).new(name: "Bob"))
150
+ result = {
151
+ user: {
152
+ name: data.user.name
153
+ }
154
+ }
155
+ ```
156
+
157
+ ```ruby
158
+ # AFTER
159
+ data = OpenStruct.new(user: Data.define(:name).new(name: "Bob"))
160
+ data.to_deep_h # => {user: {name: "Bob"}}
91
161
  ```
92
162
 
93
- **Extensions:** `to_struct`, `to_ostruct`, `to_istruct`, `to_h`, `to_deep_h`
163
+ *Methods used: [`to_deep_h`](https://itsthedevman.com/docs/everythingrb/OpenStruct.html#to_deep_h-instance_method)*
164
+
165
+ **Extensions:** [`to_struct`](https://itsthedevman.com/docs/everythingrb/Hash.html#to_struct-instance_method), [`to_ostruct`](https://itsthedevman.com/docs/everythingrb/Hash.html#to_ostruct-instance_method), [`to_istruct`](https://itsthedevman.com/docs/everythingrb/Hash.html#to_istruct-instance_method), [`to_h`](https://itsthedevman.com/docs/everythingrb/String.html#to_h-instance_method), [`to_deep_h`](https://itsthedevman.com/docs/everythingrb/Hash.html#to_deep_h-instance_method)
94
166
 
95
167
  ### Collection Processing
96
168
 
97
- Extract and transform data elegantly:
169
+ Extract and transform data with elegant, expressive code:
98
170
 
99
171
  ```ruby
100
- # Extract data from arrays of hashes in one step
172
+ # BEFORE
101
173
  users = [{ name: "Alice", roles: ["admin"] }, { name: "Bob", roles: ["user"] }]
174
+ names = users.map { |user| user[:name] }
175
+ # => ["Alice", "Bob"]
176
+ ```
177
+
178
+ ```ruby
179
+ # AFTER
102
180
  users.key_map(:name) # => ["Alice", "Bob"]
103
- users.dig_map(:roles, 0) # => ["admin", "user"]
181
+ ```
182
+
183
+ *Methods used: [`key_map`](https://itsthedevman.com/docs/everythingrb/Array.html#key_map-instance_method)*
184
+
185
+ Simplify nested data extraction:
186
+
187
+ ```ruby
188
+ # BEFORE
189
+ users = [
190
+ {user: {profile: {name: "Alice"}}},
191
+ {user: {profile: {name: "Bob"}}}
192
+ ]
193
+ names = users.map { |u| u.dig(:user, :profile, :name) }
194
+ # => ["Alice", "Bob"]
195
+ ```
196
+
197
+ ```ruby
198
+ # AFTER
199
+ users.dig_map(:user, :profile, :name) # => ["Alice", "Bob"]
200
+ ```
201
+
202
+ *Methods used: [`dig_map`](https://itsthedevman.com/docs/everythingrb/Array.html#dig_map-instance_method)*
203
+
204
+ Combine filter, map, and join operations in one step:
205
+
206
+ ```ruby
207
+ # BEFORE
208
+ data = [1, 2, nil, 3, 4]
209
+ result = data.compact.filter_map { |n| "Item #{n}" if n.odd? }.join(" | ")
210
+ # => "Item 1 | Item 3"
211
+ ```
104
212
 
105
- # Filter, map, and join in a single operation
213
+ ```ruby
214
+ # AFTER
106
215
  [1, 2, nil, 3, 4].join_map(" | ") { |n| "Item #{n}" if n&.odd? }
107
216
  # => "Item 1 | Item 3"
217
+ ```
108
218
 
109
- # With ActiveSupport loaded, join arrays in natural language with "or"
110
- ["red", "blue", "green"].to_or_sentence # => "red, blue, or green"
219
+ *Methods used: [`join_map`](https://itsthedevman.com/docs/everythingrb/Array.html#join_map-instance_method)*
220
+
221
+ Group elements with natural syntax:
222
+
223
+ ```ruby
224
+ # BEFORE
225
+ users = [
226
+ {name: "Alice", department: {name: "Engineering"}},
227
+ {name: "Bob", department: {name: "Sales"}},
228
+ {name: "Charlie", department: {name: "Engineering"}}
229
+ ]
230
+ users.group_by { |user| user[:department][:name] }
231
+ # => {"Engineering"=>[{name: "Alice",...}, {name: "Charlie",...}], "Sales"=>[{name: "Bob",...}]}
111
232
  ```
112
233
 
113
- **Extensions:** `join_map`, `key_map`, `dig_map`, `to_or_sentence`, `group_by_key`
234
+ ```ruby
235
+ # AFTER
236
+ users.group_by_key(:department, :name)
237
+ # => {"Engineering"=>[{name: "Alice",...}, {name: "Charlie",...}], "Sales"=>[{name: "Bob",...}]}
238
+ ```
114
239
 
115
- ### Object Protection
240
+ *Methods used: [`group_by_key`](https://itsthedevman.com/docs/everythingrb/Enumerable.html#group_by_key-instance_method)*
116
241
 
117
- Prevent unwanted modifications with a single call:
242
+ Create natural language lists:
118
243
 
119
244
  ```ruby
120
- config = {
121
- api: {
122
- key: "secret",
123
- endpoints: ["v1", "v2"]
124
- }
125
- }.deep_freeze
245
+ # BEFORE
246
+ options = ["red", "blue", "green"]
247
+ # The default to_sentence uses "and"
248
+ options.to_sentence # => "red, blue, and green"
249
+
250
+ # Need "or" instead? Time for string surgery
251
+ if options.size <= 2
252
+ options.to_sentence(words_connector: " or ")
253
+ else
254
+ # Replace the last "and" with "or" - careful with i18n!
255
+ options.to_sentence.sub(/,?\s+and\s+/, ", or ")
256
+ end
257
+ # => "red, blue, or green"
258
+ ```
126
259
 
127
- # Everything is frozen!
128
- config.frozen? # => true
129
- config[:api][:endpoints][0].frozen? # => true
260
+ ```ruby
261
+ # AFTER
262
+ ["red", "blue", "green"].to_or_sentence # => "red, blue, or green"
130
263
  ```
131
264
 
132
- **Extensions:** `deep_freeze`
265
+ *Methods used: [`to_or_sentence`](https://itsthedevman.com/docs/everythingrb/Array.html#to_or_sentence-instance_method)*
266
+
267
+ **Extensions:** [`join_map`](https://itsthedevman.com/docs/everythingrb/Array.html#join_map-instance_method), [`key_map`](https://itsthedevman.com/docs/everythingrb/Array.html#key_map-instance_method), [`dig_map`](https://itsthedevman.com/docs/everythingrb/Array.html#dig_map-instance_method), [`to_or_sentence`](https://itsthedevman.com/docs/everythingrb/Array.html#to_or_sentence-instance_method), [`group_by_key`](https://itsthedevman.com/docs/everythingrb/Enumerable.html#group_by_key-instance_method)
133
268
 
134
269
  ### Hash Convenience
135
270
 
136
271
  Work with hashes more intuitively:
137
272
 
138
273
  ```ruby
139
- # Create deeply nested structures without initialization
140
- stats = Hash.new_nested_hash
274
+ # BEFORE
275
+ stats = {}
276
+ stats[:server] ||= {}
277
+ stats[:server][:region] ||= {}
278
+ stats[:server][:region][:us_east] ||= {}
279
+ stats[:server][:region][:us_east][:errors] ||= []
141
280
  stats[:server][:region][:us_east][:errors] << "Connection timeout"
281
+ ```
282
+
283
+ ```ruby
284
+ # AFTER
285
+ stats = Hash.new_nested_hash(depth: 3)
286
+ (stats[:server][:region][:us_east][:errors] ||= []) << "Connection timeout"
142
287
  # No need to initialize each level first!
288
+ ```
289
+
290
+ *Methods used: [`new_nested_hash`](https://itsthedevman.com/docs/everythingrb/Hash.html#new_nested_hash-class_method)*
291
+
292
+ Transform values with access to their keys:
143
293
 
144
- # Transform values with access to keys
294
+ ```ruby
295
+ # BEFORE
296
+ users = {alice: {name: "Alice"}, bob: {name: "Bob"}}
297
+ result = {}
298
+ users.each do |key, value|
299
+ result[key] = "User #{key}: #{value[:name]}"
300
+ end
301
+ # => {alice: "User alice: Alice", bob: "User bob: Bob"}
302
+ ```
303
+
304
+ ```ruby
305
+ # AFTER
145
306
  users.transform_values(with_key: true) { |v, k| "User #{k}: #{v[:name]}" }
307
+ # => {alice: "User alice: Alice", bob: "User bob: Bob"}
308
+ ```
309
+
310
+ *Methods used: [`transform_values(with_key: true)`](https://itsthedevman.com/docs/everythingrb/Hash.html#transform_values-instance_method)*
311
+
312
+ Find values based on conditions:
313
+
314
+ ```ruby
315
+ # BEFORE
316
+ users = {
317
+ alice: {name: "Alice", role: "admin"},
318
+ bob: {name: "Bob", role: "user"},
319
+ charlie: {name: "Charlie", role: "admin"}
320
+ }
321
+ admins = users.select { |_k, v| v[:role] == "admin" }.values
322
+ # => [{name: "Alice", role: "admin"}, {name: "Charlie", role: "admin"}]
323
+ ```
324
+
325
+ ```ruby
326
+ # AFTER
327
+ users.values_where { |_k, v| v[:role] == "admin" }
328
+ # => [{name: "Alice", role: "admin"}, {name: "Charlie", role: "admin"}]
329
+ ```
330
+
331
+ *Methods used: [`values_where`](https://itsthedevman.com/docs/everythingrb/Hash.html#values_where-instance_method)*
332
+
333
+ Just want the first match? Even simpler:
334
+
335
+ ```ruby
336
+ # BEFORE
337
+ users.find { |_k, v| v[:role] == "admin" }&.last
338
+ # => {name: "Alice", role: "admin"}
339
+ ```
340
+
341
+ ```ruby
342
+ # AFTER
343
+ users.value_where { |_k, v| v[:role] == "admin" }
344
+ # => {name: "Alice", role: "admin"}
345
+ ```
346
+
347
+ *Methods used: [`value_where`](https://itsthedevman.com/docs/everythingrb/Hash.html#value_where-instance_method)*
348
+
349
+ Rename keys while preserving order:
146
350
 
147
- # Find values based on conditions
148
- users.values_where { |k, v| v[:role] == "admin" }
351
+ ```ruby
352
+ # BEFORE
353
+ config = {api_key: "secret", timeout: 30}
354
+ new_config = config.each_with_object({}) do |(key, value), hash|
355
+ new_key =
356
+ case key
357
+ when :api_key
358
+ :key
359
+ when :timeout
360
+ :request_timeout
361
+ else
362
+ key
363
+ end
364
+
365
+ hash[new_key] = value
366
+ end
367
+ # => {key: "secret", request_timeout: 30}
368
+ ```
369
+
370
+ ```ruby
371
+ # AFTER
372
+ config = {api_key: "secret", timeout: 30}
373
+ config.rename_keys(api_key: :key, timeout: :request_timeout)
374
+ # => {key: "secret", request_timeout: 30}
375
+ ```
376
+
377
+ *Methods used: [`rename_keys`](https://itsthedevman.com/docs/everythingrb/Hash.html#rename_keys-instance_method)*
378
+
379
+ Filter hash by values:
380
+
381
+ ```ruby
382
+ # BEFORE
383
+ result = {a: 1, b: nil, c: 2}.select { |_k, v| v.is_a?(Integer) && v > 1 }
384
+ # => {c: 2}
149
385
  ```
150
386
 
151
- **Extensions:** `new_nested_hash`, `with_key`, `value_where`, `values_where`
387
+ ```ruby
388
+ # AFTER
389
+ {a: 1, b: nil, c: 2}.select_values { |v| v.is_a?(Integer) && v > 1 }
390
+ # => {c: 2}
391
+ ```
392
+
393
+ *Methods used: [`select_values`](https://itsthedevman.com/docs/everythingrb/Hash.html#select_values-instance_method)*
394
+
395
+ Conditionally merge hashes with clear intent:
396
+
397
+ ```ruby
398
+ # BEFORE
399
+ user_params = {name: "Alice", role: "user"}
400
+ filtered = {verified: true, admin: true}.select { |k, v| v == true && k == :verified }
401
+ user_params.merge(filtered)
402
+ # => {name: "Alice", role: "user", verified: true}
403
+ ```
404
+
405
+ ```ruby
406
+ # AFTER
407
+ user_params = {name: "Alice", role: "user"}
408
+ user_params.merge_if(verified: true, admin: true) { |k, v| v == true && k == :verified }
409
+ # => {name: "Alice", role: "user", verified: true}
410
+ ```
411
+
412
+ *Methods used: [`merge_if`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_if-instance_method)*
413
+
414
+ The nil-filtering pattern we've all written dozens of times:
415
+
416
+ ```ruby
417
+ # BEFORE
418
+ params = {sort: "created_at"}
419
+ filtered = {filter: "active", search: nil}.compact
420
+ params.merge(filtered)
421
+ # => {sort: "created_at", filter: "active"}
422
+ ```
423
+
424
+ ```ruby
425
+ # AFTER
426
+ params = {sort: "created_at"}
427
+ params.merge_compact(filter: "active", search: nil)
428
+ # => {sort: "created_at", filter: "active"}
429
+ ```
430
+
431
+ *Methods used: [`merge_compact`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_compact-instance_method)*
432
+
433
+ **Extensions:** [`new_nested_hash`](https://itsthedevman.com/docs/everythingrb/Hash.html#new_nested_hash-class_method), [`transform_values(with_key: true)`](https://itsthedevman.com/docs/everythingrb/Hash.html#transform_values-instance_method), [`value_where`](https://itsthedevman.com/docs/everythingrb/Hash.html#value_where-instance_method), [`values_where`](https://itsthedevman.com/docs/everythingrb/Hash.html#values_where-instance_method), [`rename_key`](https://itsthedevman.com/docs/everythingrb/Hash.html#rename_key-instance_method), [`rename_keys`](https://itsthedevman.com/docs/everythingrb/Hash.html#rename_keys-instance_method), [`select_values`](https://itsthedevman.com/docs/everythingrb/Hash.html#select_values-instance_method), [`reject_values`](https://itsthedevman.com/docs/everythingrb/Hash.html#reject_values-instance_method), [`merge_if`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_if-instance_method), [`merge_if!`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_if%21-instance_method), [`merge_if_values`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_if_values-instance_method), [`merge_if_values!`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_if_values%21-instance_method), [`merge_compact`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_compact-instance_method), [`merge_compact!`](https://itsthedevman.com/docs/everythingrb/Hash.html#merge_compact%21-instance_method)
152
434
 
153
435
  ### Array Cleaning
154
436
 
155
437
  Clean up array boundaries while preserving internal structure:
156
438
 
157
439
  ```ruby
158
- # Remove nil values from the beginning/end
440
+ # BEFORE
441
+ data = [nil, nil, 1, nil, 2, nil, nil]
442
+ data.drop_while(&:nil?).reverse.drop_while(&:nil?).reverse
443
+ # => [1, nil, 2]
444
+ ```
445
+
446
+ ```ruby
447
+ # AFTER
159
448
  [nil, nil, 1, nil, 2, nil, nil].trim_nils # => [1, nil, 2]
449
+ ```
160
450
 
161
- # With ActiveSupport, remove blank values
451
+ *Methods used: [`trim_nils`](https://itsthedevman.com/docs/everythingrb/Array.html#trim_nils-instance_method)*
452
+
453
+ With ActiveSupport, remove blank values too:
454
+
455
+ ```ruby
456
+ # BEFORE
457
+ data = [nil, "", 1, "", 2, nil, ""]
458
+ data.drop_while(&:blank?).reverse.drop_while(&:blank?).reverse
459
+ # => [1, "", 2]
460
+ ```
461
+
462
+ ```ruby
463
+ # AFTER
162
464
  [nil, "", 1, "", 2, nil, ""].trim_blanks # => [1, "", 2]
163
465
  ```
164
466
 
165
- **Extensions:** `trim_nils`, `compact_prefix`, `compact_suffix`, `trim_blanks` (with ActiveSupport)
467
+ *Methods used: [`trim_blanks`](https://itsthedevman.com/docs/everythingrb/Array.html#trim_blanks-instance_method)*
468
+
469
+ **Extensions:** [`trim_nils`](https://itsthedevman.com/docs/everythingrb/Array.html#trim_nils-instance_method), [`compact_prefix`](https://itsthedevman.com/docs/everythingrb/Array.html#compact_prefix-instance_method), [`compact_suffix`](https://itsthedevman.com/docs/everythingrb/Array.html#compact_suffix-instance_method), [`trim_blanks`](https://itsthedevman.com/docs/everythingrb/Array.html#trim_blanks-instance_method) (with ActiveSupport)
470
+
471
+ ### String Formatting
472
+
473
+ Format strings and other values consistently:
474
+
475
+ ```ruby
476
+ # BEFORE
477
+ def format_value(value)
478
+ case value
479
+ when String
480
+ "\"#{value}\""
481
+ when Symbol
482
+ "\"#{value}\""
483
+ when Numeric
484
+ "\"#{value}\""
485
+ when NilClass
486
+ "\"nil\""
487
+ when Array, Hash
488
+ "\"#{value.inspect}\""
489
+ else
490
+ "\"#{value}\""
491
+ end
492
+ end
493
+
494
+ selection = nil
495
+ message = "You selected #{format_value(selection)}"
496
+ ```
497
+
498
+ ```ruby
499
+ # AFTER
500
+ "hello".in_quotes # => "\"hello\""
501
+ 42.in_quotes # => "\"42\""
502
+ nil.in_quotes # => "\"nil\""
503
+ :symbol.in_quotes # => "\"symbol\""
504
+ [1, 2].in_quotes # => "\"[1, 2]\""
505
+ Time.now.in_quotes # => "\"2025-05-04 12:34:56 +0000\""
506
+
507
+ message = "You selected #{selection.in_quotes}"
508
+ ```
509
+
510
+ *Methods used: [`in_quotes`](https://itsthedevman.com/docs/everythingrb/Everythingrb/InspectQuotable.html#in_quotes-instance_method), [`with_quotes`](https://itsthedevman.com/docs/everythingrb/Everythingrb/InspectQuotable.html#with_quotes-instance_method)*
511
+
512
+ Convert strings to camelCase with ease:
513
+
514
+ ```ruby
515
+ # BEFORE
516
+ name = "user_profile_settings"
517
+ pascal_case = name.gsub(/[-_\s]+([a-z])/i) { $1.upcase }.gsub(/[-_\s]/, '')
518
+ pascal_case[0].upcase!
519
+ pascal_case
520
+ # => "UserProfileSettings"
521
+
522
+ camel_case = name.gsub(/[-_\s]+([a-z])/i) { $1.upcase }.gsub(/[-_\s]/, '')
523
+ camel_case[0].downcase!
524
+ camel_case
525
+ # => "userProfileSettings"
526
+ ```
527
+
528
+ ```ruby
529
+ # AFTER
530
+ "user_profile_settings".to_camelcase # => "UserProfileSettings"
531
+ "user_profile_settings".to_camelcase(:lower) # => "userProfileSettings"
532
+
533
+ # Handles all kinds of input consistently
534
+ "please-WAIT while_loading...".to_camelcase # => "PleaseWaitWhileLoading"
535
+ ```
536
+
537
+ *Methods used: [`to_camelcase`](https://itsthedevman.com/docs/everythingrb/String.html#to_camelcase-instance_method)*
538
+
539
+ **Extensions:** [`in_quotes`](https://itsthedevman.com/docs/everythingrb/Everythingrb/InspectQuotable.html#in_quotes-instance_method), [`with_quotes`](https://itsthedevman.com/docs/everythingrb/Everythingrb/InspectQuotable.html#with_quotes-instance_method) (alias), [`to_camelcase`](https://itsthedevman.com/docs/everythingrb/String.html#to_camelcase-instance_method)
166
540
 
167
541
  ### Boolean Methods
168
542
 
169
543
  Create predicate methods with minimal code:
170
544
 
171
545
  ```ruby
546
+ # BEFORE
547
+ class User
548
+ attr_accessor :admin
549
+
550
+ def admin?
551
+ !!@admin
552
+ end
553
+ end
554
+
555
+ user = User.new
556
+ user.admin = true
557
+ user.admin? # => true
558
+ ```
559
+
560
+ ```ruby
561
+ # AFTER
172
562
  class User
173
563
  attr_accessor :admin
174
564
  attr_predicate :admin
@@ -177,8 +567,21 @@ end
177
567
  user = User.new
178
568
  user.admin = true
179
569
  user.admin? # => true
570
+ ```
571
+
572
+ *Methods used: [`attr_predicate`](https://itsthedevman.com/docs/everythingrb/Module.html#attr_predicate-instance_method)*
573
+
574
+ Works with Data objects too:
575
+
576
+ ```ruby
577
+ # BEFORE
578
+ Person = Data.define(:active) do
579
+ def active?
580
+ !!active
581
+ end
582
+ end
180
583
 
181
- # Works with Data objects too!
584
+ # AFTER
182
585
  Person = Data.define(:active)
183
586
  Person.attr_predicate(:active)
184
587
 
@@ -186,7 +589,27 @@ person = Person.new(active: false)
186
589
  person.active? # => false
187
590
  ```
188
591
 
189
- **Extensions:** `attr_predicate`
592
+ *Methods used: [`attr_predicate`](https://itsthedevman.com/docs/everythingrb/Module.html#attr_predicate-instance_method)*
593
+
594
+ **Extensions:** [`attr_predicate`](https://itsthedevman.com/docs/everythingrb/Module.html#attr_predicate-instance_method)
595
+
596
+ ### Value Transformation
597
+
598
+ Chain transformations with a more descriptive syntax:
599
+
600
+ ```ruby
601
+ # BEFORE
602
+ result = value.then { |v| transform_it(v) }
603
+ ```
604
+
605
+ ```ruby
606
+ # AFTER
607
+ result = value.morph { |v| transform_it(v) }
608
+ ```
609
+
610
+ *Methods used: [`morph`](https://itsthedevman.com/docs/everythingrb/Kernel.html#morph-instance_method)*
611
+
612
+ **Extensions:** [`morph`](https://itsthedevman.com/docs/everythingrb/Kernel.html#morph-instance_method) (alias for `then`/`yield_self`)
190
613
 
191
614
  ## Full Documentation
192
615
 
@@ -1,11 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "array"
4
+ require_relative "boolean"
4
5
  require_relative "data"
6
+ require_relative "date"
5
7
  require_relative "enumerable"
6
8
  require_relative "hash"
9
+ require_relative "kernel"
7
10
  require_relative "module"
11
+ require_relative "nil"
12
+ require_relative "numeric"
8
13
  require_relative "ostruct"
14
+ require_relative "range"
15
+ require_relative "regexp"
9
16
  require_relative "string"
10
17
  require_relative "struct"
11
18
  require_relative "symbol"
19
+ require_relative "time"