shale-builder 0.2.4 → 0.4.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: e1b61d4f6f883e6c38a5e30350fd069a965af0768a3025b8dcaee86c15e12b33
4
- data.tar.gz: 6f7cc4a30ea88549050d3054451b37caae4c25bbd0fed6593b40d481bab6bd7f
3
+ metadata.gz: da77acaa0e4c63b3155b114625c4da322066c92447ce1297915eac5e4facef71
4
+ data.tar.gz: 043214cb3659bc261089c29306082051e1cf14dc222e8852336b9cf9f4dd102e
5
5
  SHA512:
6
- metadata.gz: 9a2dd0016276064808485498d44784e36f8f408332d77aa1f8a2b33c73e0388d27eb89ddfa0a7199faa406d7f62943630f72dcbc562d9c09989aa9e6b342ae12
7
- data.tar.gz: e17f0dd84c2d654fce94acbd803e9984992abe72dfe6748865762faadbbd9d4ec45f333c4efc50338084b4980b640cfa005e0064b86528ee7a06bf30619f7025
6
+ metadata.gz: 2e00a2bbeb8ba5c240543520d7a881e2b10fc3e79cf941250230c5906e7ba85742b31611a04154f45e953ba8ec16a1c6dbbd5dc7c6a72e895d25f646e01a19b7
7
+ data.tar.gz: 1f5462ad104ca4ffdb7f68d895a517d70dd67b7fe666da7baed61bddd2c68de101061d992abad6895045cb6dc8c958ec59a57cc39cbc51a8fb56056e1bafd5ed
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  inherit_gem:
2
- rubocop-espago: rubocop.yml
2
+ rubocop-espago: sorbet.yml
3
3
 
4
4
  AllCops:
5
5
  TargetRubyVersion: 3.1
@@ -14,3 +14,21 @@ Style/TrailingCommaInArguments:
14
14
 
15
15
  Naming/BlockForwarding:
16
16
  Enabled: false
17
+
18
+ Sorbet/ForbidTSig:
19
+ Enabled: false
20
+
21
+ Sorbet/RedundantExtendTSig:
22
+ Enabled: false
23
+
24
+ Sorbet/ForbidMixesInClassMethods:
25
+ Enabled: false
26
+
27
+ Sorbet/ForbidTUnsafe:
28
+ Enabled: false
29
+
30
+ Sorbet/ForbidTHelpers:
31
+ Enabled: false
32
+
33
+ Style/DocumentDynamicEvalDefinition:
34
+ Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.4.5
data/CHANGELOG.md CHANGED
@@ -1,50 +1,108 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.4.0] - 2025-10-14
9
+
10
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.3.0...v0.2.1)
11
+
12
+ ### Changes
13
+ - Add `Shale::Builder::NestedValidations`
14
+ - Add `Shale::Builder#alias_attribute`
15
+
16
+ ## [0.3.0] - 2025-09-24
17
+
18
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.1...v0.3.0)
19
+
20
+ ### Changes
21
+ - Add support for `BigDecimal`
22
+
1
23
  ## [0.2.1] - 2024-07-16
2
24
 
25
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.0...v0.2.1)
26
+
27
+ ### Changes
3
28
  - Add additional sorbet type documentation
4
29
 
5
30
  ## [0.2.0] - 2024-06-11
6
31
 
32
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.9...v0.2.0)
33
+
34
+ ### Changes
7
35
  - Add support for `return_type` and `setter_type` in custom primitive shale types
8
36
  - Add a more thorough description of sorbet and tapioca support in the README
9
37
 
10
38
  ## [0.1.9] - 2024-06-03
11
39
 
40
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.8...v0.1.9)
41
+
42
+ ### Changes
12
43
  - Fix the signature of `new` class method
13
44
 
14
45
  ## [0.1.8] - 2024-05-15
15
46
 
47
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.7...v0.1.8)
48
+
49
+ ### Changes
16
50
  - Sort attribute names in the tapioca compiler
17
51
 
18
52
  ## [0.1.7] - 2024-05-13
19
53
 
54
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.6...v0.1.7)
55
+
56
+ ### Changes
20
57
  - Drop support for Ruby 3.0
21
58
  - Add support for Ruby 3.3
22
59
 
23
60
  ## [0.1.6] - 2024-05-13
