shale-builder 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ad79ec1b93dc534e3c8fb9b6b2a141bc186148b4ce21cbd3ce1f090b3445323
4
- data.tar.gz: f9b8d364e8418d94b69046257d9470ff26596601fbffd5b3454f82ef152d98d7
3
+ metadata.gz: a1194476cdc1f12fedaee4208834a474caf3397d0b4cab907f20648d5e812394
4
+ data.tar.gz: ce1363ceced738925bbe89abc807daa9e7cc54099244181083e0c35364d5c76d
5
5
  SHA512:
6
- metadata.gz: 96d7fcf6887a218e486fded1f9b0cee50cf275f0788482d4a2a1a0e5bc65712b86ea708d596d1b0b9c40dbb548091dc1324cb6c6dca567ae56f50a06d1222f2c
7
- data.tar.gz: 1e861780af38b06aee8440419a7d67313f83d535954793362a27a7ae196c6bd49c0485369186655b11602194dcffea4ed6f6a7b8c16f64fa2a6b5ec3a256162d
6
+ metadata.gz: 8fb3b29c2765d93b8cbcdd35ec04085d50bbc918bb6c5e2bec62ce80cfeb75d2af3a815956b68d31b882e7c46db8929f48039cb8a0880b4b50766581de0a811d
7
+ data.tar.gz: 3e2c7f826e65b70ac6c2efca789b836ac476594bee5e93d265c56a88f9ec2921fdff7a5352baf33a2ca1a887efdb824d24b2335481fb9fb5bda64547e69c7b05
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.2.0] - 2024-06-11
2
+
3
+ - Add support for `return_type` and `setter_type` in custom primitive shale types
4
+ - Add a more thorough description of sorbet and tapioca support in the README
5
+
1
6
  ## [0.1.9] - 2024-06-03
2
7
 
3
8
  - Fix the signature of `new` class method
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shale-builder (0.1.9)
4
+ shale-builder (0.2.0)
5
5
  booleans (>= 0.1)
6
6
  shale (< 2.0)
7
7
  sorbet-runtime (> 0.5)
data/README.md CHANGED
@@ -51,11 +51,7 @@ class Amount < Shale::Mapper
51
51
  include Shale::Builder
52
52
 
53
53
  attribute :value, Shale::Type::Float
54
- attribute :currency, Shale::Type::String, doc: <<~DOC
55
- This is some custom documentation that can be used by sorbet.
56
- It will be used by the tapioca DSL compiler
57
- to generate the RBI documentation for this attribute.
58
- DOC
54
+ attribute :currency, Shale::Type::String
59
55
  end
60
56
  ```
61
57
 
@@ -74,36 +70,6 @@ amount = Amount.build do |a|
74
70
  end
75
71
  ```
76
72
 
77
- If you use sorbet and run `bundle exec tapioca dsl` you'll get the following RBI file.
78
-
79
- ```rb
80
- # typed: true
81
-
82
- class Amount
83
- include ShaleAttributeMethods
84
-
85
- module ShaleAttributeMethods
86
- sig { returns(T.nilable(Float)) }
87
- def value; end
88
-
89
- sig { params(value: T.nilable(Float)).returns(T.nilable(Float)) }
90
- def value=(value); end
91
-
92
- # This is some custom documentation that can be used by sorbet.
93
- # It will be used by the tapioca DSL compiler
94
- # to generate the RBI documentation for this attribute.
95
- sig { returns(T.nilable(String)) }
96
- def currency; end
97
-
98
- # This is some custom documentation that can be used by sorbet.
99
- # It will be used by the tapioca DSL compiler
100
- # to generate the RBI documentation for this attribute.
101
- sig { params(value: T.nilable(String)).returns(T.nilable(String)) }
102
- def currency=(value); end
103
- end
104
- end
105
- ```
106
-
107
73
  ### Building nested objects
108
74
 
109
75
  It's kind of pointless when you've got a flat structure.
@@ -247,6 +213,145 @@ transaction = Transaction.build do |t|
247
213
  end
