tron 2.0.0 → 3.0.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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -23
  3. data/lib/tron/version.rb +4 -2
  4. data/lib/tron.rb +9 -12
  5. metadata +11 -94
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3d033d6fa697cd4da7d443028e7ca891676266f8e41ecf00be057d52e84e0e0
4
- data.tar.gz: 222f4a27b2acd1f887ee5deeb6e41b475f45c027c82663174129d7d83db6e5f5
3
+ metadata.gz: dc919787c5b549b14e26fc8d2d2a1cfd601bfbf6320751e0e4862d23856ec604
4
+ data.tar.gz: 74e32cc0cd310b830bb58bb5a92c4e44f4a966d9271557ad7482337051d8dcf5
5
5
  SHA512:
6
- metadata.gz: cbb6fe573460da64aac5a59da8148fc766dfc73152cb8f887950fd4b99e90c7e2f9c0ebabed249d44f6e5b28dc912e48506866f29d0b44a65e84a7318f9339c8
7
- data.tar.gz: 497c6f228706f96d9157a9600de35af4bd2e432177ed7c5e66c6c37e10f6dc74a874467a1b8ca235066619e36a3db8bea51c390bd5e540a2ab641e1dfe5f2617
6
+ metadata.gz: 82a40a2046b62244b66cf7dbc52210215359b9f61112bd4836363b65491f7aec939be457d9a67de6bc7093cd9bdfc7676074a4cc791ba14a64389d18891c429f
7
+ data.tar.gz: 51149e095d5bf173eafeb4a99f46b4890bc47f6dcee8b8c8cbe4337ca59f5c94df436073b263aa2d1b152330a3e50d5654f15d0193728d174164e715f00e2923
data/README.md CHANGED
@@ -1,21 +1,18 @@
1
1
  [![Gem Version](https://img.shields.io/gem/v/tron.svg)](https://rubygems.org/gems/tron)
2
- [![Build Status](https://travis-ci.org/halo/tron.svg?branch=master)](https://travis-ci.org/halo/tron)
2
+ [![Build Status](https://github.com/halo/tron/actions/workflows/main.yml/badge.svg)](https://github.com/halo/tron/actions)
3
3
  [![License](http://img.shields.io/badge/license-MIT-blue.svg)](http://github.com/halo/tron/blob/master/LICENSE.md)
4
4
 
5
5
  ## TL;DR
6
6
 
7
7
  Tron is a minimalistic combination of a [monad](https://www.morozov.is/2018/09/08/monad-laws-in-ruby.html) and [value object](https://madeintandem.com/blog/creating-value-objects-in-ruby/), implemented in [a few lines](https://github.com/halo/tron/blob/master/lib/tron.rb) of code.
8
8
 
9
- Return `Tron.success(:it_worked)` or `Tron.failure(:aww_too_bad)` from a method to explain why and how it succeded/failed. That returns an immutable Struct (value object) that responds to `result.success?` and `result.failure?`.
10
-
11
- The reason is accessible in `result.success #=> :it_worked`. You can add more metadata as a second argument: `Tron.failure(:nopes, error_code: 404)` which you can access like a Struct: `result.error_code #=> 404`.
12
-
13
- Chaining can make your code cleaner: `result.on_success { download }.on_failure { show_message }`
9
+ * Return `Tron.success(:it_worked)` or `Tron.failure(:aww_too_bad)` from a method, to explain why and how it succeded or failed. That returns an immutable Data (value object) that responds to `result.success?` and `result.failure?`.
10
+ * Add metadata as a second argument: `Tron.failure(:nopes, error_code: 404)` which you then can access: `result.error_code #=> 404`.
11
+ * The result can also be queried with `result.success #=> :it_worked` and `result.failure #=> nil`.
12
+ * Chaining can make your code cleaner: `result.on_success { download }.on_failure { show_message }`
14
13
 
15
14
  ## Introduction
16
15
 
17
-
18
-
19
16
  Imagine you have a class like this:
20
17
 
21
18
  ```ruby
@@ -42,7 +39,7 @@ class User
42
39
  if @users.delete id
43
40
  Tron.success :user_deleted, user: user
44
41
  else
45
- Tron.success :deletion_failed, id: id
42
+ Tron.success :already_deleted, id: id # Notice the success here
46
43
  end
47
44
 
48
45
  rescue ConnectionError
@@ -51,7 +48,7 @@ class User
51
48
  end
52
49
  ```
53
50
 
54
- One could even take it a step further and write it like this:
51
+ One could break the functionality apart into smaller pieces:
55
52
 
56
53
  ```ruby
57
54
  class User
@@ -83,11 +80,20 @@ class User
83
80
  end
84
81
  ```
85
82
 
86
- ## So what are the benefits?
83
+ On a side-note, the data object can be passed on further with modifications, that's due to the way `Data` object work.
84
+
85
+ ```ruby
86
+ result = Tron.success(:api_not_responding, reason: :password_not_accepted)
87
87
 
88
- ### 1. It will give you robust and predictable code
88
+ result.with(code: :could_not_delete_user)
89
+ # => "#<data failure=:could_not_delete_user, reason=:password_not_accepted>"
90
+ ```
89
91
 
90
- Tron will give you this consistent, implementation-unaware, programming convention:
92
+ ## So, what are the benefits?
93
+
94
+ ### 1. An internal API that doesn't change over time
95
+
96
+ Tron will give you a consistent, implementation-unaware, programming convention. That means that you can decide later, what constitutes a success or a failure, without changing the way the result is handled. You could also add metadata after-the-fact and the following code would still work fine:
91
97
 
92
98
  ```ruby
93
99
  result = User.delete 42
@@ -99,7 +105,7 @@ else
99
105
  end
100
106
  ```
101
107
 
102
- The result is just a Struct:
108
+ The result is just an instance of Data:
103
109
 
104
110
  ```ruby
105
111
  result = User.delete 42
@@ -114,9 +120,7 @@ result.failure # => :deletion_failed_badly
114
120
 
115
121
  # Access immutable metadata
116
122
  result.message # => "..."
117
- result.inspect # => "#<struct failure=:alright, user_id=42, message='...'>"
118
-
119
- result.message.upcase! # => modification raises an exception
123
+ result.inspect # => "#<data failure=:alright, user_id=42, message='...'>"
120
124
  ```
121
125
 
122
126
  ### 2. If will give you better tests
@@ -138,15 +142,20 @@ class Product
138
142
  end
139
143
  ```
140
144
 
141
- You cannot simply test for the `false` as expected return value because it could mean anything. Tron helps you to check the response objects for every case.
145
+ You cannot simply test for `false` as expected return value, because it could mean anything. Tron helps you to check the response objects for every case. Data objects even support deconstruction for `case` statements.
142
146
 
143
147
  ### 3. It gives you documentation
144
148
 
145
- While the code you're writing becomes slightly more verbose, that verbosity translates directly into documenation. You see immediately what each line is doing.
149
+ While the code you're writing becomes slightly more verbose, that verbosity translates directly into documentation. You see immediately what each line is doing.
150
+
151
+ ## Upgrading from 2.0.0 to 3.0.0
152
+
153
+ * You will need to use at least Ruby `3.2`
154
+ * The result object doesn't respond to collection methods any more, such as `result[:some_key]` or `result.to_a`, but it's unlikely that you relied on them in the first place.
146
155
 
147
156
  ## Upgrading from 1.x.x to 2.0.0
148
157
 
149
- * 1.2.0 and 2.0.0 are identical, except that all deprecations have been removed and don't work any more.
158
+ * `1.2.0` and `2.0.0` are identical, except that all deprecations have been removed and don't work any more.
150
159
 
151
160
  ## Upgrading from 0.x.x to 1.x.x
152
161
 
@@ -161,12 +170,16 @@ Tron is a complete rewrite of its predecessor [operation](https://github.com/hal
161
170
 
162
171
  ## Requirements
163
172
 
164
- * Ruby >= 2.5.0
173
+ * Ruby >= 3.2.0
174
+
175
+ ## Development
176
+
177
+ Clone the repository, run `bundle install` and run the tests with `bundle exec rake`.
165
178
 
166
179
  ## Copyright
167
180
 
168
- MIT 2015-2019 halo. See [MIT-LICENSE](http://github.com/halo/tron/blob/master/LICENSE.md).
181
+ MIT halo. See [MIT-LICENSE](http://github.com/halo/tron/blob/master/LICENSE.txt).
169
182
 
170
183
  ## Caveats
171
184
 
172
- * There are no setter methods in the returned Struct, so you cannot overwrite the metadata. The values are also frozen, so you don't accidentally modify the attributes in-place. However, they are not deep-frozen, so an object may still be modified if you're ignorant.
185
+ * There are no setter methods in the returned Data, so you cannot overwrite the metadata. But you can use `Data#with` to essentially clone the object and change values.
data/lib/tron/version.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tron
2
- module VERSION #:nodoc:
3
- MAJOR = 2
4
+ module VERSION # :nodoc:
5
+ MAJOR = 3
4
6
  MINOR = 0
5
7
  TINY = 0
6
8
  PRE = nil
data/lib/tron.rb CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  require 'tron/version'
4
4
 
5
+ # Return data objects that can indicate success or failure.
5
6
  module Tron
6
- def self.success(code, attributes = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
7
+ def self.success(code, attributes = {}) # rubocop:disable Metrics/MethodLength
7
8
  code.respond_to?(:to_sym) ||
8
9
  raise(ArgumentError, 'Tron.success must be called with a Symbol as first argument')
9
10
 
@@ -11,12 +12,10 @@ module Tron
11
12
  raise(ArgumentError, 'The second argument (metadata) for Tron.success must respond to #keys')
12
13
 
13
14
  attributes.respond_to?(:values) ||
14
- raise(ArgumentError, 'The second argument (metadata) for Tron.success must respond to #values')
15
-
16
- Struct.new(:success, *attributes.keys) do
17
- undef_method :[]=
18
- members.each { |member| undef_method :"#{member}=" }
15
+ raise(ArgumentError,
16
+ 'The second argument (metadata) for Tron.success must respond to #values')
19
17
 
18
+ Data.define(:success, *attributes.keys) do
20
19
  def success?
21
20
  true
22
21
  end
@@ -39,7 +38,7 @@ module Tron
39
38
  end.new code.to_sym, *attributes.values
40
39
  end
41
40
 
42
- def self.failure(code, attributes = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
41
+ def self.failure(code, attributes = {}) # rubocop:disable Metrics/MethodLength
43
42
  code.respond_to?(:to_sym) ||
44
43
  raise(ArgumentError, 'Tron.failure must be called with a Symbol as first argument')
45
44
 
@@ -47,12 +46,10 @@ module Tron
47
46
  raise(ArgumentError, 'The second argument (metadata) for Tron.failure must respond to #keys')
48
47
 
49
48
  attributes.respond_to?(:values) ||
50
- raise(ArgumentError, 'The second argument (metadata) for Tron.failure must respond to #values')
51
-
52
- Struct.new(:failure, *attributes.keys) do
53
- undef_method :[]=
54
- members.each { |member| undef_method :"#{member}=" }
49
+ raise(ArgumentError,
50
+ 'The second argument (metadata) for Tron.failure must respond to #values')
55
51
 
52
+ Data.define(:failure, *attributes.keys) do
56
53
  def success?
57
54
  false
58
55
  end
metadata CHANGED
@@ -1,103 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tron
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - halo
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-30 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: guard-rspec
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: hashie
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rb-fsevent
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rspec
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rubocop
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop-rspec
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
11
+ date: 2023-08-25 00:00:00.000000000 Z
12
+ dependencies: []
97
13
  description: General-purpose method return objects that can be chained. Think minimalistic
98
14
  value object monads. Heavily inspired by the `deterministic` gem, but much much
99
15
  more light-weight.
100
- email:
16
+ email:
101
17
  executables: []
102
18
  extensions: []
103
19
  extra_rdoc_files: []
@@ -108,8 +24,9 @@ files:
108
24
  homepage: https://github.com/halo/tron
109
25
  licenses:
110
26
  - MIT
111
- metadata: {}
112
- post_install_message:
27
+ metadata:
28
+ rubygems_mfa_required: 'true'
29
+ post_install_message:
113
30
  rdoc_options: []
114
31
  require_paths:
115
32
  - lib
@@ -117,15 +34,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
34
  requirements:
118
35
  - - ">="
119
36
  - !ruby/object:Gem::Version
120
- version: 2.5.0
37
+ version: 3.2.0
121
38
  required_rubygems_version: !ruby/object:Gem::Requirement
122
39
  requirements:
123
40
  - - ">="
124
41
  - !ruby/object:Gem::Version
125
42
  version: '0'
126
43
  requirements: []
127
- rubygems_version: 3.1.2
128
- signing_key:
44
+ rubygems_version: 3.4.18
45
+ signing_key:
129
46
  specification_version: 4
130
47
  summary: General-purpose method return objects that can be chained.
131
48
  test_files: []