24
61
 
62
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.5...v0.1.6)
63
+
64
+ ### Changes
25
65
  - Add support for doc strings in the tapioca compiler
26
66
 
27
67
  ## [0.1.5] - 2024-05-13
28
68
 
69
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.4...v0.1.5)
70
+
71
+ ### Changes
29
72
  - Fix a bug in the tapioca compiler
30
73
 
31
74
  ## [0.1.4] - 2024-05-13
32
75
 
76
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.3...v0.1.4)
77
+
78
+ ### Changes
33
79
  - Add a tapioca compiler for shale and shale builder
34
80
 
35
81
  ## [0.1.3] - 2023-11-23
36
82
 
83
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.2...v0.1.3)
84
+
85
+ ### Changes
37
86
  - Change shale version dependency from `< 1.0` to `< 2.0`
38
87
 
39
88
  ## [0.1.2] - 2023-10-11
40
89
 
90
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.1...v0.1.2)
91
+
92
+ ### Changes
41
93
  - Add support for collections
42
94
  - Drop support for Ruby 2.7
43
95
 
44
96
  ## [0.1.1] - 2023-02-22
45
97
 
98
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.0...v0.1.1)
99
+
100
+ ### Changes
46
101
  - Add support for inheritance
47
102
 
48
103
  ## [0.1.0] - 2023-02-21
49
104
 
105
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.0.0...v0.1.0)
106
+
107
+ ### Changes
50
108
  - Initial release
data/Gemfile CHANGED
@@ -5,11 +5,16 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in diggable.gemspec
6
6
  gemspec
7
7
 
8
+ gem 'activemodel', '~> 8.0' # validations
9
+ gem 'base64', '~> 0.3' # Base64
8
10
  gem 'byebug', '~> 11.1' # debugger
9
11
  gem 'minitest', '~> 5.0' # test framework
12
+ gem 'mutex_m', '~> 0.3' # Mutexes
13
+ gem 'racc', '~> 1.8' # parser
10
14
  gem 'rake', '~> 13.0' # automation tasks
11
- gem 'rubocop-espago', '~> 1.0' # ruby linter
15
+ gem 'rubocop', '~> 1.81' # ruby linter
16
+ gem 'rubocop-espago', '~> 1.2' # Espago rubocop config
17
+ gem 'rubocop-sorbet', '~> 0.11' # sorbet rubocop config
12
18
  gem 'shoulda-context', '~> 2.0' # more pleasant test syntax
13
- gem 'solargraph', '~> 0.48' # language server
14
19
  gem 'sorbet', '>= 0.5' # static typechecker
15
20
  gem 'tapioca', '> 0.13' # RBI generator for sorbet
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shale-builder (0.2.4)
4
+ shale-builder (0.4.0)
5
5
  booleans (>= 0.1)
6
6
  shale (< 2.0)
7
7
  sorbet-runtime (> 0.5)
@@ -9,119 +9,135 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- ast (2.4.2)
13
- backport (1.2.0)
14
- benchmark (0.2.1)
12
+ activemodel (8.0.3)
13
+ activesupport (= 8.0.3)
14
+ activesupport (8.0.3)
15
+ base64
16
+ benchmark (>= 0.3)
17
+ bigdecimal
18
+ concurrent-ruby (~> 1.0, >= 1.3.1)
19
+ connection_pool (>= 2.2.5)
20
+ drb
21
+ i18n (>= 1.6, < 2)
22
+ logger (>= 1.4.2)
23
+ minitest (>= 5.1)
24
+ securerandom (>= 0.3)
25
+ tzinfo (~> 2.0, >= 2.0.5)
26
+ uri (>= 0.13.1)
27
+ ast (2.4.3)
28
+ base64 (0.3.0)
29
+ benchmark (0.4.1)
30
+ bigdecimal (3.2.3)
15
31
  booleans (0.1.1)
16
32
  byebug (11.1.3)
