shale-builder 0.3.0 → 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: 0f414f7972ec3166248e62fff4de18535943acbf50716be2d5c44a7554ea478a
4
- data.tar.gz: ba908e4c6a3eacf20454c0414c17d6030aac70c46a107e9cdc6787ace36c4dcb
3
+ metadata.gz: da77acaa0e4c63b3155b114625c4da322066c92447ce1297915eac5e4facef71
4
+ data.tar.gz: 043214cb3659bc261089c29306082051e1cf14dc222e8852336b9cf9f4dd102e
5
5
  SHA512:
6
- metadata.gz: 9b577f88840d98b081b093a2c55c21b002b70234692459a8f3cae3af8f02b57b3baddfa5a196c3c922cb3bbf48b1586544488ece5e5891e8a93eef86694f52e8
7
- data.tar.gz: 999ef9a4ea5e36dd0bff06d0046c27b243ada40ba5d49688ae9d8b2c8bda4e35496784918796fd8a634b2e82a921eced59979b7a0142ca59cc58bd4bfd0d672b
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/CHANGELOG.md CHANGED
@@ -5,23 +5,31 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.3.0] - 2024-09-24
8
+ ## [0.4.0] - 2025-10-14
9
9
 
10
10
  [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.3.0...v0.2.1)
11
11
 
12
12
  ### Changes