248
214
  ```
249
215
 
216
+ ### Sorbet support
217
+
218
+ Shale-builder adds support for sorbet and tapioca.
219
+
220
+ You can leverage an additional `doc` keyword argument in `attribute` definitions.
221
+ It will be used to generate a comment in the RBI file.
222
+
223
+ ```rb
224
+ require 'shale/builder'
225
+
226
+ class Amount < Shale::Mapper
227
+ include Shale::Builder
228
+
229
+ attribute :value, Shale::Type::Float
230
+ attribute :currency, Shale::Type::String, doc: <<~DOC
231
+ This is some custom documentation that can be used by sorbet.
232
+ It will be used by the tapioca DSL compiler
233
+ to generate the RBI documentation for this attribute.
234
+ DOC
235
+ end
236
+ ```
237
+
238
+ If you use sorbet and run `bundle exec tapioca dsl` you'll get the following RBI file.
239
+
240
+ ```rb
241
+ # typed: true
242
+
243
+ # DO NOT EDIT MANUALLY
244
+ # This is an autogenerated file for dynamic methods in `Amount`.
245
+ # Please instead update this file by running `bin/tapioca dsl Amount`.
246
+
247
+ class Amount
248
+ include ShaleAttributeMethods
249
+
250
+ module ShaleAttributeMethods
251
+ sig { returns(T.nilable(Float)) }
252
+ def value; end
253
+
254
+ sig { params(value: T.nilable(Float)).returns(T.nilable(Float)) }
255
+ def value=(value); end
256
+
257
+ # This is some custom documentation that can be used by sorbet.
258
+ # It will be used by the tapioca DSL compiler
259
+ # to generate the RBI documentation for this attribute.
260
+ sig { returns(T.nilable(String)) }
261
+ def currency; end
262
+
263
+ # This is some custom documentation that can be used by sorbet.
264
+ # It will be used by the tapioca DSL compiler
265
+ # to generate the RBI documentation for this attribute.
266
+ sig { params(value: T.nilable(String)).returns(T.nilable(String)) }
267
+ def currency=(value); end
268
+ end
269
+ end
270
+ ```
271
+
272
+ #### Primitive types
273
+
274
+ If you define custom primitive types in Shale by inheriting from `Shale::Type::Value`
275
+ you can describe the return type of the getter of the field that uses this primitive type by defining the `return_type` method that returns a sorbet type.
276
+
277
+ ```rb
278
+ def self.return_type = T.nilable(String)
279
+ ```
280
+
281
+ You can also describe the accepted argument type in the setter by defining the `setter_type` method that returns a sorbet type.
282
+
283
+ ```rb
284
+ def self.setter_type = T.any(String, Float, Integer)
285
+ ```
286
+
287
+ Here is a full example.
288
+
289
+ ```rb
290
+ # typed: true
291
+ require 'shale/builder'
292
+
293
+ # Cast from XML string to BigDecimal.
294
+ # And from BigDecimal to XML string.
295
+ class BigDecimalShaleType < Shale::Type::Value
296
+ class << self
297
+ extend T::Sig
298
+
299
+ # the return type of the field that uses this class as its type
300
+ def return_type = T.nilable(BigDecimal)
301
+ # the type of the argument given to a setter of the field
302
+ # that uses this class as its type
303
+ def setter_type = T.any(BigDecimal, String, NilClass)
304
+
305
+ # Decode from XML.
306
+ sig { params(value: T.any(BigDecimal, String, NilClass)).returns(T.nilable(BigDecimal)) }
307
+ def cast(value)
308
+ return if value.nil?
309
+
310
+ BigDecimal(value)
311
+ end
312
+
313
+ # Encode to XML.
314
+ #
315
+ # @param value: Value to convert to XML
316
+ sig { params(value: T.nilable(BigDecimal)).returns(T.nilable(String)) }
317
+ def as_xml_value(value)
318
+ return if value.nil?
319
+
320
+ value.to_s('F')
321
+ end
322
+ end
323
+ end
324
+
325
+ class Amount < Shale::Mapper
326
+ include Shale::Builder
327
+
328
+ # `value` uses BigDecimalShaleType as its type
329
+ attribute :value, BigDecimalShaleType
330
+ end
331
+ ```
332
+
333
+ After running `bundle exec tapioca dsl` you'll get the following RBI file.
334
+
335
+ ```rb
336
+ # typed: true
337
+
338
+ # DO NOT EDIT MANUALLY
339
+ # This is an autogenerated file for dynamic methods in `Amount`.
340
+ # Please instead update this file by running `bin/tapioca dsl Amount`.
341
+
342
+ class Amount
343
+ include ShaleAttributeMethods
344
+
345
+ module ShaleAttributeMethods
346
+ sig { returns(T.nilable(::BigDecimal)) }
347
+ def value; end
348
+
349
+ sig { params(value: T.nilable(T.any(::BigDecimal, ::String))).returns(T.nilable(T.any(::BigDecimal, ::String))) }
350
+ def value=(value); end
351
+ end
352
+ end
353
+ ```
354
+
250
355
  ## Development
251
356
 
252
357
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Shale
4
4
  module Builder
5
- VERSION = '0.1.9'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
@@ -37,7 +37,7 @@ module Tapioca
37
37
  attribute_names = constant.attributes.keys.sort
38
38
  attribute_names.each do |attribute_name|
39
39
  attribute = T.let(constant.attributes[attribute_name], ::Shale::Attribute)
40
- non_nilable_type, nilable_type = shale_type_to_sorbet_type(attribute)
40
+ non_nilable_type, nilable_type = shale_type_to_sorbet_return_type(attribute)
41
41
  type = nilable_type
42
42
  if attribute.collection?
43
43
  type = "T.nilable(T::Array[#{non_nilable_type}])"
@@ -69,6 +69,12 @@ module Tapioca
69
69
  mod.create_method(attribute.name, return_type: type, comments: comments)
70
70
  end
71
71
 
72
+ non_nilable_type, nilable_type = shale_type_to_sorbet_setter_type(attribute)
73
+ type = nilable_type
74
+ if attribute.collection?
75
+ type = "T.nilable(T::Array[#{non_nilable_type}])"
76
+ end
77
+
72
78
  # setter
73
79
  mod.create_method(
74
80
  "#{attribute.name}=",
@@ -106,22 +112,44 @@ module Tapioca
106
112
  )
107
113
 
108
114
  sig { params(attribute: ::Shale::Attribute).returns([String, String]) }
109
- def shale_type_to_sorbet_type(attribute)
115
+ def shale_type_to_sorbet_return_type(attribute)
110
116
  return_type = SHALE_TYPES_MAP[attribute.type]
111
- return complex_shale_type_to_sorbet_type(attribute) unless return_type
117
+ return complex_shale_type_to_sorbet_return_type(attribute) unless return_type
112
118
  return [T.must(return_type.name), T.must(return_type.name)] if attribute.collection? || attribute.default.is_a?(return_type)
113
119
 
114
120
  [T.must(return_type.name), "T.nilable(#{return_type.name})"]
115
121
  end
116
122
 
117
123
  sig { params(attribute: ::Shale::Attribute).returns([String, String]) }
118
- def complex_shale_type_to_sorbet_type(attribute)
124
+ def complex_shale_type_to_sorbet_return_type(attribute)
119
125
  return [T.cast(attribute.type.to_s, String), "T.nilable(#{attribute.type})"] unless attribute.type.respond_to?(:return_type)
120
126
 
121
127
  return_type_string = attribute.type.return_type.to_s
122
128
  [return_type_string, return_type_string]
123
129
  end
124
130
 
131
+ sig { params(attribute: ::Shale::Attribute).returns([String, String]) }
132
+ def shale_type_to_sorbet_setter_type(attribute)
133
+ setter_type = SHALE_TYPES_MAP[attribute.type]
134
+ return complex_shale_type_to_sorbet_setter_type(attribute) unless setter_type
135
+ return [T.must(setter_type.name), T.must(setter_type.name)] if attribute.collection? || attribute.default.is_a?(setter_type)
136
+
137
+ [T.must(setter_type.name), "T.nilable(#{setter_type.name})"]
138
+ end
139
+
140
+ sig { params(attribute: ::Shale::Attribute).returns([String, String]) }
141
+ def complex_shale_type_to_sorbet_setter_type(attribute)
142
+ if attribute.type.respond_to?(:setter_type)
143
+ setter_type_string = attribute.type.setter_type.to_s
144
+ [setter_type_string, setter_type_string]
145
+ elsif attribute.type.respond_to?(:return_type)
146
+ return_type_string = attribute.type.return_type.to_s
147
+ [return_type_string, return_type_string]
148
+ else
149
+ [T.cast(attribute.type.to_s, String), "T.nilable(#{attribute.type})"]
150
+ end
151
+ end
152
+
125
153
  end
126
154
  end
127
155
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shale-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateusz Drewniak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-03 00:00:00.000000000 Z
11
+ date: 2024-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: booleans