17
- diff-lcs (1.5.0)
18
- e2mmap (0.1.0)
19
- erubi (1.12.0)
20
- jaro_winkler (1.5.4)
21
- json (2.6.3)
22
- kramdown (2.4.0)
23
- rexml
24
- kramdown-parser-gfm (1.1.0)
25
- kramdown (~> 2.0)
33
+ concurrent-ruby (1.3.5)
34
+ connection_pool (2.5.4)
35
+ drb (2.2.3)
36
+ erubi (1.13.1)
37
+ i18n (1.14.7)
38
+ concurrent-ruby (~> 1.0)
39
+ json (2.15.1)
40
+ language_server-protocol (3.17.0.5)
41
+ lint_roller (1.1.0)
42
+ logger (1.7.0)
26
43
  minitest (5.17.0)
44
+ mutex_m (0.3.0)
27
45
  netrc (0.11.0)
28
- nokogiri (1.16.5-arm64-darwin)
29
- racc (~> 1.4)
30
- nokogiri (1.16.5-x86_64-linux)
31
- racc (~> 1.4)
32
- parallel (1.22.1)
33
- parser (3.2.1.0)
46
+ parallel (1.27.0)
47
+ parser (3.3.9.0)
34
48
  ast (~> 2.4.1)
35
- prism (0.29.0)
36
- racc (1.7.3)
49
+ racc
50
+ prism (1.5.2)
51
+ racc (1.8.1)
37
52
  rainbow (3.1.1)
38
53
  rake (13.0.6)
39
- rbi (0.1.13)
40
- prism (>= 0.18.0, < 1.0.0)
41
- sorbet-runtime (>= 0.5.9204)
42
- regexp_parser (2.7.0)
43
- reverse_markdown (2.1.1)
44
- nokogiri
45
- rexml (3.2.5)
46
- rubocop (1.45.1)
54
+ rbi (0.3.7)
55
+ prism (~> 1.0)
56
+ rbs (>= 3.4.4)
57
+ rbs (3.9.5)
58
+ logger
59
+ regexp_parser (2.11.3)
60
+ rubocop (1.81.1)
47
61
  json (~> 2.3)
62
+ language_server-protocol (~> 3.17.0.2)
63
+ lint_roller (~> 1.1.0)
48
64
  parallel (~> 1.10)
49
- parser (>= 3.2.0.0)
65
+ parser (>= 3.3.0.2)
50
66
  rainbow (>= 2.2.2, < 4.0)
51
- regexp_parser (>= 1.8, < 3.0)
52
- rexml (>= 3.2.5, < 4.0)
53
- rubocop-ast (>= 1.24.1, < 2.0)
67
+ regexp_parser (>= 2.9.3, < 3.0)
68
+ rubocop-ast (>= 1.47.1, < 2.0)
54
69
  ruby-progressbar (~> 1.7)
55
- unicode-display_width (>= 2.4.0, < 3.0)
56
- rubocop-ast (1.26.0)
57
- parser (>= 3.2.1.0)
58
- rubocop-espago (1.0.2)
70
+ unicode-display_width (>= 2.4.0, < 4.0)
71
+ rubocop-ast (1.47.1)
72
+ parser (>= 3.3.7.2)
73
+ prism (~> 1.4)
74
+ rubocop-espago (1.2.0)
59
75
  rubocop
60
- ruby-progressbar (1.11.0)
61
- shale (0.9.0)
76
+ rubocop-sorbet (0.11.0)
77
+ lint_roller
78
+ rubocop (>= 1.75.2)
79
+ ruby-progressbar (1.13.0)
80
+ securerandom (0.4.1)
81
+ shale (1.2.2)
82
+ bigdecimal
62
83
  shoulda-context (2.0.0)
63
- solargraph (0.48.0)
64
- backport (~> 1.2)
65
- benchmark
66
- bundler (>= 1.17.2)
67
- diff-lcs (~> 1.4)
68
- e2mmap
69
- jaro_winkler (~> 1.5)
70
- kramdown (~> 2.3)
71
- kramdown-parser-gfm (~> 1.1)
72
- parser (~> 3.0)
73
- reverse_markdown (>= 1.0.5, < 3)
74
- rubocop (>= 0.52)
75
- thor (~> 1.0)
76
- tilt (~> 2.0)
77
- yard (~> 0.9, >= 0.9.24)
78
- sorbet (0.5.11372)
79
- sorbet-static (= 0.5.11372)
80
- sorbet-runtime (0.5.11372)
81
- sorbet-static (0.5.11372-universal-darwin)
82
- sorbet-static (0.5.11372-x86_64-linux)
83
- sorbet-static-and-runtime (0.5.11372)
84
- sorbet (= 0.5.11372)
85
- sorbet-runtime (= 0.5.11372)
86
- spoom (1.3.2)
84
+ sorbet (0.6.12642)
85
+ sorbet-static (= 0.6.12642)
86
+ sorbet-runtime (0.6.12642)
87
+ sorbet-static (0.6.12642-universal-darwin)
88
+ sorbet-static (0.6.12642-x86_64-linux)
89
+ sorbet-static-and-runtime (0.6.12642)
90
+ sorbet (= 0.6.12642)
91
+ sorbet-runtime (= 0.6.12642)
92
+ spoom (1.6.1)
87
93
  erubi (>= 1.10.0)
