shale 1.1.0 → 1.2.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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +182 -84
- data/lib/shale/adapter/json.rb +10 -7
- data/lib/shale/adapter/toml_rb.rb +5 -3
- data/lib/shale/adapter/tomlib.rb +36 -0
- data/lib/shale/error.rb +14 -1
- data/lib/shale/mapper.rb +36 -30
- data/lib/shale/mapping/dict_base.rb +3 -1
- data/lib/shale/schema/json_generator/boolean.rb +2 -1
- data/lib/shale/schema/json_generator/collection.rb +2 -1
- data/lib/shale/schema/json_generator/date.rb +3 -1
- data/lib/shale/schema/json_generator/float.rb +2 -1
- data/lib/shale/schema/json_generator/integer.rb +2 -1
- data/lib/shale/schema/json_generator/object.rb +2 -0
- data/lib/shale/schema/json_generator/string.rb +2 -1
- data/lib/shale/schema/json_generator/time.rb +3 -1
- data/lib/shale/schema/json_generator/value.rb +2 -1
- data/lib/shale/type/boolean.rb +2 -0
- data/lib/shale/type/complex.rb +32 -18
- data/lib/shale/type/date.rb +2 -0
- data/lib/shale/type/float.rb +2 -0
- data/lib/shale/type/integer.rb +2 -0
- data/lib/shale/type/string.rb +2 -0
- data/lib/shale/type/time.rb +2 -0
- data/lib/shale/type.rb +56 -0
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +6 -4
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 81b22181e1c63b2757fdd137f09a185caf894de6d43c108119c18c9260b48afd
         | 
| 4 | 
            +
              data.tar.gz: 065bc2d6f8a6eec466b52574ed38846dc0b4e0315ba9b83fc0d24ed75066ef07
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9b106ac74372bc089093ee8c12238b48505cff4d318967e2760ef2842e9a783125227177fd5f2cb47b27872adc7cbbf0686226934132b5c8f346c71b92159c8a
         | 
| 7 | 
            +
              data.tar.gz: dcb0088d6f700f1654313a72156e9d1e4cd0c1b75b99a82cea17e12af96ced1407e358b1d0cc52e7e3f0a1c46cb19d702b3a49628a0da67e521a20906e006a6c
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,11 @@ | |
| 1 | 
            +
            ## [1.2.0] - 2024-10-31
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ### Added
         | 
| 4 | 
            +
            - Allow to pass adapter specific options
         | 
| 5 | 
            +
            - Allow to pass `additional_properties` option to JSON Schema generator
         | 
| 6 | 
            +
            - Allow to pass `description` option to JSON Schema generator
         | 
| 7 | 
            +
            - Support for symbol type aliases in attribute mappings
         | 
| 8 | 
            +
             | 
| 1 9 | 
             
            ## [1.1.0] - 2024-02-17
         | 
| 2 10 |  | 
| 3 11 | 
             
            ### Added
         | 
    
        data/README.md
    CHANGED
    
    | @@ -65,6 +65,7 @@ $ gem install shale | |
