inline_transforms 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 22f30721666a47350279cb918ceadc3887f4fa5aaca5202901559ec690778fa6
4
+ data.tar.gz: bc800383746ebb80919e00a9103fac32ad4cf8c8863a5207c2ffcd186de58ca4
5
+ SHA512:
6
+ metadata.gz: 423e20167b171a3a929c9dcc063d9bcb7a10cc91a1f0b6cab20817df8ababf10471f96196c09994dad0e7b0999ac324d1466d19d99f680a7ebdb5b5a57e77ea8
7
+ data.tar.gz: 65bb28caa0f2d10c3a45a5a45a05574f55f230c77f47783bd5ec819280d62809c1cd2808d314176f62588e02f107d42ccb17caac0121ed16f9d205d59bd9bae1
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --format='html'
2
+ --markup='markdown'
3
+ --no-private
4
+ --output-dir='./docs'
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nestor Custodio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,159 @@
1
+ [![Gem Version](https://img.shields.io/github/v/release/nestor-custodio/inline_transforms?color=green&label=gem%20version)](https://rubygems.org/gems/inline_transforms)
2
+ [![MIT License](https://img.shields.io/github/license/nestor-custodio/inline_transforms)](https://tldrlegal.com/license/mit-license)
3
+
4
+
5
+ # Inline Transforms
6
+
7
+ Ruby is an incredibly expressive (and easy to read!) language, but lacks a way for you to transform a value _inline_ without resorting to nested ternaries (🫠). This gem allows you to do exactly that in a way that still feels like _Ruby_ (i.e. via _value manipulation_ through method calls rather than classic flow control blocks).
8
+
9
+ In simplest terms:
10
+ ```ruby
11
+ # "Unless" Logic:
12
+
13
+ final_value = original_value
14
+ final_value = different_value if original_value == a_bad_thing
15
+
16
+ # ... or ...
17
+
18
+ final_value = if original_value == a_bad_thing
19
+ different_value
20
+ else
21
+ original_value
22
+ end
23
+
24
+ # ... becomes ...
25
+
26
+ final_value = original_value.unless a_bad_thing,
27
+ then: different_value
28
+
29
+
30
+ # "Transform" Logic:
31
+
32
+ final_value = case original_value
33
+ when true then 'success'
34
+ when false then 'failure'
35
+ when String then %(error: "#{original_value}")
36
+ end
37
+
38
+ # ... becomes ...
39
+
40
+ final_value = original_value.transform true => 'success',
41
+ false => 'failure',
42
+ String => %(error: "#{original_value}")
43
+
44
+ ```
45
+
46
+ [Full documentation is available here](https://nestor-custodio.github.io/inline_transforms), but do read below for a crash course on availble featues!
47
+
48
+
49
+ ## Installation
50
+
51
+ - If your project uses [Bundler](https://github.com/bundler/bundler):
52
+ - Add one of the following to your application's Gemfile:
53
+ ```ruby
54
+ # For on-demand usage:
55
+
56
+ gem 'inline_transforms'
57
+ ```
58
+ - And then run a:
59
+ ```shell
60
+ $ bundle install
61
+ ```
62
+
63
+ - Or, you can keep things simple with a manual install:
64
+ ```shell
65
+ $ gem install inline_transforms
66
+ ```
67
+
68
+
69
+ ## Usage
70
+
71
+ ### Object#unless
72
+
73
+ `unless` lets you specify a "bad" value and a `then` replacement.
74
+
75
+ - If your `then` replacement is a `Proc`, it is resolved (via `call`) before being returned.
76
+ - This method uses **case comparison** (`===`), so you can check for range inclusion or class.
77
+
78
+ ```ruby
79
+ final = value.unless bad_value, then: fallback_value
80
+ # ... or ...
81
+ final = value.unless bad_value, then: -> { some_method_call with_params }
82
+ ```
83
+
84
+
85
+ ### Object#transform
86
+
87
+ `transform` lets you specify a transformation hash and will return the value for the first matching key, or (if no matching key is found) the `:else` value.
88
+
89
+ - Any `Proc` values in the transform hash are resolved (via `call`) before being returned.
90
+ - This method uses **case comparison** (`===`), so range and class keys work as you expect.
91
+
92
+ ```ruby
93
+ final = value.transform key_1 => value_1,
94
+ key_2 => value_2,
95
+ # ...
96
+ else: else_value
97
+ ```
98
+
99
+
100
+ ## Potential Gotchas
101
+
102
+ - `Proc` instances are only resolved if they _need to be returned and are not the original value_:
103
+ ```ruby
104
+ value = -> { 'value proc' }
105
+ replacement_proc = -> { 'replacement proc' }
106
+
107
+ # Returns the original `value`, still a *Proc*.
108
+ #
109
+ # The original `value` is never resolved.
110
+ # The `replacement_proc` is not resolved.
111
+ #
112
+ final = value.unless 99, then: replacement_proc
113
+
114
+ # Returns the *String* 'replacement proc'.
115
+ #
116
+ # The original `value` is never resolved.
117
+ # The `replacement_proc` DOES get resolved.
118
+ #
119
+ final = value.unless value, then: replacement_proc
120
+
121
+ # Returns 99.
122
+ #
123
+ # The original `value` is never resolved.
124
+ # The `replacement_proc` is not resolved.
125
+ #
126
+ final = value.transform value => 99, else: replacement_proc
127
+
128
+ # Returns the *String* 'replacement proc'.
129
+ #
130
+ # The original `value` is never resolved.
131
+ # The `replacement_proc` DOES get resolved.
132
+ #
133
+ final = value.transform 99 => 99, else: replacement_proc
134
+ ```
135
+
136
+ - Because _return_ `Proc`s are resolved before being passed back, you have to "proc-wrap" any `Proc` you want returned as-is (😵‍💫):
137
+ ```ruby
138
+ value = 'some value'
139
+ replacement_proc = -> { 'replacement proc' }
140
+
141
+ # Returns the `replacement_proc`, still a *Proc*.
142
+ #
143
+ value.unless 99, then: -> { replacement_proc }
144
+ ```
145
+ It should be _exceedingly rare_ for someone to want to do this, but it _is_ supported and this is how you would make that happen.
146
+
147
+
148
+ ## Contribution / Development
149
+
150
+ Bug reports and pull requests are welcome at: [https://github.com/nestor-custodio/inline_transforms](https://github.com/nestor-custodio/inline_transforms)
151
+
152
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
153
+
154
+ Linting is courtesy of [Rubocop](https://docs.rubocop.org/) (`rake rubocop`) and documentation is built using [YARD](https://yardoc.org/). Please ensure you have a clean bill of health from Rubocop and that any new features and/or changes to behaviour are reflected in the adjacent documentation before submitting a pull request.
155
+
156
+
157
+ ## License
158
+
159
+ The `inline_transforms` gem is available as open source under the terms of the [MIT License](https://tldrlegal.com/license/mit-license).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ require 'rubocop/rake_task'
7
+
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[spec rubocop]
@@ -0,0 +1,3 @@
1
+ module InlineTransforms
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,78 @@
1
+ require_relative 'inline_transforms/version'
2
+
3
+ # Defines `unless` and `transform`, which we'll then want to make available in `Object` instances.
4
+ #
5
+ module InlineTransforms
6
+ # Our use of case equality in matching bad/target values
7
+ # is intentional and part of the promise behind the gem.
8
+ #
9
+ # rubocop:disable Style/CaseEquality
10
+
11
+ # Returns `self` ... unless it matches a "bad" value, in which case it returns an alternate (`then:`) value.
12
+ #
13
+ # (NOTE: this takes a `then: nil` named param, but is defined as taking `(**options)` because `then` is reserved.)
14
+ #
15
+ #
16
+ # @param bad_value [Object]
17
+ # The one value we consider "bad", and for which we'd like the `then:` option back instead.
18
+ #
19
+ # @option then: [Object]
20
+ # The value we'd like back if `self` matches the `bad_value` **using case comparison**.
21
+ # Defaults to `nil`.
22
+ #
23
+ # @return
24
+ # Returns either `self` or the value given as the `then:` option.
25
+ #
26
+ def unless(bad_value, **options)
27
+ return self unless inline_transforms_equality? bad_value
28
+
29
+ alt_value = options[:then]
30
+ return alt_value.call if alt_value.is_a? Proc
31
+
32
+ alt_value
33
+ end
34
+
35
+ # Returns `self` ... unless it matches one of the keys in the given "transformation hash", in which case the
36
+ # corresponding hash value is returned. If no matching hash key is found, this returns a fallback (`else:`) value.
37
+ #
38
+ # (NOTE: this takes an `else: nil` named param, but is defined as taking `(**options)` because `else` is reserved.)
39
+ #
40
+ #
41
+ # @option **
42
+ # A hash of keys to case-compare against `self` so we can return the corresponding value.
43
+ #
44
+ # @option else: [Object]
45
+ # The fallback value to return if no matching key is found.
46
+ #
47
+ # @return
48
+ # Returns either `self`, one of the transformation hash values, or the `else:` option.
49
+ #
50
+ def transform(**options)
51
+ default = options.delete :else
52
+
53
+ options.each { |key, value| return value.unless Proc, then: -> { value.call } if inline_transforms_equality? key }
54
+ default
55
+ end
56
+
57
+ private
58
+
59
+ # You can't case-compare *against* a `Proc` because `Proc#===` is an alias for `Proc#call`. (?!)
60
+ # So we have to be careful when testing for this.
61
+ #
62
+ # @param value [Object]
63
+ # The value against which to case-compare `self`.
64
+ #
65
+ # @return [true, false]
66
+ #
67
+ def inline_transforms_equality?(value)
68
+ return value == self if value.is_a? Proc
69
+
70
+ value === self
71
+ end
72
+
73
+ # rubocop:enable Style/CaseEquality
74
+ end
75
+
76
+ # Gets the `InlineTransforms` methods.
77
+ #
78
+ class Object; include InlineTransforms; end # rubocop:disable Style/OneClassPerFile
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inline_transforms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nestor Custodio
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ email:
13
+ - nestor@custodio.org
14
+ executables: []
15
+ extensions: []
16
+ extra_rdoc_files: []
17
+ files:
18
+ - ".ruby-version"
19
+ - ".yardopts"
20
+ - LICENSE
21
+ - README.md
22
+ - Rakefile
23
+ - lib/inline_transforms.rb
24
+ - lib/inline_transforms/version.rb
25
+ homepage: https://github.com/nestor-custodio/inline_transforms
26
+ licenses:
27
+ - MIT
28
+ metadata:
29
+ allowed_push_host: https://rubygems.org
30
+ homepage_uri: https://github.com/nestor-custodio/inline_transforms
31
+ changelog_uri: https://github.com/nestor-custodio/inline_transforms/CHANGELOG.md
32
+ rubygems_mfa_required: 'true'
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '3.4'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubygems_version: 3.6.9
48
+ specification_version: 4
49
+ summary: Facilitates inline value logic.
50
+ test_files: []