88
- prism (>= 0.19.0)
94
+ prism (>= 0.28.0)
95
+ rbi (>= 0.2.3)
89
96
  sorbet-static-and-runtime (>= 0.5.10187)
90
97
  thor (>= 0.19.2)
91
- tapioca (0.14.1)
98
+ tapioca (0.16.11)
99
+ benchmark
92
100
  bundler (>= 2.2.25)
93
101
  netrc (>= 0.11.0)
94
102
  parallel (>= 1.21.0)
95
- rbi (>= 0.1.4, < 0.2)
103
+ rbi (~> 0.2)
96
104
  sorbet-static-and-runtime (>= 0.5.11087)
97
105
  spoom (>= 1.2.0)
98
106
  thor (>= 1.2.0)
99
107
  yard-sorbet
100
- thor (1.2.1)
101
- tilt (2.1.0)
102
- unicode-display_width (2.4.2)
103
- webrick (1.7.0)
104
- yard (0.9.28)
105
- webrick (~> 1.7.0)
106
- yard-sorbet (0.8.1)
107
- sorbet-runtime (>= 0.5)
108
- yard (>= 0.9)
108
+ thor (1.4.0)
109
+ tzinfo (2.0.6)
110
+ concurrent-ruby (~> 1.0)
111
+ unicode-display_width (3.2.0)
112
+ unicode-emoji (~> 4.1)
113
+ unicode-emoji (4.1.0)
114
+ uri (1.0.4)
115
+ yard (0.9.37)
116
+ yard-sorbet (0.9.0)
117
+ sorbet-runtime
118
+ yard
109
119
 
110
120
  PLATFORMS
111
121
  arm64-darwin-20
112
122
  arm64-darwin-22
123
+ arm64-darwin-24
113
124
  x86_64-linux
114
125
 
115
126
  DEPENDENCIES
127
+ activemodel (~> 8.0)
128
+ base64 (~> 0.3)
116
129
  byebug (~> 11.1)
117
130
  minitest (~> 5.0)
131
+ mutex_m (~> 0.3)
132
+ racc (~> 1.8)
118
133
  rake (~> 13.0)
119
- rubocop-espago (~> 1.0)
134
+ rubocop (~> 1.81)
135
+ rubocop-espago (~> 1.2)
136
+ rubocop-sorbet (~> 0.11)
120
137
  shale-builder!
121
138
  shoulda-context (~> 2.0)
122
- solargraph (~> 0.48)
123
139
  sorbet (>= 0.5)
124
140
  tapioca (> 0.13)
125
141
 
126
142
  BUNDLED WITH
127
- 2.4.7
143
+ 2.7.2
data/README.md CHANGED
@@ -213,6 +213,100 @@ transaction = Transaction.build do |t|
213
213
  end
