README.md in shale-builder-0.1.9 vs README.md in shale-builder-0.2.0

- old
+ new

@@ -49,15 +49,11 @@ class Amount < Shale::Mapper include Shale::Builder attribute :value, Shale::Type::Float - attribute :currency, Shale::Type::String, doc: <<~DOC - This is some custom documentation that can be used by sorbet. - It will be used by the tapioca DSL compiler - to generate the RBI documentation for this attribute. - DOC + attribute :currency, Shale::Type::String end ``` Now instead of creating an instance like that: @@ -72,40 +68,10 @@ a.value = 2.3 a.currency = 'PLN' end ``` -If you use sorbet and run `bundle exec tapioca dsl` you'll get the following RBI file. - -```rb -# typed: true - -class Amount - include ShaleAttributeMethods - - module ShaleAttributeMethods - sig { returns(T.nilable(Float)) } - def value; end - - sig { params(value: T.nilable(Float)).returns(T.nilable(Float)) } - def value=(value); end - - # This is some custom documentation that can be used by sorbet. - # It will be used by the tapioca DSL compiler - # to generate the RBI documentation for this attribute. - sig { returns(T.nilable(String)) } - def currency; end - - # This is some custom documentation that can be used by sorbet. - # It will be used by the tapioca DSL compiler - # to generate the RBI documentation for this attribute. - sig { params(value: T.nilable(String)).returns(T.nilable(String)) } - def currency=(value); end - end -end -``` - ### Building nested objects It's kind of pointless when you've got a flat structure. It really shines when nested objects come into play. @@ -242,9 +208,148 @@ if some_condition? p.expiration_year = 2045 p.expiration_month = 12 end end +end +``` + +### Sorbet support + +Shale-builder adds support for sorbet and tapioca. + +You can leverage an additional `doc` keyword argument in `attribute` definitions. +It will be used to generate a comment in the RBI file. + +```rb +require 'shale/builder' + +class Amount < Shale::Mapper + include Shale::Builder + + attribute :value, Shale::Type::Float + attribute :currency, Shale::Type::String, doc: <<~DOC + This is some custom documentation that can be used by sorbet. + It will be used by the tapioca DSL compiler + to generate the RBI documentation for this attribute. + DOC +end +``` + +If you use sorbet and run `bundle exec tapioca dsl` you'll get the following RBI file. + +```rb +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for dynamic methods in `Amount`. +# Please instead update this file by running `bin/tapioca dsl Amount`. + +class Amount + include ShaleAttributeMethods + + module ShaleAttributeMethods + sig { returns(T.nilable(Float)) } + def value; end + + sig { params(value: T.nilable(Float)).returns(T.nilable(Float)) } + def value=(value); end + + # This is some custom documentation that can be used by sorbet. + # It will be used by the tapioca DSL compiler + # to generate the RBI documentation for this attribute. + sig { returns(T.nilable(String)) } + def currency; end + + # This is some custom documentation that can be used by sorbet. + # It will be used by the tapioca DSL compiler + # to generate the RBI documentation for this attribute. + sig { params(value: T.nilable(String)).returns(T.nilable(String)) } + def currency=(value); end + end +end +``` + +#### Primitive types + +If you define custom primitive types in Shale by inheriting from `Shale::Type::Value` +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. + +```rb +def self.return_type = T.nilable(String) +``` + +You can also describe the accepted argument type in the setter by defining the `setter_type` method that returns a sorbet type. + +```rb +def self.setter_type = T.any(String, Float, Integer) +``` + +Here is a full example. + +```rb +# typed: true +require 'shale/builder' + +# Cast from XML string to BigDecimal. +# And from BigDecimal to XML string. +class BigDecimalShaleType < Shale::Type::Value + class << self + extend T::Sig + + # the return type of the field that uses this class as its type + def return_type = T.nilable(BigDecimal) + # the type of the argument given to a setter of the field + # that uses this class as its type + def setter_type = T.any(BigDecimal, String, NilClass) + + # Decode from XML. + sig { params(value: T.any(BigDecimal, String, NilClass)).returns(T.nilable(BigDecimal)) } + def cast(value) + return if value.nil? + + BigDecimal(value) + end + + # Encode to XML. + # + # @param value: Value to convert to XML + sig { params(value: T.nilable(BigDecimal)).returns(T.nilable(String)) } + def as_xml_value(value) + return if value.nil? + + value.to_s('F') + end + end +end + +class Amount < Shale::Mapper + include Shale::Builder + + # `value` uses BigDecimalShaleType as its type + attribute :value, BigDecimalShaleType +end +``` + +After running `bundle exec tapioca dsl` you'll get the following RBI file. + +```rb +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for dynamic methods in `Amount`. +# Please instead update this file by running `bin/tapioca dsl Amount`. + +class Amount + include ShaleAttributeMethods + + module ShaleAttributeMethods + sig { returns(T.nilable(::BigDecimal)) } + def value; end + + sig { params(value: T.nilable(T.any(::BigDecimal, ::String))).returns(T.nilable(T.any(::BigDecimal, ::String))) } + def value=(value); end + end end ``` ## Development