shale-builder 0.3.0 → 0.4.1

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: 3a79ea1df97f6d5d49af0d596144d931b5aacea98e142866d7e322497fbeaae5
4
+ data.tar.gz: 59f671f470be89ed4854798843657160c87163de286a867be73c4832bb4a2df2
5
5
  SHA512:
6
- metadata.gz: 9b577f88840d98b081b093a2c55c21b002b70234692459a8f3cae3af8f02b57b3baddfa5a196c3c922cb3bbf48b1586544488ece5e5891e8a93eef86694f52e8
7
- data.tar.gz: 999ef9a4ea5e36dd0bff06d0046c27b243ada40ba5d49688ae9d8b2c8bda4e35496784918796fd8a634b2e82a921eced59979b7a0142ca59cc58bd4bfd0d672b
6
+ metadata.gz: f763a5973d2d15c2a2c314ae61ed61f7455724f624f38852f8cd4d174fe2bf12af7bee2eb37a847b5940f9779fa4ad2960eff6a99259c12d0445d16fb63b8775
7
+ data.tar.gz: e872ffe315cec734fa77af67b1be80efded4b750194e66c2e41d069302b5dc18cc4bd0f3da2932528661cc2fa1d84ff90a08f3326c7052a65030987f5c4685eb
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,38 @@ 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.1] - 2025-10-14
9
9
 
10
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.3.0...v0.2.1)
10
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.4.0...v0.4.1)
11
11
 
12
12
  ### Changes
13
- - Add additional sorbet type documentation
13
+ - Fix `Shale::Builder::alias_attribute`, improve changelog
14
+
15
+ ## [0.4.0] - 2025-10-14
16
+
17
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.3.0...v0.4.0)
18
+
19
+ ### Changes
20
+ - Add `Shale::Builder::NestedValidations`
21
+ - Add `Shale::Builder#alias_attribute`
22
+
23
+ ## [0.3.0] - 2025-09-24
24
+
25
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.1...v0.3.0)
26
+
27
+ ### Changes
28
+ - Add support for `BigDecimal`
14
29
 
15
30
  ## [0.2.1] - 2024-07-16
16
31
 
17
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.1...v0.2.0)
32
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.0...v0.2.1)
18
33
 
19
34
  ### Changes
20
35
  - Add additional sorbet type documentation
21
36
 
22
37
  ## [0.2.0] - 2024-06-11
23
38
 
24
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.2.0...v0.1.9)
39
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.9...v0.2.0)
25
40
 
26
41
  ### Changes
27
42
  - Add support for `return_type` and `setter_type` in custom primitive shale types
@@ -29,21 +44,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
29
44
 
30
45
  ## [0.1.9] - 2024-06-03
31
46
 
32
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.9...v0.1.8)
47
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.8...v0.1.9)
33
48
 
34
49
  ### Changes
35
50
  - Fix the signature of `new` class method
36
51
 
37
52
  ## [0.1.8] - 2024-05-15
38
53
 
39
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.8...v0.1.7)
54
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.7...v0.1.8)
40
55
 
41
56
  ### Changes
42
57
  - Sort attribute names in the tapioca compiler
43
58
 
44
59
  ## [0.1.7] - 2024-05-13
45
60
 
46
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.7...v0.1.6)
61
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.6...v0.1.7)
47
62
 
48
63
  ### Changes
49
64
  - Drop support for Ruby 3.0
@@ -51,35 +66,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
51
66
 
52
67
  ## [0.1.6] - 2024-05-13
53
68
 
54
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.6...v0.1.5)
69
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.5...v0.1.6)
55
70
 
56
71
  ### Changes
57
72
  - Add support for doc strings in the tapioca compiler
58
73
 
59
74
  ## [0.1.5] - 2024-05-13
60
75
 
61
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.5...v0.1.4)
76
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.4...v0.1.5)
62
77
 
63
78
  ### Changes
64
79
  - Fix a bug in the tapioca compiler
65
80
 
66
81
  ## [0.1.4] - 2024-05-13
67
82
 
68
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.4...v0.1.3)
83
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.3...v0.1.4)
69
84
 
70
85
  ### Changes
71
86
  - Add a tapioca compiler for shale and shale builder
72
87
 
73
88
  ## [0.1.3] - 2023-11-23
74
89
 
75
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.3...v0.1.2)
90
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.2...v0.1.3)
76
91
 
77
92
  ### Changes
78
93
  - Change shale version dependency from `< 1.0` to `< 2.0`
79
94
 
80
95
  ## [0.1.2] - 2023-10-11
81
96
 
82
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.2...v0.1.1)
97
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.1...v0.1.2)
83
98
 
84
99
  ### Changes
85
100
  - Add support for collections
@@ -87,14 +102,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
87
102
 
88
103
  ## [0.1.1] - 2023-02-22
89
104
 
90
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.1...v0.1.0)
105
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.0...v0.1.1)
91
106
 
92
107
  ### Changes
93
108
  - Add support for inheritance
94
109
 
95
110
  ## [0.1.0] - 2023-02-21
96
111
 
97
- [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.1.0...v0.0.0)
112
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.0.0...v0.1.0)
98
113
 
99
114
  ### Changes
100
115
  - 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.1)
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,82 @@ 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
+ require 'shale/builder'
274
+
275
+ class Amount < Shale::Mapper
276
+ include Shale::Builder
277
+
278
+ attribute :value, Shale::Type::Float
279
+ attribute :currency, Shale::Type::String
280
+
281
+ alias_attribute :val, :value
282
+ end
283
+
284
+ a = Amount.build do |a|
285
+ a.val = 3.2
286
+ end
287
+
288
+ a.val #=> 3.2
289
+ a.value #=> 3.2
290
+ ```
291
+
216
292
  ### Sorbet support
217
293
 
218
294
  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.1'
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
@@ -136,8 +140,24 @@ module Shale
136
140
  RUBY
137
141
  end
138
142
 
139
- end
143
+ # Create an alias for the getter and setter of an attribute.
144
+ sig { params(new_name: Symbol, old_name: Symbol).void }
145
+ def alias_attribute(new_name, old_name)
146
+ attr = attributes.fetch(old_name)
147
+ (attr.aliases ||= []) << new_name
140
148
 
149
+ builder_methods_module.class_eval <<~RUBY, __FILE__, __LINE__ + 1
150
+ def #{new_name}
151
+ #{old_name}
152
+ end
153
+
154
+ def #{new_name}=(val)
155
+ self.#{old_name} = val
156
+ end
157
+ RUBY
158
+ end
159
+
160
+ end
141
161
  mixes_in_class_methods(ClassMethods)
142
162
 
143
163
  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.1
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