214
214
  ```
215
215
 
216
+ ### Nested Validations
217
+
218
+ There is an additional module `Shale::Builder::NestedValidations` that provides
219
+ support for seamless nested validations using `ActiveModel`.
220
+
221
+ In order to load it do:
222
+
223
+ ```rb
224
+ require 'shale/builder/nested_validations'
225
+ ```
226
+
227
+ Then you can use it like so
228
+
229
+ ```rb
230
+ class AmountType < ::Shale::Mapper
231
+ include ::Shale::Builder
232
+ include ::ActiveModel::Validations
233
+ include ::Shale::Builder::NestedValidations
234
+
235
+ attribute :value, ::Shale::Type::Float
236
+ attribute :currency, ::Shale::Type::String
237
+
238
+ validates :value, presence: true
239
+ end
240
+
241
+ class TransactionType < ::Shale::Mapper
242
+ include ::Shale::Builder
243
+ include ::ActiveModel::Validations
244
+ include ::Shale::Builder::NestedValidations
245
+
246
+ attribute :cvv_code, ::Shale::Type::String
247
+ attribute :amount, AmountType
248
+
249
+ validates :cvv_code, presence: true
250
+ validates :amount, presence: true
251
+ end
252
+
253
+ obj = TransactionType.build do |t|
254
+ t.amount do |a|
255
+ a.currency = 'USD'
256
+ end
257
+ end
258
+
259
+ obj.valid? #=> false
260
+ obj.errors #=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=cvv_code, type=blank, options={}>, #<ActiveModel::NestedError attribute=amount.value, type=blank, options={}>]>
261
+ obj.errors.messages #=> {cvv_code: ["can't be blank"], "amount.value": ["can't be blank"]}
262
+ ```
263
+
264
+ You MUST include `ActiveModel::Validations` before `Shale::Builder::NestedValidations`.
265
+
266
+ ### Attribute aliases
267
+
268
+ You can easily create aliases for attributes using `alias_attribute`
269
+
270
+ Then you can use it like so
271
+
272
+ ```rb
273
+ class AmountType < ::Shale::Mapper
274
+ include ::Shale::Builder
275
+ include ::ActiveModel::Validations
276
+ include ::Shale::Builder::NestedValidations
277
+
278
+ attribute :value, ::Shale::Type::Float
279
+ attribute :currency, ::Shale::Type::String
280
+
281
+ validates :value, presence: true
282
+ end
283
+
284
+ class TransactionType < ::Shale::Mapper
285
+ include ::Shale::Builder
286
+ include ::ActiveModel::Validations
287
+ include ::Shale::Builder::NestedValidations
288
+
289
+ attribute :cvv_code, ::Shale::Type::String
290
+ attribute :amount, AmountType
291
+
292
+ validates :cvv_code, presence: true
293
+ validates :amount, presence: true
294
+ end
295
+
296
+ obj = TransactionType.build do |t|
297
+ t.amount do |a|
298
+ a.currency = 'USD'
299
+ end
300
+ end
301
+
302
+ obj.valid? #=> false
303
+ obj.errors #=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=cvv_code, type=blank, options={}>, #<ActiveModel::NestedError attribute=amount.value, type=blank, options={}>]>
304
+ obj.errors.messages #=> {cvv_code: ["can't be blank"], "amount.value": ["can't be blank"]}
305
+ ```
306
+
307
+ You MUST include `ActiveModel::Validations` before `Shale::Builder::NestedValidations`.
308
+
309
+
216
310
  ### Sorbet support
217
311
 
218
312
  Shale-builder adds support for sorbet and tapioca.
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
1
  # typed: true
2
+ # frozen_string_literal: true
3
3
 
4
4
  require 'shale'
5
5
 
@@ -11,5 +11,19 @@ module Shale
11
11
  # in a Ruby String.
12
12
  sig { returns(T.nilable(String)) }
13
13
  attr_accessor :doc
14
+
15
+ # Contains the documentation comment for the shale attribute
16
+ # in a Ruby String.
17
+ sig { returns(T.nilable(T::Array[Symbol])) }
18
+ attr_accessor :aliases
19
+
20
+ sig { returns(T::Array[Symbol]) }
21
+ def all_names
22
+ names = [name]
23
+ aliases = self.aliases
24
+ return names unless aliases
25
+
26
+ names + aliases
27
+ end
14
28
  end
15
29
  end
@@ -0,0 +1,61 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require 'shale'
5
+ require 'booleans'
6
+
7
+ module Shale
8
+ module Builder
9
+ # Include in a class tha already includes `Shale::Builder` to add support
10
+ # for nested ActiveModel validations.
11
+ #
12
+ # @requires_ancestor: Object
13
+ module NestedValidations
14
+ extend T::Sig
15
+ extend T::Helpers
16
+
17
+ # @requires_ancestor: singleton(Shale::Mapper)
18
+ module ClassMethods
19
+ extend T::Sig
20
+
21
+ sig { returns(T::Hash[Symbol, Shale::Attribute]) }
22
+ def validatable_attributes
23
+ @validatable_attributes ||= attributes.select do |_, val|
24
+ val.validatable?
25
+ end
26
+ end
27
+ end
28
+ mixes_in_class_methods ClassMethods
29
+
30
+ sig { returns(T::Boolean) }
31
+ def valid?
32
+ result = super
33
+ errlist = errors
34
+
35
+ attrs = T.unsafe(self).class.validatable_attributes
36
+ attrs.each_key do |name|
37
+ val = public_send(name)
38
+ next unless val
39
+ next if val.valid?
40
+
41
+ result = false
42
+ val.errors.each do |err|
43
+ errlist.import(err, attribute: "#{name}.#{err.attribute}")
44
+ end
45
+ end
46
+
47
+ result
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+
54
+ module Shale
55
+ class Attribute # rubocop:disable Style/Documentation
56
+ sig { returns(T::Boolean) }
57
+ def validatable?
58
+ Boolean(type.is_a?(Class) && type < ::ActiveModel::Validations)
59
+ end
60
+ end
61
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Shale
4
4
  module Builder
5
- VERSION = '0.2.4'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
data/lib/shale/builder.rb CHANGED
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
1
  # typed: true
2
+ # frozen_string_literal: true
3
3
 
4
4
  require 'shale'
5
5
  require 'sorbet-runtime'
@@ -40,6 +40,7 @@ module Shale
40
40
  # end
41
41
  #
42
42
  module Builder
43
+ extend T::Sig
43
44
  extend T::Helpers
44
45
 
45
46
  class << self
@@ -66,6 +67,7 @@ module Shale
66
67
  module ClassMethods
67
68
  extend T::Sig
68
69
  extend T::Generic
70
+
69
71
  abstract!
70
72
  has_attached_class!
71
73
 
@@ -96,18 +98,20 @@ module Shale
96
98
 
97
99
  sig do
98
100
  params(
99
- name: T.any(String, Symbol),
100
- type: Class,
101
+ name: T.any(String, Symbol),
102
+ type: Class,
101
103
  collection: T::Boolean,
102
- default: T.nilable(Proc),
103
- doc: T.nilable(String),
104
- kwargs: Object,
105
- block: T.nilable(T.proc.void),
104
+ default: T.nilable(Proc),
105
+ doc: T.nilable(String),
106
+ kwargs: Object,
107
+ block: T.nilable(T.proc.void),
106
108
  ).void
107
109
  end
108
110
  def attribute(name, type, collection: false, default: nil, doc: nil, **kwargs, &block)
109
111
  super(name, type, collection:, default:, **kwargs, &block)
110
- attributes[name.to_sym]&.doc = doc # add doc to the attribute
112
+ if (attr_def = attributes[name.to_sym])
113
+ attr_def.doc = doc
114
+ end
111
115
  return unless type < ::Shale::Mapper
112
116
 
113
117
  if collection
@@ -137,8 +141,26 @@ module Shale
137
141
  end
138
142
 
139
143
  end
140
-
141
144
  mixes_in_class_methods(ClassMethods)
142
145
 
146
+ # Create an alias for the getter and setter of an attribute.
147
+ sig { params(new_name: Symbol, old_name: Symbol).void }
148
+ def alias_attribute(new_name, old_name)
149
+ klass = T.unsafe(self).class
150
+
151
+ attr = klass.attributes[old_name]
152
+ (attr.aliases ||= []) << new_name
153
+
154
+ klass.builder_methods_module.class_eval <<~RUBY, __FILE__, __LINE__ + 1
155
+ def #{new_name}
156
+ #{old_name}
157
+ end
158
+
159
+ def #{new_name}=(val)
160
+ self.#{old_name} = val
161
+ end
162
+ RUBY
163
+ end
164
+
143
165
  end
144
166
  end
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'shale'
5
5
  require 'booleans'
6
+ require 'bigdecimal'
6
7
  begin
7
8
  require 'shale/builder'
8
9
  rescue LoadError
@@ -51,12 +52,6 @@ module Tapioca
51
52
  getter_without_block_type = return_type.to_s
52
53
  end
53
54
 
54
- if has_shale_builder && attribute.type < ::Shale::Mapper
55
- generate_mapper_getter(mod, attribute.name, return_type, getter_without_block_type, comments)
56
- else
57
- mod.create_method(attribute.name, return_type: getter_without_block_type, comments: comments)
58
- end
59
-
60
55
  setter_type, nilable = shale_type_to_sorbet_setter_type(attribute)
61
56
  if attribute.collection?
62
57
  setter_type_str = "T.nilable(T::Array[#{setter_type}])"
@@ -66,13 +61,22 @@ module Tapioca
66
61
  setter_type_str = setter_type.to_s
67
62
  end
68
63
 
69
- # setter
70
- mod.create_method(
71
- "#{attribute.name}=",
72
- parameters: [create_param('value', type: setter_type_str)],
73
- return_type: setter_type_str,
74
- comments: comments,
75
- )
64
+ attribute.all_names.each do |name|
65
+ name_str = name.to_s
66
+ if has_shale_builder && attribute.type < ::Shale::Mapper
67
+ generate_mapper_getter(mod, name_str, return_type, getter_without_block_type, comments)
68
+ else
69
+ mod.create_method(name_str, return_type: getter_without_block_type, comments: comments)
70
+ end
71
+
72
+ # setter
73
+ mod.create_method(
74
+ "#{name_str}=",
75
+ parameters: [create_param('value', type: setter_type_str)],
76
+ return_type: setter_type_str,
77
+ comments: comments,
78
+ )
79
+ end
76
80
  end
77
81
  end
78
82
 
@@ -89,6 +93,7 @@ module Tapioca
89
93
  end
90
94
  def generate_mapper_getter(mod, method_name, type, getter_without_block_type, comments)
91
95
  if mod.respond_to?(:create_sig)
96
+ mod = T.unsafe(mod)
92
97
  # for tapioca < 0.16.0
93
98
  sigs = T.let([], T::Array[RBI::Sig])
94
99
 
@@ -148,7 +153,9 @@ module Tapioca
148
153
  ::Shale::Type::Time => Time,
149
154
  ::Shale::Type::Date => Date,
150
155
  ::Shale::Type::Boolean => T::Boolean,
151
- }.freeze,
156
+ }.tap do |h|
157
+ h[::Shale::Type::Decimal] = BigDecimal if defined?(::Shale::Type::Decimal)
158
+ end.freeze,
152
159
  T::Hash[Class, Object],
153
160
  )
154
161
 
@@ -162,7 +169,11 @@ module Tapioca
162
169
  ::Shale::Type::Time => Time,
163
170
  ::Shale::Type::Date => Date,
164
171
  ::Shale::Type::Boolean => Object,
165
- }.freeze,
172
+ }.tap do |h|
173
+ if defined?(::Shale::Type::Decimal)
174
+ h[::Shale::Type::Decimal] = T.any(BigDecimal, String, Float, Integer, NilClass)
175
+ end
176
+ end.freeze,
166
177
  T::Hash[Class, Object],
167
178
  )
168
179
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shale-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateusz Drewniak
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-01-08 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: booleans
@@ -70,6 +69,7 @@ files:
70
69
  - Rakefile
71
70
  - lib/shale/attribute.rb
72
71
  - lib/shale/builder.rb
72
+ - lib/shale/builder/nested_validations.rb
73
73
  - lib/shale/builder/version.rb
74
74
  - lib/shale/mapper.rbi
75
75
  - lib/tapioca/dsl/compilers/shale.rb
@@ -81,7 +81,6 @@ metadata:
81
81
  source_code_uri: https://github.com/Verseth/ruby-shale-builder
82
82
  changelog_uri: https://github.com/Verseth/ruby-shale-builder/blob/main/CHANGELOG.md
83
83
  rubygems_mfa_required: 'true'
84
- post_install_message:
85
84
  rdoc_options: []
86
85
  require_paths:
87
86
  - lib
@@ -96,8 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
95
  - !ruby/object:Gem::Version
97
96
  version: '0'
98
97
  requirements: []
99
- rubygems_version: 3.4.21
100
- signing_key:
98
+ rubygems_version: 3.7.2
101
99
  specification_version: 4
102
100
  summary: An addon to the shale Ruby gem which adds a simple yet powerful builder DSL.
103
101
  test_files: []