| 65 65 | 
             
            * [Using methods to extract and generate data](#using-methods-to-extract-and-generate-data)
         | 
| 66 66 | 
             
            * [Delegating fields to child attributes](#delegating-fields-to-child-attributes)
         | 
| 67 67 | 
             
            * [Additional options](#additional-options)
         | 
| 68 | 
            +
            * [Overriding attribute methods](#overriding-attribute-methods)
         | 
| 68 69 | 
             
            * [Using custom models](#using-custom-models)
         | 
| 69 70 | 
             
            * [Supported types](#supported-types)
         | 
| 70 71 | 
             
            * [Writing your own type](#writing-your-own-type)
         | 
| @@ -82,17 +83,17 @@ $ gem install shale | |
| 82 83 | 
             
            require 'shale'
         | 
| 83 84 |  | 
| 84 85 | 
             
            class Address < Shale::Mapper
         | 
| 85 | 
            -
              attribute :city,  | 
| 86 | 
            -
              attribute :street,  | 
| 87 | 
            -
              attribute :zip,  | 
| 86 | 
            +
              attribute :city, :string
         | 
| 87 | 
            +
              attribute :street, :string
         | 
| 88 | 
            +
              attribute :zip, :string
         | 
| 88 89 | 
             
            end
         | 
| 89 90 |  | 
| 90 91 | 
             
            class Person < Shale::Mapper
         | 
| 91 | 
            -
              attribute :first_name,  | 
| 92 | 
            -
              attribute :last_name,  | 
| 93 | 
            -
              attribute :age,  | 
| 94 | 
            -
              attribute :married,  | 
| 95 | 
            -
              attribute :hobbies,  | 
| 92 | 
            +
              attribute :first_name, :string
         | 
| 93 | 
            +
              attribute :last_name, :string
         | 
| 94 | 
            +
              attribute :age, :integer
         | 
| 95 | 
            +
              attribute :married, :boolean, default: -> { false }
         | 
| 96 | 
            +
              attribute :hobbies, :string, collection: true
         | 
| 96 97 | 
             
              attribute :address, Address
         | 
| 97 98 | 
             
            end
         | 
| 98 99 | 
             
            ```
         | 
| @@ -208,8 +209,8 @@ person.to_yaml | |
| 208 209 | 
             
            ### Converting TOML to object
         | 
| 209 210 |  | 
| 210 211 | 
             
            To use TOML with Shale you have to set adapter you want to use.
         | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 212 | 
            +
            It comes with adapters for [Tomlib](https://github.com/kgiszczak/tomlib) and
         | 
| 213 | 
            +
            [toml-rb](https://github.com/emancu/toml-rb).
         | 
| 213 214 | 
             
            For details see [Adapters](#adapters) section.
         | 
| 214 215 |  | 
| 215 216 | 
             
            To set it, first make sure Tomlib gem is installed:
         | 
| @@ -221,8 +222,8 @@ $ gem install tomlib | |
| 221 222 | 
             
            then setup adapter:
         | 
| 222 223 |  | 
| 223 224 | 
             
            ```ruby
         | 
| 224 | 
            -
            require 'tomlib'
         | 
| 225 | 
            -
            Shale.toml_adapter = Tomlib
         | 
| 225 | 
            +
            require 'sahle/adapter/tomlib'
         | 
| 226 | 
            +
            Shale.toml_adapter = Shale::Adapter::Tomlib
         | 
| 226 227 |  | 
| 227 228 | 
             
            # Alternatively if you'd like to use toml-rb, use:
         | 
| 228 229 | 
             
            require 'shale/adapter/toml_rb'
         | 
| @@ -442,8 +443,8 @@ By default keys are named the same as attributes. To use custom keys use: | |
| 442 443 |  | 
| 443 444 | 
             
            ```ruby
         | 
| 444 445 | 
             
            class Person < Shale::Mapper
         | 
| 445 | 
            -
              attribute :first_name,  | 
| 446 | 
            -
              attribute :last_name,  | 
| 446 | 
            +
              attribute :first_name, :string
         | 
| 447 | 
            +
              attribute :last_name, :string
         | 
| 447 448 |  | 
| 448 449 | 
             
              json do
         | 
| 449 450 | 
             
                map 'firstName', to: :first_name
         | 
| @@ -456,8 +457,8 @@ end | |
| 456 457 |  | 
| 457 458 | 
             
            ```ruby
         | 
| 458 459 | 
             
            class Person < Shale::Mapper
         | 
| 459 | 
            -
              attribute :first_name,  | 
| 460 | 
            -
              attribute :last_name,  | 
| 460 | 
            +
              attribute :first_name, :string
         | 
| 461 | 
            +
              attribute :last_name, :string
         | 
| 461 462 |  | 
| 462 463 | 
             
              yaml do
         | 
| 463 464 | 
             
                map 'firstName', to: :first_name
         | 
| @@ -470,8 +471,8 @@ end | |
| 470 471 |  | 
| 471 472 | 
             
            ```ruby
         | 
| 472 473 | 
             
            class Person < Shale::Mapper
         | 
| 473 | 
            -
              attribute :first_name,  | 
| 474 | 
            -
              attribute :last_name,  | 
| 474 | 
            +
              attribute :first_name, :string
         | 
| 475 | 
            +
              attribute :last_name, :string
         | 
| 475 476 |  | 
| 476 477 | 
             
              toml do
         | 
| 477 478 | 
             
                map 'firstName', to: :first_name
         | 
| @@ -488,8 +489,8 @@ to `:first_name` attribute and the second column to `:last_name`. | |
| 488 489 |  | 
| 489 490 | 
             
            ```ruby
         | 
| 490 491 | 
             
            class Person < Shale::Mapper
         | 
| 491 | 
            -
              attribute :first_name,  | 
| 492 | 
            -
              attribute :last_name,  | 
| 492 | 
            +
              attribute :first_name, :string
         | 
| 493 | 
            +
              attribute :last_name, :string
         | 
| 493 494 |  | 
| 494 495 | 
             
              csv do
         | 
| 495 496 | 
             
                map 'firstName', to: :first_name
         | 
| @@ -502,8 +503,8 @@ end | |
| 502 503 |  | 
| 503 504 | 
             
            ```ruby
         | 
| 504 505 | 
             
            class Person < Shale::Mapper
         | 
| 505 | 
            -
              attribute :first_name,  | 
| 506 | 
            -
              attribute :last_name,  | 
| 506 | 
            +
              attribute :first_name, :string
         | 
| 507 | 
            +
              attribute :last_name, :string
         | 
| 507 508 |  | 
| 508 509 | 
             
              hsh do
         | 
| 509 510 | 
             
                map 'firstName', to: :first_name
         | 
| @@ -518,9 +519,9 @@ XML is more complicated format than JSON or YAML. To map elements, attributes an | |
| 518 519 |  | 
| 519 520 | 
             
            ```ruby
         | 
| 520 521 | 
             
            class Address < Shale::Mapper
         | 
| 521 | 
            -
              attribute :street,  | 
| 522 | 
            -
              attribute :city,  | 
| 523 | 
            -
              attribute :zip,  | 
| 522 | 
            +
              attribute :street, :string
         | 
| 523 | 
            +
              attribute :city, :string
         | 
| 524 | 
            +
              attribute :zip, :string
         | 
| 524 525 |  | 
| 525 526 | 
             
              xml do
         | 
| 526 527 | 
             
                map_content to: :street
         | 
| @@ -530,10 +531,10 @@ class Address < Shale::Mapper | |
| 530 531 | 
             
            end
         | 
| 531 532 |  | 
| 532 533 | 
             
            class Person < Shale::Mapper
         | 
| 533 | 
            -
              attribute :first_name,  | 
| 534 | 
            -
              attribute :last_name,  | 
| 535 | 
            -
              attribute :age,  | 
| 536 | 
            -
              attribute :hobbies,  | 
| 534 | 
            +
              attribute :first_name, :string
         | 
| 535 | 
            +
              attribute :last_name, :string
         | 
| 536 | 
            +
              attribute :age, :integer
         | 
| 537 | 
            +
              attribute :hobbies, :string, collection: true
         | 
| 537 538 | 
             
              attribute :address, Address
         | 
| 538 539 |  | 
| 539 540 | 
             
              xml do
         | 
| @@ -572,7 +573,7 @@ You can use `cdata: true` option on `map_element` and `map_content` to handle CD | |
| 572 573 |  | 
| 573 574 | 
             
            ```ruby
         | 
| 574 575 | 
             
            class Address < Shale::Mapper
         | 
| 575 | 
            -
              attribute :content,  | 
| 576 | 
            +
              attribute :content, :string
         | 
| 576 577 |  | 
| 577 578 | 
             
              xml do
         | 
| 578 579 | 
             
                map_content to: :content, cdata: true
         | 
| @@ -580,7 +581,7 @@ class Address < Shale::Mapper | |
| 580 581 | 
             
            end
         | 
| 581 582 |  | 
| 582 583 | 
             
            class Person < Shale::Mapper
         | 
| 583 | 
            -
              attribute :first_name,  | 
| 584 | 
            +
              attribute :first_name, :string
         | 
| 584 585 | 
             
              attribute :address, Address
         | 
| 585 586 |  | 
| 586 587 | 
             
              xml do
         | 
| @@ -606,9 +607,9 @@ To map namespaced elements and attributes use `namespace` and `prefix` propertie | |
| 606 607 |  | 
| 607 608 | 
             
            ```ruby
         | 
| 608 609 | 
             
            class Person < Shale::Mapper
         | 
| 609 | 
            -
              attribute :first_name,  | 
| 610 | 
            -
              attribute :last_name,  | 
| 611 | 
            -
              attribute :age,  | 
| 610 | 
            +
              attribute :first_name, :string
         | 
| 611 | 
            +
              attribute :last_name, :string
         | 
| 612 | 
            +
              attribute :age, :integer
         | 
| 612 613 |  | 
| 613 614 | 
             
              xml do
         | 
| 614 615 | 
             
                root 'person'
         | 
| @@ -633,11 +634,11 @@ explicitly declare it on `map_attribute`). | |
| 633 634 |  | 
| 634 635 | 
             
            ```ruby
         | 
| 635 636 | 
             
            class Person < Shale::Mapper
         | 
| 636 | 
            -
              attribute :first_name,  | 
| 637 | 
            -
              attribute :middle_name,  | 
| 638 | 
            -
              attribute :last_name,  | 
| 639 | 
            -
              attribute :age,  | 
| 640 | 
            -
              attribute :hobby,  | 
| 637 | 
            +
              attribute :first_name, :string
         | 
| 638 | 
            +
              attribute :middle_name, :string
         | 
| 639 | 
            +
              attribute :last_name, :string
         | 
| 640 | 
            +
              attribute :age, :integer
         | 
| 641 | 
            +
              attribute :hobby, :string
         | 
| 641 642 |  | 
| 642 643 | 
             
              xml do
         | 
| 643 644 | 
             
                root 'person'
         | 
| @@ -673,9 +674,9 @@ For CSV the default is to render `nil` elements. | |
| 673 674 |  | 
| 674 675 | 
             
            ```ruby
         | 
| 675 676 | 
             
            class Person < Shale::Mapper
         | 
| 676 | 
            -
              attribute :first_name,  | 
| 677 | 
            -
              attribute :last_name,  | 
| 678 | 
            -
              attribute :age,  | 
| 677 | 
            +
              attribute :first_name, :string
         | 
| 678 | 
            +
              attribute :last_name, :string
         | 
| 679 | 
            +
              attribute :age, :integer
         | 
| 679 680 |  | 
| 680 681 | 
             
              json do
         | 
| 681 682 | 
             
                map 'first_name', to: :first_name, render_nil: true
         | 
| @@ -723,9 +724,9 @@ class Base < Shale::Mapper | |
| 723 724 | 
             
            end
         | 
| 724 725 |  | 
| 725 726 | 
             
            class Person < Base
         | 
| 726 | 
            -
              attribute :first_name,  | 
| 727 | 
            -
              attribute :last_name,  | 
| 728 | 
            -
              attribute :age,  | 
| 727 | 
            +
              attribute :first_name, :string
         | 
| 728 | 
            +
              attribute :last_name, :string
         | 
| 729 | 
            +
              attribute :age, :integer
         | 
| 729 730 |  | 
| 730 731 | 
             
              json do
         | 
| 731 732 | 
             
                # override default from Base class
         | 
| @@ -742,8 +743,8 @@ end | |
| 742 743 |  | 
| 743 744 | 
             
            ```ruby
         | 
| 744 745 | 
             
            class Person < Base
         | 
| 745 | 
            -
              attribute :first_name,  | 
| 746 | 
            -
              attribute :last_name,  | 
| 746 | 
            +
              attribute :first_name, :string
         | 
| 747 | 
            +
              attribute :last_name, :string
         | 
| 747 748 |  | 
| 748 749 | 
             
              json do
         | 
| 749 750 | 
             
                render_nil false
         | 
| @@ -762,9 +763,9 @@ you can use methods to do so: | |
| 762 763 |  | 
| 763 764 | 
             
            ```ruby
         | 
| 764 765 | 
             
            class Person < Shale::Mapper
         | 
| 765 | 
            -
              attribute :hobbies,  | 
| 766 | 
            -
              attribute :street,  | 
| 767 | 
            -
              attribute :city,  | 
| 766 | 
            +
              attribute :hobbies, :string, collection: true
         | 
| 767 | 
            +
              attribute :street, :string
         | 
| 768 | 
            +
              attribute :city, :string
         | 
| 768 769 |  | 
| 769 770 | 
             
              json do
         | 
| 770 771 | 
             
                map 'hobbies', using: { from: :hobbies_from_json, to: :hobbies_to_json }
         | 
| @@ -853,7 +854,7 @@ You can also pass a `context` object that will be available in extractor/generat | |
| 853 854 |  | 
| 854 855 | 
             
            ```ruby
         | 
| 855 856 | 
             
            class Person < Shale::Mapper
         | 
| 856 | 
            -
              attribute :password,  | 
| 857 | 
            +
              attribute :password, :string
         | 
| 857 858 |  | 
| 858 859 | 
             
              json do
         | 
| 859 860 | 
             
                map 'password', using: { from: :password_from_json, to: :password_to_json }
         | 
| @@ -883,7 +884,7 @@ If you want to work on multiple elements at a time you can group them using `gro | |
| 883 884 |  | 
| 884 885 | 
             
            ```ruby
         | 
| 885 886 | 
             
            class Person < Shale::Mapper
         | 
| 886 | 
            -
              attribute :name,  | 
| 887 | 
            +
              attribute :name, :string
         | 
| 887 888 |  | 
| 888 889 | 
             
              json do
         | 
| 889 890 | 
             
                group from: :name_from_json, to: :name_to_json do
         | 
| @@ -934,12 +935,12 @@ To delegate fields to child complex types you can use `receiver: :child` declara | |
| 934 935 |  | 
| 935 936 | 
             
            ```ruby
         | 
| 936 937 | 
             
            class Address < Shale::Mapper
         | 
| 937 | 
            -
              attribute :city,  | 
| 938 | 
            -
              attribute :street,  | 
| 938 | 
            +
              attribute :city, :string
         | 
| 939 | 
            +
              attribute :street, :string
         | 
| 939 940 | 
             
            end
         | 
| 940 941 |  | 
| 941 942 | 
             
            class Person < Shale::Mapper
         | 
| 942 | 
            -
              attribute :name,  | 
| 943 | 
            +
              attribute :name, :string
         | 
| 943 944 | 
             
              attribute :address, Address
         | 
| 944 945 |  | 
| 945 946 | 
             
              json do
         | 
| @@ -1059,8 +1060,8 @@ names and shouldn't be included in the returned collection. It also accepts all | |
| 1059 1060 |  | 
| 1060 1061 | 
             
            ```ruby
         | 
| 1061 1062 | 
             
            class Person
         | 
| 1062 | 
            -
              attribute :first_name,  | 
| 1063 | 
            -
              attribute :last_name,  | 
| 1063 | 
            +
              attribute :first_name, :string
         | 
| 1064 | 
            +
              attribute :last_name, :string
         | 
| 1064 1065 | 
             
            end
         | 
| 1065 1066 |  | 
| 1066 1067 | 
             
            people = Person.from_csv(<<~DATA, headers: true, col_sep: '|')
         | 
| @@ -1085,6 +1086,63 @@ Person.to_csv(people, headers: true, col_sep: '|') | |
| 1085 1086 | 
             
            # James|Sixpack
         | 
| 1086 1087 | 
             
            ```
         | 
| 1087 1088 |  | 
| 1089 | 
            +
            Most adapters accept options specific to them. Eg. if you want to be able to work
         | 
| 1090 | 
            +
            with NaN values in JSON:
         | 
| 1091 | 
            +
             | 
| 1092 | 
            +
            ```ruby
         | 
| 1093 | 
            +
            class Person
         | 
| 1094 | 
            +
              attribute :age, :float
         | 
| 1095 | 
            +
            end
         | 
| 1096 | 
            +
             | 
| 1097 | 
            +
            person = Person.from_json('{"age": NaN}', allow_nan: true)
         | 
| 1098 | 
            +
             | 
| 1099 | 
            +
            # =>
         | 
| 1100 | 
            +
            #
         | 
| 1101 | 
            +
            # #<Person:0x0000000113d7a488 @age=Float::NAN>
         | 
| 1102 | 
            +
             | 
| 1103 | 
            +
            Person.to_json(person, allow_nan: true)
         | 
| 1104 | 
            +
             | 
| 1105 | 
            +
            # =>
         | 
| 1106 | 
            +
            #
         | 
| 1107 | 
            +
            # {
         | 
| 1108 | 
            +
            #   "age": NaN
         | 
| 1109 | 
            +
            # }
         | 
| 1110 | 
            +
            ```
         | 
| 1111 | 
            +
             | 
| 1112 | 
            +
            ### Overriding attribute methods
         | 
| 1113 | 
            +
             | 
| 1114 | 
            +
            It's possible to override an attribute method to change its output:
         | 
| 1115 | 
            +
             | 
| 1116 | 
            +
            ```ruby
         | 
| 1117 | 
            +
            class Person < Shale::Mapper
         | 
| 1118 | 
            +
              attribute :gender, :string
         | 
| 1119 | 
            +
             | 
| 1120 | 
            +
              def gender
         | 
| 1121 | 
            +
                if super == 'm'
         | 
| 1122 | 
            +
                  'male'
         | 
| 1123 | 
            +
                else
         | 
| 1124 | 
            +
                  'female'
         | 
| 1125 | 
            +
                end
         | 
| 1126 | 
            +
              end
         | 
| 1127 | 
            +
            end
         | 
| 1128 | 
            +
             | 
| 1129 | 
            +
            puts Person.from_json('{"gender":"m"}')
         | 
| 1130 | 
            +
             | 
| 1131 | 
            +
            # =>
         | 
| 1132 | 
            +
            #
         | 
| 1133 | 
            +
            # #<Person:0x00007f9bc3086d60
         | 
| 1134 | 
            +
            #  @gender="male">
         | 
| 1135 | 
            +
            ```
         | 
| 1136 | 
            +
             | 
| 1137 | 
            +
            Be conscious that the original attribute value will be lost after its transformation though:
         | 
| 1138 | 
            +
             | 
| 1139 | 
            +
            ```ruby
         | 
| 1140 | 
            +
            puts User.from_json('{"gender":"m"}').to_json
         | 
| 1141 | 
            +
            # => {"gender":"male"}
         | 
| 1142 | 
            +
            ```
         | 
| 1143 | 
            +
             | 
| 1144 | 
            +
            It'll no longer return gender `m`.
         | 
| 1145 | 
            +
             | 
| 1088 1146 | 
             
            ### Using custom models
         | 
| 1089 1147 |  | 
| 1090 1148 | 
             
            By default Shale combines mapper and model into one class. If you want to use your own classes
         | 
| @@ -1102,15 +1160,15 @@ end | |
| 1102 1160 | 
             
            class AddressMapper < Shale::Mapper
         | 
| 1103 1161 | 
             
              model Address
         | 
| 1104 1162 |  | 
| 1105 | 
            -
              attribute :street,  | 
| 1106 | 
            -
              attribute :city,  | 
| 1163 | 
            +
              attribute :street, :string
         | 
| 1164 | 
            +
              attribute :city, :string
         | 
| 1107 1165 | 
             
            end
         | 
| 1108 1166 |  | 
| 1109 1167 | 
             
            class PersonMapper < Shale::Mapper
         | 
| 1110 1168 | 
             
              model Person
         | 
| 1111 1169 |  | 
| 1112 | 
            -
              attribute :first_name,  | 
| 1113 | 
            -
              attribute :last_name,  | 
| 1170 | 
            +
              attribute :first_name, :string
         | 
| 1171 | 
            +
              attribute :last_name, :string
         | 
| 1114 1172 | 
             
              attribute :address, AddressMapper
         | 
| 1115 1173 | 
             
            end
         | 
| 1116 1174 |  | 
| @@ -1150,12 +1208,21 @@ PersonMapper.to_json(person, pretty: true) | |
| 1150 1208 |  | 
| 1151 1209 | 
             
            Shale supports these types out of the box:
         | 
| 1152 1210 |  | 
| 1153 | 
            -
            - `Shale::Type::Boolean`
         | 
| 1154 | 
            -
            - `Shale::Type::Date`
         | 
| 1155 | 
            -
            - `Shale::Type::Float`
         | 
| 1156 | 
            -
            - `Shale::Type::Integer`
         | 
| 1157 | 
            -
            - `Shale::Type::String`
         | 
| 1158 | 
            -
            - `Shale::Type::Time`
         | 
| 1211 | 
            +
            - `:boolean` (`Shale::Type::Boolean`)
         | 
| 1212 | 
            +
            - `:date` (`Shale::Type::Date`)
         | 
| 1213 | 
            +
            - `:float` (`Shale::Type::Float`)
         | 
| 1214 | 
            +
            - `:integer` (`Shale::Type::Integer`)
         | 
| 1215 | 
            +
            - `:string` (`Shale::Type::String`)
         | 
| 1216 | 
            +
            - `:time` (`Shale::Type::Time`)
         | 
| 1217 | 
            +
             | 
| 1218 | 
            +
            The symbol type alias and the type class are interchangeable:
         | 
| 1219 | 
            +
             | 
| 1220 | 
            +
            ```ruby
         | 
| 1221 | 
            +
            class Person < Shale::Mapper
         | 
| 1222 | 
            +
              attribute :age, Shale::Type::Integer
         | 
| 1223 | 
            +
              # attribute :age, :integer
         | 
| 1224 | 
            +
            end
         | 
| 1225 | 
            +
            ```
         | 
| 1159 1226 |  | 
| 1160 1227 | 
             
            ### Writing your own type
         | 
| 1161 1228 |  | 
| @@ -1171,6 +1238,31 @@ class MyIntegerType < Shale::Type::Value | |
| 1171 1238 | 
             
            end
         | 
| 1172 1239 | 
             
            ```
         | 
| 1173 1240 |  | 
| 1241 | 
            +
            Then you can use it in your model:
         | 
| 1242 | 
            +
             | 
| 1243 | 
            +
            ```ruby
         | 
| 1244 | 
            +
            class Person < Shale::Mapper
         | 
| 1245 | 
            +
              attribute :age, MyIntegerType
         | 
| 1246 | 
            +
            end
         | 
| 1247 | 
            +
            ```
         | 
| 1248 | 
            +
             | 
| 1249 | 
            +
            You can also register your own type with a symbol alias if you
         | 
| 1250 | 
            +
            intend to use it often.
         | 
| 1251 | 
            +
             | 
| 1252 | 
            +
            ```ruby
         | 
| 1253 | 
            +
            require 'shale/type'
         | 
| 1254 | 
            +
             | 
| 1255 | 
            +
            Shale::Type.register(:my_integer, MyIntegerType)
         | 
| 1256 | 
            +
            ```
         | 
| 1257 | 
            +
             | 
| 1258 | 
            +
            Then you can use it like this:
         | 
| 1259 | 
            +
             | 
| 1260 | 
            +
            ```ruby
         | 
| 1261 | 
            +
            class Person < Shale::Mapper
         | 
| 1262 | 
            +
              attribute :age, :my_integer
         | 
| 1263 | 
            +
            end
         | 
| 1264 | 
            +
            ```
         | 
| 1265 | 
            +
             | 
| 1174 1266 | 
             
            ### Adapters
         | 
| 1175 1267 |  | 
| 1176 1268 | 
             
            Shale uses adapters for parsing and generating documents.
         | 
| @@ -1323,18 +1415,18 @@ require 'shale/schema' | |
| 1323 1415 | 
             
            class PersonMapper < Shale::Mapper
         | 
| 1324 1416 | 
             
              model Person
         | 
| 1325 1417 |  | 
| 1326 | 
            -
              attribute :first_name,  | 
| 1327 | 
            -
              attribute :last_name,  | 
| 1328 | 
            -
              attribute :address,  | 
| 1329 | 
            -
              attribute :age,  | 
| 1418 | 
            +
              attribute :first_name, :string
         | 
| 1419 | 
            +
              attribute :last_name, :string
         | 
| 1420 | 
            +
              attribute :address, :string
         | 
| 1421 | 
            +
              attribute :age, :integer
         | 
| 1330 1422 |  | 
| 1331 1423 | 
             
              json do
         | 
| 1332 | 
            -
                properties max_properties: 5
         | 
| 1424 | 
            +
                properties max_properties: 5, additional_properties: false
         | 
| 1333 1425 |  | 
| 1334 1426 | 
             
                map "first_name", to: :first_name, schema: { required: true }
         | 
| 1335 1427 | 
             
                map "last_name", to: :last_name, schema: { required: true }
         | 
| 1336 | 
            -
                map "address", to: : | 
| 1337 | 
            -
                map "age", to: :age, schema: { minimum: 1, maximum: 150 }
         | 
| 1428 | 
            +
                map "address", to: :address, schema: { max_length: 128, description: "Street, home number, city and country" }
         | 
| 1429 | 
            +
                map "age", to: :age, schema: { minimum: 1, maximum: 150, description: "Person age" }
         | 
| 1338 1430 | 
             
              end
         | 
| 1339 1431 | 
             
            end
         | 
| 1340 1432 |  | 
| @@ -1352,7 +1444,6 @@ Shale::Schema.to_json( | |
| 1352 1444 | 
             
            #   "$defs": {
         | 
| 1353 1445 | 
             
            #     "Person": {
         | 
| 1354 1446 | 
             
            #       "type": "object",
         | 
| 1355 | 
            -
            #       "maxProperties": 5,
         | 
| 1356 1447 | 
             
            #       "properties": {
         | 
| 1357 1448 | 
             
            #         "first_name": {
         | 
| 1358 1449 | 
             
            #           "type": "string"
         | 
| @@ -1360,23 +1451,30 @@ Shale::Schema.to_json( | |
| 1360 1451 | 
             
            #         "last_name": {
         | 
| 1361 1452 | 
             
            #           "type": "string"
         | 
| 1362 1453 | 
             
            #         },
         | 
| 1363 | 
            -
            #         " | 
| 1454 | 
            +
            #         "address": {
         | 
| 1364 1455 | 
             
            #           "type": [
         | 
| 1365 | 
            -
            #             " | 
| 1456 | 
            +
            #             "string",
         | 
| 1366 1457 | 
             
            #             "null"
         | 
| 1367 1458 | 
             
            #           ],
         | 
| 1368 | 
            -
            # | 
| 1369 | 
            -
            # | 
| 1370 | 
            -
            # | 
| 1371 | 
            -
            #         " | 
| 1459 | 
            +
            #           "maxLength": 128,
         | 
| 1460 | 
            +
            #           "description": "Street, home number, city and country"
         | 
| 1461 | 
            +
            #         },
         | 
| 1462 | 
            +
            #         "age": {
         | 
| 1372 1463 | 
             
            #           "type": [
         | 
| 1373 | 
            -
            #             " | 
| 1464 | 
            +
            #             "integer",
         | 
| 1374 1465 | 
             
            #             "null"
         | 
| 1375 1466 | 
             
            #           ],
         | 
| 1376 | 
            -
            #           " | 
| 1467 | 
            +
            #           "minimum": 1,
         | 
| 1468 | 
            +
            #           "maximum": 150,
         | 
| 1469 | 
            +
            #           "description": "Person age"
         | 
| 1377 1470 | 
             
            #         }
         | 
| 1378 1471 | 
             
            #       },
         | 
| 1379 | 
            -
            #       "required": [ | 
| 1472 | 
            +
            #       "required": [
         | 
| 1473 | 
            +
            #         "first_name",
         | 
| 1474 | 
            +
            #         "last_name"
         | 
| 1475 | 
            +
            #       ],
         | 
| 1476 | 
            +
            #       "maxProperties": 5,
         | 
| 1477 | 
            +
            #       "additionalProperties": false
         | 
| 1380 1478 | 
             
            #     }
         | 
| 1381 1479 | 
             
            #   }
         | 
| 1382 1480 | 
             
            # }
         | 
    
        data/lib/shale/adapter/json.rb
    CHANGED
    
    | @@ -11,27 +11,30 @@ module Shale | |
| 11 11 | 
             
                  # Parse JSON into Hash
         | 
| 12 12 | 
             
                  #
         | 
| 13 13 | 
             
                  # @param [String] json JSON document
         | 
| 14 | 
            +
                  # @param [Hash] options
         | 
| 14 15 | 
             
                  #
         | 
| 15 16 | 
             
                  # @return [Hash]
         | 
| 16 17 | 
             
                  #
         | 
| 17 18 | 
             
                  # @api private
         | 
| 18 | 
            -
                  def self.load(json)
         | 
| 19 | 
            -
                    ::JSON.parse(json)
         | 
| 19 | 
            +
                  def self.load(json, **options)
         | 
| 20 | 
            +
                    ::JSON.parse(json, **options)
         | 
| 20 21 | 
             
                  end
         | 
| 21 22 |  | 
| 22 23 | 
             
                  # Serialize Hash into JSON
         | 
| 23 24 | 
             
                  #
         | 
| 24 25 | 
             
                  # @param [Hash] obj Hash object
         | 
| 25 | 
            -
                  # @param [ | 
| 26 | 
            +
                  # @param [Hash] options
         | 
| 26 27 | 
             
                  #
         | 
| 27 28 | 
             
                  # @return [String]
         | 
| 28 29 | 
             
                  #
         | 
| 29 30 | 
             
                  # @api private
         | 
| 30 | 
            -
                  def self.dump(obj,  | 
| 31 | 
            -
                     | 
| 32 | 
            -
             | 
| 31 | 
            +
                  def self.dump(obj, **options)
         | 
| 32 | 
            +
                    json_options = options.except(:pretty)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    if options[:pretty]
         | 
| 35 | 
            +
                      ::JSON.pretty_generate(obj, **json_options)
         | 
| 33 36 | 
             
                    else
         | 
| 34 | 
            -
                      ::JSON.generate(obj)
         | 
| 37 | 
            +
                      ::JSON.generate(obj, **json_options)
         | 
| 35 38 | 
             
                    end
         | 
| 36 39 | 
             
                  end
         | 
| 37 40 | 
             
                end
         | 
| @@ -4,29 +4,31 @@ require 'toml-rb' | |
| 4 4 |  | 
| 5 5 | 
             
            module Shale
         | 
| 6 6 | 
             
              module Adapter
         | 
| 7 | 
            -
                #  | 
| 7 | 
            +
                # TomlRB adapter
         | 
| 8 8 | 
             
                #
         | 
| 9 9 | 
             
                # @api public
         | 
| 10 10 | 
             
                class TomlRB
         | 
| 11 11 | 
             
                  # Parse TOML into Hash
         | 
| 12 12 | 
             
                  #
         | 
| 13 13 | 
             
                  # @param [String] toml TOML document
         | 
| 14 | 
            +
                  # @param [Hash] options
         | 
| 14 15 | 
             
                  #
         | 
| 15 16 | 
             
                  # @return [Hash]
         | 
| 16 17 | 
             
                  #
         | 
| 17 18 | 
             
                  # @api private
         | 
| 18 | 
            -
                  def self.load(toml)
         | 
| 19 | 
            +
                  def self.load(toml, **_options)
         | 
| 19 20 | 
             
                    ::TomlRB.parse(toml)
         | 
| 20 21 | 
             
                  end
         | 
| 21 22 |  | 
| 22 23 | 
             
                  # Serialize Hash into TOML
         | 
| 23 24 | 
             
                  #
         | 
| 24 25 | 
             
                  # @param [Hash] obj Hash object
         | 
| 26 | 
            +
                  # @param [Hash] options
         | 
| 25 27 | 
             
                  #
         | 
| 26 28 | 
             
                  # @return [String]
         | 
| 27 29 | 
             
                  #
         | 
| 28 30 | 
             
                  # @api private
         | 
| 29 | 
            -
                  def self.dump(obj)
         | 
| 31 | 
            +
                  def self.dump(obj, **_options)
         | 
| 30 32 | 
             
                    ::TomlRB.dump(obj)
         | 
| 31 33 | 
             
                  end
         | 
| 32 34 | 
             
                end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'tomlib'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Shale
         | 
| 6 | 
            +
              module Adapter
         | 
| 7 | 
            +
                # Tomlib adapter
         | 
| 8 | 
            +
                #
         | 
| 9 | 
            +
                # @api public
         | 
| 10 | 
            +
                class Tomlib
         | 
| 11 | 
            +
                  # Parse TOML into Hash
         | 
| 12 | 
            +
                  #
         | 
| 13 | 
            +
                  # @param [String] toml TOML document
         | 
| 14 | 
            +
                  # @param [Hash] options
         | 
| 15 | 
            +
                  #
         | 
| 16 | 
            +
                  # @return [Hash]
         | 
| 17 | 
            +
                  #
         | 
| 18 | 
            +
                  # @api private
         | 
| 19 | 
            +
                  def self.load(toml, **_options)
         | 
| 20 | 
            +
                    ::Tomlib.load(toml)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  # Serialize Hash into TOML
         | 
| 24 | 
            +
                  #
         | 
| 25 | 
            +
                  # @param [Hash] obj Hash object
         | 
| 26 | 
            +
                  # @param [Hash] options
         | 
| 27 | 
            +
                  #
         | 
| 28 | 
            +
                  # @return [String]
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  # @api private
         | 
| 31 | 
            +
                  def self.dump(obj, **options)
         | 
| 32 | 
            +
                    ::Tomlib.dump(obj, **options)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
    
        data/lib/shale/error.rb
    CHANGED
    
    | @@ -9,7 +9,8 @@ module Shale | |
| 9 9 |  | 
| 10 10 | 
             
                # To use Tomlib:
         | 
| 11 11 | 
             
                # Make sure tomlib is installed eg. execute: gem install tomlib
         | 
| 12 | 
            -
                 | 
| 12 | 
            +
                require 'shale/adapter/tomlib'
         | 
| 13 | 
            +
                Shale.toml_adapter = Shale::Adapter::Tomlib
         | 
| 13 14 |  | 
| 14 15 | 
             
                # To use toml-rb:
         | 
| 15 16 | 
             
                # Make sure toml-rb is installed eg. execute: gem install toml-rb
         | 
| @@ -104,6 +105,18 @@ module Shale | |
| 104 105 | 
             
              class NotAShaleMapperError < ShaleError
         | 
| 105 106 | 
             
              end
         | 
| 106 107 |  | 
| 108 | 
            +
              # Error for registering class that is not a valid Type::Value
         | 
| 109 | 
            +
              #
         | 
| 110 | 
            +
              # @api private
         | 
| 111 | 
            +
              class NotATypeValueError < ShaleError
         | 
| 112 | 
            +
              end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
              # Error for using unknown symbol type
         | 
| 115 | 
            +
              #
         | 
| 116 | 
            +
              # @api private
         | 
| 117 | 
            +
              class UnknownTypeError < ShaleError
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
             | 
| 107 120 | 
             
              # Raised when receiver attribute is not defined
         | 
| 108 121 | 
             
              #
         | 
| 109 122 | 
             
              # @api private
         | 
    
        data/lib/shale/mapper.rb
    CHANGED
    
    | @@ -5,6 +5,7 @@ require_relative 'error' | |
| 5 5 | 
             
            require_relative 'utils'
         | 
| 6 6 | 
             
            require_relative 'mapping/dict'
         | 
| 7 7 | 
             
            require_relative 'mapping/xml'
         | 
| 8 | 
            +
            require_relative 'type'
         | 
| 8 9 | 
             
            require_relative 'type/complex'
         | 
| 9 10 |  | 
| 10 11 | 
             
            module Shale
         | 
| @@ -12,16 +13,16 @@ module Shale | |
| 12 13 | 
             
              #
         | 
| 13 14 | 
             
              # @example
         | 
| 14 15 | 
             
              #   class Address < Shale::Mapper
         | 
| 15 | 
            -
              #     attribute :city,  | 
| 16 | 
            -
              #     attribute :street,  | 
| 17 | 
            -
              #     attribute :state,  | 
| 18 | 
            -
              #     attribute :zip,  | 
| 16 | 
            +
              #     attribute :city, :string
         | 
| 17 | 
            +
              #     attribute :street, :string
         | 
| 18 | 
            +
              #     attribute :state, :string
         | 
| 19 | 
            +
              #     attribute :zip, :string
         | 
| 19 20 | 
             
              #   end
         | 
| 20 21 | 
             
              #
         | 
| 21 22 | 
             
              #   class Person < Shale::Mapper
         | 
| 22 | 
            -
              #     attribute :first_name,  | 
| 23 | 
            -
              #     attribute :last_name,  | 
| 24 | 
            -
              #     attribute :age,  | 
| 23 | 
            +
              #     attribute :first_name, :string
         | 
| 24 | 
            +
              #     attribute :last_name, :string
         | 
| 25 | 
            +
              #     attribute :age, :integer
         | 
| 25 26 | 
             
              #     attribute :address, Address
         | 
| 26 27 | 
             
              #   end
         | 
| 27 28 | 
             
              #
         | 
| @@ -144,18 +145,19 @@ module Shale | |
| 144 145 | 
             
                  # Define attribute on class
         | 
| 145 146 | 
             
                  #
         | 
| 146 147 | 
             
                  # @param [Symbol] name Name of the attribute
         | 
| 147 | 
            -
                  # @param [Shale::Type::Value] type Type of the attribute
         | 
| 148 | 
            +
                  # @param [Symbol, Class<Shale::Type::Value>] type Type of the attribute
         | 
| 148 149 | 
             
                  # @param [Boolean] collection Is the attribute a collection
         | 
| 149 150 | 
             
                  # @param [Proc] default Default value for the attribute
         | 
| 150 151 | 
             
                  #
         | 
| 151 152 | 
             
                  # @raise [DefaultNotCallableError] when attribute's default is not callable
         | 
| 153 | 
            +
                  # @raise [UnknownTypeError] when type is a symbol and not found in the registry
         | 
| 152 154 | 
             
                  #
         | 
| 153 155 | 
             
                  # @example
         | 
| 154 156 | 
             
                  #   class Person < Shale::Mapper
         | 
| 155 | 
            -
                  #     attribute :first_name,  | 
| 156 | 
            -
                  #     attribute :last_name,  | 
| 157 | 
            -
                  #     attribute :age,  | 
| 158 | 
            -
                  #     attribute :hobbies,  | 
| 157 | 
            +
                  #     attribute :first_name, :string
         | 
| 158 | 
            +
                  #     attribute :last_name, :string
         | 
| 159 | 
            +
                  #     attribute :age, :integer, default: -> { 1 }
         | 
| 160 | 
            +
                  #     attribute :hobbies, :string, collection: true
         | 
| 159 161 | 
             
                  #   end
         | 
| 160 162 | 
             
                  #
         | 
| 161 163 | 
             
                  #   person = Person.new
         | 
| @@ -177,6 +179,10 @@ module Shale | |
| 177 179 | 
             
                      raise DefaultNotCallableError.new(to_s, name)
         | 
| 178 180 | 
             
                    end
         | 
| 179 181 |  | 
| 182 | 
            +
                    if type.is_a?(Symbol)
         | 
| 183 | 
            +
                      type = Type.lookup(type)
         | 
| 184 | 
            +
                    end
         | 
| 185 | 
            +
             | 
| 180 186 | 
             
                    @attributes[name] = Attribute.new(name, type, collection, default)
         | 
| 181 187 |  | 
| 182 188 | 
             
                    @hash_mapping.map(name.to_s, to: name) unless @hash_mapping.finalized?
         | 
| @@ -201,9 +207,9 @@ module Shale | |
| 201 207 | 
             
                  #
         | 
| 202 208 | 
             
                  # @example
         | 
| 203 209 | 
             
                  #   class Person < Shale::Mapper
         | 
| 204 | 
            -
                  #     attribute :first_name,  | 
| 205 | 
            -
                  #     attribute :last_name,  | 
| 206 | 
            -
                  #     attribute :age,  | 
| 210 | 
            +
                  #     attribute :first_name, :string
         | 
| 211 | 
            +
                  #     attribute :last_name, :string
         | 
| 212 | 
            +
                  #     attribute :age, :integer
         | 
| 207 213 | 
             
                  #
         | 
| 208 214 | 
             
                  #     hsh do
         | 
| 209 215 | 
             
                  #       map 'firstName', to: :first_name
         | 
| @@ -225,9 +231,9 @@ module Shale | |
| 225 231 | 
             
                  #
         | 
| 226 232 | 
             
                  # @example
         | 
| 227 233 | 
             
                  #   class Person < Shale::Mapper
         | 
| 228 | 
            -
                  #     attribute :first_name,  | 
| 229 | 
            -
                  #     attribute :last_name,  | 
| 230 | 
            -
                  #     attribute :age,  | 
| 234 | 
            +
                  #     attribute :first_name, :string
         | 
| 235 | 
            +
                  #     attribute :last_name, :string
         | 
| 236 | 
            +
                  #     attribute :age, :integer
         | 
| 231 237 | 
             
                  #
         | 
| 232 238 | 
             
                  #     json do
         | 
| 233 239 | 
             
                  #       map 'firstName', to: :first_name
         | 
| @@ -249,9 +255,9 @@ module Shale | |
| 249 255 | 
             
                  #
         | 
| 250 256 | 
             
                  # @example
         | 
| 251 257 | 
             
                  #   class Person < Shale::Mapper
         | 
| 252 | 
            -
                  #     attribute :first_name,  | 
| 253 | 
            -
                  #     attribute :last_name,  | 
| 254 | 
            -
                  #     attribute :age,  | 
| 258 | 
            +
                  #     attribute :first_name, :string
         | 
| 259 | 
            +
                  #     attribute :last_name, :string
         | 
| 260 | 
            +
                  #     attribute :age, :integer
         | 
| 255 261 | 
             
                  #
         | 
| 256 262 | 
             
                  #     yaml do
         | 
| 257 263 | 
             
                  #       map 'first_name', to: :first_name
         | 
| @@ -273,9 +279,9 @@ module Shale | |
| 273 279 | 
             
                  #
         | 
| 274 280 | 
             
                  # @example
         | 
| 275 281 | 
             
                  #   class Person < Shale::Mapper
         | 
| 276 | 
            -
                  #     attribute :first_name,  | 
| 277 | 
            -
                  #     attribute :last_name,  | 
| 278 | 
            -
                  #     attribute :age,  | 
| 282 | 
            +
                  #     attribute :first_name, :string
         | 
| 283 | 
            +
                  #     attribute :last_name, :string
         | 
| 284 | 
            +
                  #     attribute :age, :integer
         | 
| 279 285 | 
             
                  #
         | 
| 280 286 | 
             
                  #     toml do
         | 
| 281 287 | 
             
                  #       map 'first_name', to: :first_name
         | 
| @@ -297,9 +303,9 @@ module Shale | |
| 297 303 | 
             
                  #
         | 
| 298 304 | 
             
                  # @example
         | 
| 299 305 | 
             
                  #   class Person < Shale::Mapper
         | 
| 300 | 
            -
                  #     attribute :first_name,  | 
| 301 | 
            -
                  #     attribute :last_name,  | 
| 302 | 
            -
                  #     attribute :age,  | 
| 306 | 
            +
                  #     attribute :first_name, :string
         | 
| 307 | 
            +
                  #     attribute :last_name, :string
         | 
| 308 | 
            +
                  #     attribute :age, :integer
         | 
| 303 309 | 
             
                  #
         | 
| 304 310 | 
             
                  #     csv do
         | 
| 305 311 | 
             
                  #       map 'first_name', to: :first_name
         | 
| @@ -321,9 +327,9 @@ module Shale | |
| 321 327 | 
             
                  #
         | 
| 322 328 | 
             
                  # @example
         | 
| 323 329 | 
             
                  #   class Person < Shale::Mapper
         | 
| 324 | 
            -
                  #     attribute :first_name,  | 
| 325 | 
            -
                  #     attribute :last_name,  | 
| 326 | 
            -
                  #     attribute :age,  | 
| 330 | 
            +
                  #     attribute :first_name, :string
         | 
| 331 | 
            +
                  #     attribute :last_name, :string
         | 
| 332 | 
            +
                  #     attribute :age, :integer
         | 
| 327 333 | 
             
                  #
         | 
| 328 334 | 
             
                  #     xml do
         | 
| 329 335 | 
             
                  #       root 'Person'
         | 
| @@ -67,13 +67,15 @@ module Shale | |
| 67 67 | 
             
                  # @param [Integer] min_properties
         | 
| 68 68 | 
             
                  # @param [Integer] max_properties
         | 
| 69 69 | 
             
                  # @param [Hash] dependent_required
         | 
| 70 | 
            +
                  # @param [Boolean] additional_properties
         | 
| 70 71 | 
             
                  #
         | 
| 71 72 | 
             
                  # @api public
         | 
| 72 | 
            -
                  def properties(min_properties: nil, max_properties: nil, dependent_required: nil)
         | 
| 73 | 
            +
                  def properties(min_properties: nil, max_properties: nil, dependent_required: nil, additional_properties: nil)
         | 
| 73 74 | 
             
                    @root = {
         | 
| 74 75 | 
             
                      min_properties: min_properties,
         | 
| 75 76 | 
             
                      max_properties: max_properties,
         | 
| 76 77 | 
             
                      dependent_required: dependent_required,
         | 
| 78 | 
            +
                      additional_properties: additional_properties,
         | 
| 77 79 | 
             
                    }
         | 
| 78 80 | 
             
                  end
         | 
| 79 81 |  | 
| @@ -46,7 +46,8 @@ module Shale | |
| 46 46 | 
             
                        'maxItems' => schema[:max_items],
         | 
| 47 47 | 
             
                        'uniqueItems' => schema[:unique],
         | 
| 48 48 | 
             
                        'minContains' => schema[:min_contains],
         | 
| 49 | 
            -
                        'maxContains' => schema[:max_contains] | 
| 49 | 
            +
                        'maxContains' => schema[:max_contains],
         | 
| 50 | 
            +
                        'description' => schema[:description] }.compact
         | 
| 50 51 | 
             
                    end
         | 
| 51 52 | 
             
                  end
         | 
| 52 53 | 
             
                end
         | 
| @@ -20,7 +20,8 @@ module Shale | |
| 20 20 | 
             
                        'exclusiveMaximum' => schema[:exclusive_maximum],
         | 
| 21 21 | 
             
                        'minimum' => schema[:minimum],
         | 
| 22 22 | 
             
                        'maximum' => schema[:maximum],
         | 
| 23 | 
            -
                        'multipleOf' => schema[:multiple_of] | 
| 23 | 
            +
                        'multipleOf' => schema[:multiple_of],
         | 
| 24 | 
            +
                        'description' => schema[:description] }.compact
         | 
| 24 25 | 
             
                    end
         | 
| 25 26 | 
             
                  end
         | 
| 26 27 | 
             
                end
         | 
| @@ -20,7 +20,8 @@ module Shale | |
| 20 20 | 
             
                        'exclusiveMaximum' => schema[:exclusive_maximum],
         | 
| 21 21 | 
             
                        'minimum' => schema[:minimum],
         | 
| 22 22 | 
             
                        'maximum' => schema[:maximum],
         | 
| 23 | 
            -
                        'multipleOf' => schema[:multiple_of] | 
| 23 | 
            +
                        'multipleOf' => schema[:multiple_of],
         | 
| 24 | 
            +
                        'description' => schema[:description] }.compact
         | 
| 24 25 | 
             
                    end
         | 
| 25 26 | 
             
                  end
         | 
| 26 27 | 
             
                end
         | 
| @@ -40,6 +40,8 @@ module Shale | |
| 40 40 | 
             
                        'minProperties' => @root[:min_properties],
         | 
| 41 41 | 
             
                        'maxProperties' => @root[:max_properties],
         | 
| 42 42 | 
             
                        'dependentRequired' => @root[:dependent_required],
         | 
| 43 | 
            +
                        'description' => @root[:description],
         | 
| 44 | 
            +
                        'additionalProperties' => @root[:additional_properties],
         | 
| 43 45 | 
             
                      }.compact
         | 
| 44 46 | 
             
                    end
         | 
| 45 47 | 
             
                  end
         | 
| @@ -19,7 +19,8 @@ module Shale | |
| 19 19 | 
             
                        'format' => schema[:format],
         | 
| 20 20 | 
             
                        'minLength' => schema[:min_length],
         | 
| 21 21 | 
             
                        'maxLength' => schema[:max_length],
         | 
| 22 | 
            -
                        'pattern' => schema[:pattern] | 
| 22 | 
            +
                        'pattern' => schema[:pattern],
         | 
| 23 | 
            +
                        'description' => schema[:description] }.compact
         | 
| 23 24 | 
             
                    end
         | 
| 24 25 | 
             
                  end
         | 
| 25 26 | 
             
                end
         | 
    
        data/lib/shale/type/boolean.rb
    CHANGED
    
    
    
        data/lib/shale/type/complex.rb
    CHANGED
    
    | @@ -257,13 +257,14 @@ module Shale | |
| 257 257 | 
             
                    # @param [Array<Symbol>] only
         | 
| 258 258 | 
             
                    # @param [Array<Symbol>] except
         | 
| 259 259 | 
             
                    # @param [any] context
         | 
| 260 | 
            +
                    # @param [Hash] json_options
         | 
| 260 261 | 
             
                    #
         | 
| 261 262 | 
             
                    # @return [model instance]
         | 
| 262 263 | 
             
                    #
         | 
| 263 264 | 
             
                    # @api public
         | 
| 264 | 
            -
                    def from_json(json, only: nil, except: nil, context: nil)
         | 
| 265 | 
            +
                    def from_json(json, only: nil, except: nil, context: nil, **json_options)
         | 
| 265 266 | 
             
                      of_json(
         | 
| 266 | 
            -
                        Shale.json_adapter.load(json),
         | 
| 267 | 
            +
                        Shale.json_adapter.load(json, **json_options),
         | 
| 267 268 | 
             
                        only: only,
         | 
| 268 269 | 
             
                        except: except,
         | 
| 269 270 | 
             
                        context: context
         | 
| @@ -277,14 +278,15 @@ module Shale | |
| 277 278 | 
             
                    # @param [Array<Symbol>] except
         | 
| 278 279 | 
             
                    # @param [any] context
         | 
| 279 280 | 
             
                    # @param [true, false] pretty
         | 
| 281 | 
            +
                    # @param [Hash] json_options
         | 
| 280 282 | 
             
                    #
         | 
| 281 283 | 
             
                    # @return [String]
         | 
| 282 284 | 
             
                    #
         | 
| 283 285 | 
             
                    # @api public
         | 
| 284 | 
            -
                    def to_json(instance, only: nil, except: nil, context: nil, pretty: false)
         | 
| 286 | 
            +
                    def to_json(instance, only: nil, except: nil, context: nil, pretty: false, **json_options)
         | 
| 285 287 | 
             
                      Shale.json_adapter.dump(
         | 
| 286 288 | 
             
                        as_json(instance, only: only, except: except, context: context),
         | 
| 287 | 
            -
                        pretty: pretty
         | 
| 289 | 
            +
                        **json_options.merge(pretty: pretty)
         | 
| 288 290 | 
             
                      )
         | 
| 289 291 | 
             
                    end
         | 
| 290 292 |  | 
| @@ -294,13 +296,14 @@ module Shale | |
| 294 296 | 
             
                    # @param [Array<Symbol>] only
         | 
| 295 297 | 
             
                    # @param [Array<Symbol>] except
         | 
| 296 298 | 
             
                    # @param [any] context
         | 
| 299 | 
            +
                    # @param [Hash] yaml_options
         | 
| 297 300 | 
             
                    #
         | 
| 298 301 | 
             
                    # @return [model instance]
         | 
| 299 302 | 
             
                    #
         | 
| 300 303 | 
             
                    # @api public
         | 
| 301 | 
            -
                    def from_yaml(yaml, only: nil, except: nil, context: nil)
         | 
| 304 | 
            +
                    def from_yaml(yaml, only: nil, except: nil, context: nil, **yaml_options)
         | 
| 302 305 | 
             
                      of_yaml(
         | 
| 303 | 
            -
                        Shale.yaml_adapter.load(yaml),
         | 
| 306 | 
            +
                        Shale.yaml_adapter.load(yaml, **yaml_options),
         | 
| 304 307 | 
             
                        only: only,
         | 
| 305 308 | 
             
                        except: except,
         | 
| 306 309 | 
             
                        context: context
         | 
| @@ -313,13 +316,15 @@ module Shale | |
| 313 316 | 
             
                    # @param [Array<Symbol>] only
         | 
| 314 317 | 
             
                    # @param [Array<Symbol>] except
         | 
| 315 318 | 
             
                    # @param [any] context
         | 
| 319 | 
            +
                    # @param [Hash] yaml_options
         | 
| 316 320 | 
             
                    #
         | 
| 317 321 | 
             
                    # @return [String]
         | 
| 318 322 | 
             
                    #
         | 
| 319 323 | 
             
                    # @api public
         | 
| 320 | 
            -
                    def to_yaml(instance, only: nil, except: nil, context: nil)
         | 
| 324 | 
            +
                    def to_yaml(instance, only: nil, except: nil, context: nil, **yaml_options)
         | 
| 321 325 | 
             
                      Shale.yaml_adapter.dump(
         | 
| 322 | 
            -
                        as_yaml(instance, only: only, except: except, context: context)
         | 
| 326 | 
            +
                        as_yaml(instance, only: only, except: except, context: context),
         | 
| 327 | 
            +
                        **yaml_options
         | 
| 323 328 | 
             
                      )
         | 
| 324 329 | 
             
                    end
         | 
| 325 330 |  | 
| @@ -329,14 +334,15 @@ module Shale | |
| 329 334 | 
             
                    # @param [Array<Symbol>] only
         | 
| 330 335 | 
             
                    # @param [Array<Symbol>] except
         | 
| 331 336 | 
             
                    # @param [any] context
         | 
| 337 | 
            +
                    # @param [Hash] toml_options
         | 
| 332 338 | 
             
                    #
         | 
| 333 339 | 
             
                    # @return [model instance]
         | 
| 334 340 | 
             
                    #
         | 
| 335 341 | 
             
                    # @api public
         | 
| 336 | 
            -
                    def from_toml(toml, only: nil, except: nil, context: nil)
         | 
| 342 | 
            +
                    def from_toml(toml, only: nil, except: nil, context: nil, **toml_options)
         | 
| 337 343 | 
             
                      validate_toml_adapter
         | 
| 338 344 | 
             
                      of_toml(
         | 
| 339 | 
            -
                        Shale.toml_adapter.load(toml),
         | 
| 345 | 
            +
                        Shale.toml_adapter.load(toml, **toml_options),
         | 
| 340 346 | 
             
                        only: only,
         | 
| 341 347 | 
             
                        except: except,
         | 
| 342 348 | 
             
                        context: context
         | 
| @@ -349,14 +355,16 @@ module Shale | |
| 349 355 | 
             
                    # @param [Array<Symbol>] only
         | 
| 350 356 | 
             
                    # @param [Array<Symbol>] except
         | 
| 351 357 | 
             
                    # @param [any] context
         | 
| 358 | 
            +
                    # @param [Hash] toml_options
         | 
| 352 359 | 
             
                    #
         | 
| 353 360 | 
             
                    # @return [String]
         | 
| 354 361 | 
             
                    #
         | 
| 355 362 | 
             
                    # @api public
         | 
| 356 | 
            -
                    def to_toml(instance, only: nil, except: nil, context: nil)
         | 
| 363 | 
            +
                    def to_toml(instance, only: nil, except: nil, context: nil, **toml_options)
         | 
| 357 364 | 
             
                      validate_toml_adapter
         | 
| 358 365 | 
             
                      Shale.toml_adapter.dump(
         | 
| 359 | 
            -
                        as_toml(instance, only: only, except: except, context: context)
         | 
| 366 | 
            +
                        as_toml(instance, only: only, except: except, context: context),
         | 
| 367 | 
            +
                        **toml_options
         | 
| 360 368 | 
             
                      )
         | 
| 361 369 | 
             
                    end
         | 
| 362 370 |  | 
| @@ -1000,17 +1008,19 @@ module Shale | |
| 1000 1008 | 
             
                  # @param [Array<Symbol>] except
         | 
| 1001 1009 | 
             
                  # @param [any] context
         | 
| 1002 1010 | 
             
                  # @param [true, false] pretty
         | 
| 1011 | 
            +
                  # @param [Hash] json_options
         | 
| 1003 1012 | 
             
                  #
         | 
| 1004 1013 | 
             
                  # @return [String]
         | 
| 1005 1014 | 
             
                  #
         | 
| 1006 1015 | 
             
                  # @api public
         | 
| 1007 | 
            -
                  def to_json(only: nil, except: nil, context: nil, pretty: false)
         | 
| 1016 | 
            +
                  def to_json(only: nil, except: nil, context: nil, pretty: false, **json_options)
         | 
| 1008 1017 | 
             
                    self.class.to_json(
         | 
| 1009 1018 | 
             
                      self,
         | 
| 1010 1019 | 
             
                      only: only,
         | 
| 1011 1020 | 
             
                      except: except,
         | 
| 1012 1021 | 
             
                      context: context,
         | 
| 1013 | 
            -
                      pretty: pretty
         | 
| 1022 | 
            +
                      pretty: pretty,
         | 
| 1023 | 
            +
                      **json_options
         | 
| 1014 1024 | 
             
                    )
         | 
| 1015 1025 | 
             
                  end
         | 
| 1016 1026 |  | 
| @@ -1019,12 +1029,13 @@ module Shale | |
| 1019 1029 | 
             
                  # @param [Array<Symbol>] only
         | 
| 1020 1030 | 
             
                  # @param [Array<Symbol>] except
         | 
| 1021 1031 | 
             
                  # @param [any] context
         | 
| 1032 | 
            +
                  # @param [Hash] yaml_options
         | 
| 1022 1033 | 
             
                  #
         | 
| 1023 1034 | 
             
                  # @return [String]
         | 
| 1024 1035 | 
             
                  #
         | 
| 1025 1036 | 
             
                  # @api public
         | 
| 1026 | 
            -
                  def to_yaml(only: nil, except: nil, context: nil)
         | 
| 1027 | 
            -
                    self.class.to_yaml(self, only: only, except: except, context: context)
         | 
| 1037 | 
            +
                  def to_yaml(only: nil, except: nil, context: nil, **yaml_options)
         | 
| 1038 | 
            +
                    self.class.to_yaml(self, only: only, except: except, context: context, **yaml_options)
         | 
| 1028 1039 | 
             
                  end
         | 
| 1029 1040 |  | 
| 1030 1041 | 
             
                  # Convert Object to TOML
         | 
| @@ -1032,12 +1043,13 @@ module Shale | |
| 1032 1043 | 
             
                  # @param [Array<Symbol>] only
         | 
| 1033 1044 | 
             
                  # @param [Array<Symbol>] except
         | 
| 1034 1045 | 
             
                  # @param [any] context
         | 
| 1046 | 
            +
                  # @param [Hash] toml_options
         | 
| 1035 1047 | 
             
                  #
         | 
| 1036 1048 | 
             
                  # @return [String]
         | 
| 1037 1049 | 
             
                  #
         | 
| 1038 1050 | 
             
                  # @api public
         | 
| 1039 | 
            -
                  def to_toml(only: nil, except: nil, context: nil)
         | 
| 1040 | 
            -
                    self.class.to_toml(self, only: only, except: except, context: context)
         | 
| 1051 | 
            +
                  def to_toml(only: nil, except: nil, context: nil, **toml_options)
         | 
| 1052 | 
            +
                    self.class.to_toml(self, only: only, except: except, context: context, **toml_options)
         | 
| 1041 1053 | 
             
                  end
         | 
| 1042 1054 |  | 
| 1043 1055 | 
             
                  # Convert Object to CSV
         | 
| @@ -1045,6 +1057,8 @@ module Shale | |
| 1045 1057 | 
             
                  # @param [Array<Symbol>] only
         | 
| 1046 1058 | 
             
                  # @param [Array<Symbol>] except
         | 
| 1047 1059 | 
             
                  # @param [any] context
         | 
| 1060 | 
            +
                  # @param [true, false] headers
         | 
| 1061 | 
            +
                  # @param [Hash] csv_options
         | 
| 1048 1062 | 
             
                  #
         | 
| 1049 1063 | 
             
                  # @return [String]
         | 
| 1050 1064 | 
             
                  #
         | 
    
        data/lib/shale/type/date.rb
    CHANGED
    
    
    
        data/lib/shale/type/float.rb
    CHANGED
    
    
    
        data/lib/shale/type/integer.rb
    CHANGED
    
    
    
        data/lib/shale/type/string.rb
    CHANGED
    
    
    
        data/lib/shale/type/time.rb
    CHANGED
    
    
    
        data/lib/shale/type.rb
    ADDED
    
    | @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shale
         | 
| 4 | 
            +
              module Type
         | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  # Register a symbol alias for a Shale::Type::Value class
         | 
| 7 | 
            +
                  #
         | 
| 8 | 
            +
                  # @param [Symbol] type Short type alias
         | 
| 9 | 
            +
                  # @param [Shale::Type::Value] klass Class to register
         | 
| 10 | 
            +
                  #
         | 
| 11 | 
            +
                  # @raise [NotATypeValueError] when klass is not a Shale::Type::Value
         | 
| 12 | 
            +
                  #
         | 
| 13 | 
            +
                  # @example
         | 
| 14 | 
            +
                  #   class UnixTimestamp < Shale::Type::Value
         | 
| 15 | 
            +
                  #     def self.cast(value)
         | 
| 16 | 
            +
                  #       Time.at(value.to_i)
         | 
| 17 | 
            +
                  #     end
         | 
| 18 | 
            +
                  #   end
         | 
| 19 | 
            +
                  #
         | 
| 20 | 
            +
                  #   Shale::Type.register(:unix_timestamp, UnixTimestamp)
         | 
| 21 | 
            +
                  #
         | 
| 22 | 
            +
                  # @api public
         | 
| 23 | 
            +
                  def register(type, klass)
         | 
| 24 | 
            +
                    @registry ||= {}
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    unless klass < Value
         | 
| 27 | 
            +
                      raise NotATypeValueError, "class '#{klass}' is not a valid Shale::Type::Value"
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    @registry[type] = klass
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  # Lookup a Shale::Type::Value class by type alias
         | 
| 34 | 
            +
                  #
         | 
| 35 | 
            +
                  # @param [Symbol] type Type alias
         | 
| 36 | 
            +
                  #
         | 
| 37 | 
            +
                  # @raise [UnknownTypeError] when type is not registered
         | 
| 38 | 
            +
                  #
         | 
| 39 | 
            +
                  # @return [Shale::Type::Value] Class registered for type
         | 
| 40 | 
            +
                  #
         | 
| 41 | 
            +
                  # @example
         | 
| 42 | 
            +
                  #
         | 
| 43 | 
            +
                  #  Shale::Type.lookup(:unix_timestamp)
         | 
| 44 | 
            +
                  #  # => UnixTimestamp
         | 
| 45 | 
            +
                  #
         | 
| 46 | 
            +
                  # @api public
         | 
| 47 | 
            +
                  def lookup(type)
         | 
| 48 | 
            +
                    klass = @registry[type]
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    raise UnknownTypeError, "unknown type '#{type}'" unless klass
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    klass
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
    
        data/lib/shale/version.rb
    CHANGED
    
    
    
        data/lib/shale.rb
    CHANGED
    
    | @@ -4,6 +4,7 @@ require 'yaml' | |
| 4 4 |  | 
| 5 5 | 
             
            require_relative 'shale/mapper'
         | 
| 6 6 | 
             
            require_relative 'shale/adapter/json'
         | 
| 7 | 
            +
            require_relative 'shale/type'
         | 
| 7 8 | 
             
            require_relative 'shale/type/boolean'
         | 
| 8 9 | 
             
            require_relative 'shale/type/date'
         | 
| 9 10 | 
             
            require_relative 'shale/type/float'
         | 
| @@ -80,16 +81,17 @@ module Shale | |
| 80 81 | 
             
                # @api public
         | 
| 81 82 | 
             
                attr_writer :yaml_adapter
         | 
| 82 83 |  | 
| 83 | 
            -
                # TOML adapter accessor.
         | 
| 84 | 
            +
                # TOML adapter accessor. Available adapters are Shale::Adapter::Tomlib
         | 
| 85 | 
            +
                # and Shale::Adapter::TomRB
         | 
| 84 86 | 
             
                #
         | 
| 85 | 
            -
                # @param [@see Shale::Adapter:: | 
| 87 | 
            +
                # @param [@see Shale::Adapter::Tomlib] adapter
         | 
| 86 88 | 
             
                #
         | 
| 87 89 | 
             
                # @example setting adapter
         | 
| 88 | 
            -
                #   Shale.toml_adapter = Shale::Adapter:: | 
| 90 | 
            +
                #   Shale.toml_adapter = Shale::Adapter::Tomlib
         | 
| 89 91 | 
             
                #
         | 
| 90 92 | 
             
                # @example getting adapter
         | 
| 91 93 | 
             
                #   Shale.toml_adapter
         | 
| 92 | 
            -
                #   # => Shale::Adapter:: | 
| 94 | 
            +
                #   # => Shale::Adapter::Tomlib
         | 
| 93 95 | 
             
                #
         | 
| 94 96 | 
             
                # @api public
         | 
| 95 97 | 
             
                attr_accessor :toml_adapter
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: shale
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Kamil Giszczak
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024- | 
| 11 | 
            +
            date: 2024-10-31 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bigdecimal
         | 
| @@ -49,6 +49,7 @@ files: | |
| 49 49 | 
             
            - lib/shale/adapter/rexml/document.rb
         | 
| 50 50 | 
             
            - lib/shale/adapter/rexml/node.rb
         | 
| 51 51 | 
             
            - lib/shale/adapter/toml_rb.rb
         | 
| 52 | 
            +
            - lib/shale/adapter/tomlib.rb
         | 
| 52 53 | 
             
            - lib/shale/attribute.rb
         | 
| 53 54 | 
             
            - lib/shale/error.rb
         | 
| 54 55 | 
             
            - lib/shale/mapper.rb
         | 
| @@ -104,6 +105,7 @@ files: | |
| 104 105 | 
             
            - lib/shale/schema/xml_generator/schema.rb
         | 
| 105 106 | 
             
            - lib/shale/schema/xml_generator/typed_attribute.rb
         | 
| 106 107 | 
             
            - lib/shale/schema/xml_generator/typed_element.rb
         | 
| 108 | 
            +
            - lib/shale/type.rb
         | 
| 107 109 | 
             
            - lib/shale/type/boolean.rb
         | 
| 108 110 | 
             
            - lib/shale/type/complex.rb
         | 
| 109 111 | 
             
            - lib/shale/type/date.rb
         |