13
- - Add additional sorbet type documentation
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`
14
22
 
15
23
  ## [0.2.1] - 2024-07-16
16
24
 
17
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.1...v0.2.0)
25
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.0...v0.2.1)
18
26
 
19
27
  ### Changes
20
28
  - Add additional sorbet type documentation
21
29
 
22
30
  ## [0.2.0] - 2024-06-11
23
31
 
24
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.0...v0.1.9)
32
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.9...v0.2.0)
25
33
 
26
34
  ### Changes
27
35
  - Add support for `return_type` and `setter_type` in custom primitive shale types
@@ -29,21 +37,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
29
37
 
30
38
  ## [0.1.9] - 2024-06-03
31
39
 
32
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.9...v0.1.8)
40
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.8...v0.1.9)
33
41
 
34
42
  ### Changes
35
43
  - Fix the signature of `new` class method
36
44
 
37
45
  ## [0.1.8] - 2024-05-15
38
46
 
39
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.8...v0.1.7)
47
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.7...v0.1.8)
40
48
 
41
49
  ### Changes
42
50
  - Sort attribute names in the tapioca compiler
43
51
 
44
52
  ## [0.1.7] - 2024-05-13
45
53
 
46
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.7...v0.1.6)
54
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.6...v0.1.7)
47
55
 
48
56
  ### Changes
49
57
  - Drop support for Ruby 3.0
@@ -51,35 +59,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
51
59
 
52
60
  ## [0.1.6] - 2024-05-13
53
61
 
54
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.6...v0.1.5)
62
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.5...v0.1.6)
55
63
 
56
64
  ### Changes
57
65
  - Add support for doc strings in the tapioca compiler
58
66
 
59
67
  ## [0.1.5] - 2024-05-13
60
68
 
61
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.5...v0.1.4)
69
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.4...v0.1.5)
62
70
 
63
71
  ### Changes
64
72
  - Fix a bug in the tapioca compiler
65
73
 
66
74
  ## [0.1.4] - 2024-05-13
67
75
 
68
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.4...v0.1.3)
76
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.3...v0.1.4)
69
77
 
70
78
  ### Changes
71
79
  - Add a tapioca compiler for shale and shale builder
72
80
 
73
81
  ## [0.1.3] - 2023-11-23
74
82
 
75
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.3...v0.1.2)
83
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.2...v0.1.3)
76
84
 
77
85
  ### Changes
78
86
  - Change shale version dependency from `< 1.0` to `< 2.0`
79
87
 
80
88
  ## [0.1.2] - 2023-10-11
81
89
 
82
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.2...v0.1.1)
90
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.1...v0.1.2)
83
91
 
84
92
  ### Changes
85
93
  - Add support for collections
@@ -87,14 +95,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
87
95
 
88
96
  ## [0.1.1] - 2023-02-22
89
97
 
90
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.1...v0.1.0)
98
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.0...v0.1.1)
91
99
 
92
100
  ### Changes
93
101
  - Add support for inheritance
94
102
 
95
103
  ## [0.1.0] - 2023-02-21
96
104
 
97
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.0...v0.0.0)
105
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.0.0...v0.1.0)
98
106
 
99
107
  ### Changes
100
108
  - Initial release
data/Gemfile CHANGED
@@ -5,10 +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
19
  gem 'sorbet', '>= 0.5' # static typechecker
14
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.3.0)
4
+ shale-builder (0.4.0)
5
5
  booleans (>= 0.1)
6
6
  shale (< 2.0)
7
7
  sorbet-runtime (> 0.5)
@@ -9,73 +9,113 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- ast (2.4.2)
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)
13
30
  bigdecimal (3.2.3)
14
31
  booleans (0.1.1)
15
32
  byebug (11.1.3)
16
- erubi (1.12.0)
17
- json (2.6.3)
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)
18
43
  minitest (5.17.0)
44
+ mutex_m (0.3.0)
19
45
  netrc (0.11.0)
20
- parallel (1.22.1)
21
- parser (3.2.1.0)
46
+ parallel (1.27.0)
47
+ parser (3.3.9.0)
22
48
  ast (~> 2.4.1)
23
- prism (0.29.0)
49
+ racc
50
+ prism (1.5.2)
51
+ racc (1.8.1)
24
52
  rainbow (3.1.1)
25
53
  rake (13.0.6)
26
- rbi (0.1.13)
27
- prism (>= 0.18.0, < 1.0.0)
28
- sorbet-runtime (>= 0.5.9204)
29
- regexp_parser (2.7.0)
30
- rexml (3.2.5)
31
- 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)
32
61
  json (~> 2.3)
62
+ language_server-protocol (~> 3.17.0.2)
63
+ lint_roller (~> 1.1.0)
33
64
  parallel (~> 1.10)
34
- parser (>= 3.2.0.0)
65
+ parser (>= 3.3.0.2)
35
66
  rainbow (>= 2.2.2, < 4.0)
36
- regexp_parser (>= 1.8, < 3.0)
37
- rexml (>= 3.2.5, < 4.0)
38
- rubocop-ast (>= 1.24.1, < 2.0)
67
+ regexp_parser (>= 2.9.3, < 3.0)
68
+ rubocop-ast (>= 1.47.1, < 2.0)
39
69
  ruby-progressbar (~> 1.7)
40
- unicode-display_width (>= 2.4.0, < 3.0)
41
- rubocop-ast (1.26.0)
42
- parser (>= 3.2.1.0)
43
- 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)
44
75
  rubocop
45
- ruby-progressbar (1.11.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)
46
81
  shale (1.2.2)
47
82
  bigdecimal
48
83
  shoulda-context (2.0.0)
49
- sorbet (0.5.11372)
50
- sorbet-static (= 0.5.11372)
51
- sorbet-runtime (0.5.11372)
52
- sorbet-static (0.5.11372-universal-darwin)
53
- sorbet-static (0.5.11372-x86_64-linux)
54
- sorbet-static-and-runtime (0.5.11372)
55
- sorbet (= 0.5.11372)
56
- sorbet-runtime (= 0.5.11372)
57
- 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)
58
93
  erubi (>= 1.10.0)
59
- prism (>= 0.19.0)
94
+ prism (>= 0.28.0)
95
+ rbi (>= 0.2.3)
60
96
  sorbet-static-and-runtime (>= 0.5.10187)
61
97
  thor (>= 0.19.2)
62
- tapioca (0.14.1)
98
+ tapioca (0.16.11)
99
+ benchmark
63
100
  bundler (>= 2.2.25)
64
101
  netrc (>= 0.11.0)
65
102
  parallel (>= 1.21.0)
66
- rbi (>= 0.1.4, < 0.2)
103
+ rbi (~> 0.2)
67
104
  sorbet-static-and-runtime (>= 0.5.11087)
68
105
  spoom (>= 1.2.0)
69
106
  thor (>= 1.2.0)
70
107
  yard-sorbet
71
- thor (1.2.1)
72
- unicode-display_width (2.4.2)
73
- webrick (1.7.0)
74
- yard (0.9.28)
75
- webrick (~> 1.7.0)
76
- yard-sorbet (0.8.1)
77
- sorbet-runtime (>= 0.5)
78
- 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
79
119
 
80
120
  PLATFORMS
81
121
  arm64-darwin-20
@@ -84,10 +124,16 @@ PLATFORMS
84
124
  x86_64-linux
85
125
 
86
126
  DEPENDENCIES
127
+ activemodel (~> 8.0)
128
+ base64 (~> 0.3)
87
129
  byebug (~> 11.1)
88
130
  minitest (~> 5.0)
131
+ mutex_m (~> 0.3)
132
+ racc (~> 1.8)
89
133
  rake (~> 13.0)
90
- rubocop-espago (~> 1.0)
134
+ rubocop (~> 1.81)
135
+ rubocop-espago (~> 1.2)
136
+ rubocop-sorbet (~> 0.11)
91
137
  shale-builder!
92
138
  shoulda-context (~> 2.0)
93
139
  sorbet (>= 0.5)
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.3.0'
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
@@ -52,12 +52,6 @@ module Tapioca
52
52
  getter_without_block_type = return_type.to_s
53
53
  end
54
54
 
55
- if has_shale_builder && attribute.type < ::Shale::Mapper
56
- generate_mapper_getter(mod, attribute.name, return_type, getter_without_block_type, comments)
57
- else
58
- mod.create_method(attribute.name, return_type: getter_without_block_type, comments: comments)
59
- end
60
-
61
55
  setter_type, nilable = shale_type_to_sorbet_setter_type(attribute)
62
56
  if attribute.collection?
63
57
  setter_type_str = "T.nilable(T::Array[#{setter_type}])"
@@ -67,13 +61,22 @@ module Tapioca
67
61
  setter_type_str = setter_type.to_s
68
62
  end
69
63
 
70
- # setter
71
- mod.create_method(
72
- "#{attribute.name}=",
73
- parameters: [create_param('value', type: setter_type_str)],
74
- return_type: setter_type_str,
75
- comments: comments,
76
- )
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
77
80
  end
78
81
  end
79
82
 
@@ -90,6 +93,7 @@ module Tapioca
90
93
  end
91
94
  def generate_mapper_getter(mod, method_name, type, getter_without_block_type, comments)
92
95
  if mod.respond_to?(:create_sig)
96
+ mod = T.unsafe(mod)
93
97
  # for tapioca < 0.16.0
94
98
  sigs = T.let([], T::Array[RBI::Sig])
95
99
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shale-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateusz Drewniak
@@ -69,6 +69,7 @@ files:
69
69
  - Rakefile
70
70
  - lib/shale/attribute.rb
71
71
  - lib/shale/builder.rb
72
+ - lib/shale/builder/nested_validations.rb
72
73
  - lib/shale/builder/version.rb
73
74
  - lib/shale/mapper.rbi
74
75
  - lib/tapioca/dsl/compilers/shale.rb