nrser 0.0.26 → 0.0.27
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/lib/nrser.rb +1 -0
- data/lib/nrser/array.rb +15 -0
- data/lib/nrser/binding.rb +7 -1
- data/lib/nrser/enumerable.rb +21 -1
- data/lib/nrser/errors.rb +56 -6
- data/lib/nrser/hash/deep_merge.rb +1 -1
- data/lib/nrser/message.rb +33 -0
- data/lib/nrser/meta/props.rb +77 -15
- data/lib/nrser/meta/props/prop.rb +276 -44
- data/lib/nrser/proc.rb +7 -3
- data/lib/nrser/refinements/array.rb +5 -0
- data/lib/nrser/refinements/enumerable.rb +5 -0
- data/lib/nrser/refinements/hash.rb +8 -0
- data/lib/nrser/refinements/object.rb +11 -1
- data/lib/nrser/refinements/string.rb +17 -3
- data/lib/nrser/refinements/symbol.rb +8 -0
- data/lib/nrser/refinements/tree.rb +22 -0
- data/lib/nrser/rspex.rb +312 -70
- data/lib/nrser/rspex/shared_examples.rb +116 -0
- data/lib/nrser/string.rb +159 -27
- data/lib/nrser/temp/unicode_math.rb +48 -0
- data/lib/nrser/text.rb +3 -0
- data/lib/nrser/text/indentation.rb +210 -0
- data/lib/nrser/text/lines.rb +52 -0
- data/lib/nrser/text/word_wrap.rb +29 -0
- data/lib/nrser/tree.rb +4 -78
- data/lib/nrser/tree/each_branch.rb +76 -0
- data/lib/nrser/tree/map_branches.rb +91 -0
- data/lib/nrser/tree/map_tree.rb +97 -0
- data/lib/nrser/tree/transform.rb +56 -13
- data/lib/nrser/types.rb +1 -0
- data/lib/nrser/types/array.rb +15 -3
- data/lib/nrser/types/is_a.rb +40 -1
- data/lib/nrser/types/nil.rb +17 -0
- data/lib/nrser/types/paths.rb +17 -2
- data/lib/nrser/types/strings.rb +57 -22
- data/lib/nrser/types/tuples.rb +5 -0
- data/lib/nrser/types/type.rb +47 -6
- data/lib/nrser/version.rb +1 -1
- data/spec/nrser/errors/abstract_method_error_spec.rb +46 -0
- data/spec/nrser/meta/props/to_and_from_data_spec.rb +74 -0
- data/spec/nrser/meta/props_spec.rb +6 -2
- data/spec/nrser/refinements/erb_spec.rb +100 -1
- data/spec/nrser/{common_prefix_spec.rb → string/common_prefix_spec.rb} +9 -0
- data/spec/nrser/text/dedent_spec.rb +80 -0
- data/spec/nrser/tree/map_branch_spec.rb +83 -0
- data/spec/nrser/tree/map_tree_spec.rb +123 -0
- data/spec/nrser/tree/transform_spec.rb +26 -29
- data/spec/nrser/tree/transformer_spec.rb +179 -0
- data/spec/nrser/types/paths_spec.rb +73 -45
- data/spec/spec_helper.rb +10 -0
- metadata +27 -7
- data/spec/nrser/dedent_spec.rb +0 -36
    
        data/lib/nrser/types.rb
    CHANGED
    
    
    
        data/lib/nrser/types/array.rb
    CHANGED
    
    | @@ -30,6 +30,7 @@ module NRSER; end | |
| 30 30 | 
             
            # =======================================================================
         | 
| 31 31 |  | 
| 32 32 | 
             
            module NRSER::Types
         | 
| 33 | 
            +
              
         | 
| 33 34 | 
             
              class ArrayType < IsA
         | 
| 34 35 | 
             
                # Default value to split strings with in {#from_s} if the string provided
         | 
| 35 36 | 
             
                # does is not recognized as an encoding format (as of writing, JSON is
         | 
| @@ -51,6 +52,11 @@ module NRSER::Types | |
| 51 52 | 
             
                end
         | 
| 52 53 |  | 
| 53 54 |  | 
| 55 | 
            +
                def item_type
         | 
| 56 | 
            +
                  NRSER::Types.any
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
                
         | 
| 59 | 
            +
                
         | 
| 54 60 | 
             
                # Called on an array of string items that have been split
         | 
| 55 61 | 
             
                # from a single string by {#from_s} to convert each individual item before
         | 
| 56 62 | 
             
                # {#check} is called on the value.
         | 
| @@ -179,12 +185,17 @@ module NRSER::Types | |
| 179 185 | 
             
              # 
         | 
| 180 186 | 
             
              class << self
         | 
| 181 187 |  | 
| 182 | 
            -
                #  | 
| 188 | 
            +
                # @!group Type Factory Functions
         | 
| 189 | 
            +
                
         | 
| 190 | 
            +
                # {NRSER::Types::ArrayType} / {NRSER::Types::ArrayOfType} factory function.
         | 
| 191 | 
            +
                # 
         | 
| 192 | 
            +
                # @param [Type | Object] item_type
         | 
| 193 | 
            +
                #   Optional type of items.
         | 
| 183 194 | 
             
                # 
         | 
| 184 195 | 
             
                # @return [NRSER::Types::Type]
         | 
| 185 196 | 
             
                # 
         | 
| 186 | 
            -
                def array item_type =  | 
| 187 | 
            -
                  if item_type ==  | 
| 197 | 
            +
                def array item_type = any, **options
         | 
| 198 | 
            +
                  if item_type == any
         | 
| 188 199 | 
             
                    if options.empty?
         | 
| 189 200 | 
             
                      ARRAY
         | 
| 190 201 | 
             
                    else
         | 
| @@ -199,4 +210,5 @@ module NRSER::Types | |
| 199 210 |  | 
| 200 211 | 
             
              end # class << self (Eigenclass)
         | 
| 201 212 |  | 
| 213 | 
            +
              
         | 
| 202 214 | 
             
            end # NRSER::Types
         | 
    
        data/lib/nrser/types/is_a.rb
    CHANGED
    
    | @@ -7,19 +7,58 @@ module NRSER::Types | |
| 7 7 | 
             
                attr_reader :klass
         | 
| 8 8 |  | 
| 9 9 | 
             
                def initialize klass, **options
         | 
| 10 | 
            +
                  unless klass.is_a?( Class ) || klass.is_a?( Module )
         | 
| 11 | 
            +
                    raise ArgumentError.new binding.erb <<-ERB
         | 
| 12 | 
            +
                      `klass` argument must be a Class or Module, found:
         | 
| 13 | 
            +
                      
         | 
| 14 | 
            +
                          <%= klass.pretty_inspect %>
         | 
| 15 | 
            +
                      
         | 
| 16 | 
            +
                    ERB
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                  
         | 
| 10 19 | 
             
                  super **options
         | 
| 11 20 | 
             
                  @klass = klass
         | 
| 12 21 | 
             
                end
         | 
| 13 22 |  | 
| 14 23 | 
             
                def default_name
         | 
| 15 | 
            -
                  "#{ self.class.short_name }(#{ @klass })"
         | 
| 24 | 
            +
                  "#{ self.class.short_name }(#{ @klass.name })"
         | 
| 16 25 | 
             
                end
         | 
| 17 26 |  | 
| 18 27 | 
             
                def test value
         | 
| 19 28 | 
             
                  value.is_a? @klass
         | 
| 20 29 | 
             
                end
         | 
| 30 | 
            +
                
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                # If {#klass} responds to `#from_data`, call that and check results.
         | 
| 33 | 
            +
                # 
         | 
| 34 | 
            +
                # Otherwise, forward up to {NRSER::Types::Type#from_data}.
         | 
| 35 | 
            +
                # 
         | 
| 36 | 
            +
                # @param [Object] data
         | 
| 37 | 
            +
                #   Data to create the value from that will satisfy the type.
         | 
| 38 | 
            +
                # 
         | 
| 39 | 
            +
                # @return [Object]
         | 
| 40 | 
            +
                #   Instance of {#klass}.
         | 
| 41 | 
            +
                # 
         | 
| 42 | 
            +
                def from_data data
         | 
| 43 | 
            +
                  if @from_data.nil?
         | 
| 44 | 
            +
                    if @klass.respond_to? :from_data
         | 
| 45 | 
            +
                      check @klass.from_data( data )
         | 
| 46 | 
            +
                    else
         | 
| 47 | 
            +
                      super data
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  else
         | 
| 50 | 
            +
                    @from_data.call data
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
                
         | 
| 54 | 
            +
                
         | 
| 55 | 
            +
                def has_from_data?
         | 
| 56 | 
            +
                  @from_data || @klass.respond_to?( :from_data )
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
                
         | 
| 21 59 | 
             
              end # IsA
         | 
| 22 60 |  | 
| 61 | 
            +
              
         | 
| 23 62 | 
             
              # class membership
         | 
| 24 63 | 
             
              def self.is_a klass, **options
         | 
| 25 64 | 
             
                IsA.new klass, **options
         | 
    
        data/lib/nrser/types/paths.rb
    CHANGED
    
    | @@ -45,7 +45,6 @@ module NRSER::Types | |
| 45 45 | 
             
                where { |value| value.to_s.length > 0 },
         | 
| 46 46 | 
             
                name: 'NonEmptyPathnameType'
         | 
| 47 47 |  | 
| 48 | 
            -
              
         | 
| 49 48 | 
             
              PATH = union non_empty_str, NON_EMPTY_PATHNAME, name: 'Path'
         | 
| 50 49 |  | 
| 51 50 |  | 
| @@ -53,9 +52,10 @@ module NRSER::Types | |
| 53 52 | 
             
              # ========================================================================
         | 
| 54 53 | 
             
              # 
         | 
| 55 54 | 
             
              class << self
         | 
| 55 | 
            +
                # @!group Type Factory Functions
         | 
| 56 56 |  | 
| 57 57 | 
             
                def pathname to_data: :to_s, **options
         | 
| 58 | 
            -
                  if options.empty?
         | 
| 58 | 
            +
                  if options.empty? && to_data == :to_s
         | 
| 59 59 | 
             
                    PATHNAME
         | 
| 60 60 | 
             
                  else
         | 
| 61 61 | 
             
                    is_a \
         | 
| @@ -82,6 +82,19 @@ module NRSER::Types | |
| 82 82 | 
             
                end # #path
         | 
| 83 83 |  | 
| 84 84 |  | 
| 85 | 
            +
                def path_segment **options
         | 
| 86 | 
            +
                  if options.empty?
         | 
| 87 | 
            +
                    POSIX_PATH_SEGMENT
         | 
| 88 | 
            +
                  else
         | 
| 89 | 
            +
                    intersection  non_empty_str,
         | 
| 90 | 
            +
                                  where { |string| ! string.include?( '/' ) },
         | 
| 91 | 
            +
                                  name: 'POSIXPathSegment'
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
                
         | 
| 95 | 
            +
                alias_method :path_seg, :path_segment
         | 
| 96 | 
            +
                
         | 
| 97 | 
            +
                
         | 
| 85 98 | 
             
                # An absolute {#path}.
         | 
| 86 99 | 
             
                # 
         | 
| 87 100 | 
             
                # @param **options see NRSER::Types::Type#initialize
         | 
| @@ -139,5 +152,7 @@ module NRSER::Types | |
| 139 152 |  | 
| 140 153 | 
             
              end # class << self (Eigenclass)
         | 
| 141 154 |  | 
| 155 | 
            +
              POSIX_PATH_SEGMENT = path_segment name: 'POSIXPathSegment'
         | 
| 156 | 
            +
              
         | 
| 142 157 | 
             
            end # module NRSER::Types
         | 
| 143 158 |  | 
    
        data/lib/nrser/types/strings.rb
    CHANGED
    
    | @@ -6,33 +6,68 @@ require 'nrser/types/attrs' | |
| 6 6 | 
             
            using NRSER
         | 
| 7 7 |  | 
| 8 8 | 
             
            module NRSER::Types
         | 
| 9 | 
            -
               | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 9 | 
            +
              
         | 
| 10 | 
            +
              # Eigenclass (Singleton Class)
         | 
| 11 | 
            +
              # ========================================================================
         | 
| 12 | 
            +
              # 
         | 
| 13 | 
            +
              class << self
         | 
| 14 | 
            +
                # @!group Type Factory Functions
         | 
| 15 | 
            +
                
         | 
| 16 | 
            +
                def str length: nil, **options
         | 
| 17 | 
            +
                  if length.nil? && options.empty?
         | 
| 18 | 
            +
                    # if there are no options can point to the constant for efficiency
         | 
| 19 | 
            +
                    STR
         | 
| 16 20 | 
             
                  else
         | 
| 17 | 
            -
                     | 
| 18 | 
            -
                      IsA.new | 
| 19 | 
            -
             | 
| 20 | 
            -
                       | 
| 21 | 
            +
                    if length.nil?
         | 
| 22 | 
            +
                      IsA.new String, from_s: ->(s) { s }, **options
         | 
| 23 | 
            +
                    else
         | 
| 24 | 
            +
                      intersection \
         | 
| 25 | 
            +
                        IsA.new( String, from_s: ->(s) { s } ),
         | 
| 26 | 
            +
                        NRSER::Types.length( length ),
         | 
| 27 | 
            +
                        **options
         | 
| 28 | 
            +
                    end
         | 
| 21 29 | 
             
                  end
         | 
| 30 | 
            +
                end # string
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                alias_method :string, :str
         | 
| 33 | 
            +
                
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                def empty_str
         | 
| 36 | 
            +
                  EMPTY_STR
         | 
| 22 37 | 
             
                end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 38 | 
            +
                
         | 
| 39 | 
            +
                
         | 
| 40 | 
            +
                def non_empty_str **options
         | 
| 41 | 
            +
                  return NON_EMPTY_STR if options.empty?
         | 
| 42 | 
            +
                  
         | 
| 43 | 
            +
                  str( length: {min: 1}, **options )
         | 
| 44 | 
            +
                end # .non_empty_str
         | 
| 45 | 
            +
                
         | 
| 46 | 
            +
                
         | 
| 47 | 
            +
                private
         | 
| 48 | 
            +
                # ========================================================================
         | 
| 49 | 
            +
                  
         | 
| 50 | 
            +
                  
         | 
| 51 | 
            +
                  # @todo Document make_string_type method.
         | 
| 52 | 
            +
                  # 
         | 
| 53 | 
            +
                  # @param [type] arg_name
         | 
| 54 | 
            +
                  #   @todo Add name param description.
         | 
| 55 | 
            +
                  # 
         | 
| 56 | 
            +
                  # @return [return_type]
         | 
| 57 | 
            +
                  #   @todo Document return value.
         | 
| 58 | 
            +
                  # 
         | 
| 59 | 
            +
                  def make_string_type length: nil, match: nil
         | 
| 60 | 
            +
                    # method body...
         | 
| 61 | 
            +
                  end # #make_string_type
         | 
| 62 | 
            +
                  
         | 
| 63 | 
            +
                  
         | 
| 64 | 
            +
                # end private
         | 
| 65 | 
            +
                
         | 
| 66 | 
            +
              end # class << self (Eigenclass)
         | 
| 28 67 |  | 
| 29 | 
            -
               | 
| 68 | 
            +
              STR = str( name: 'StringType' ).freeze
         | 
| 30 69 |  | 
| 31 | 
            -
               | 
| 32 | 
            -
                return NON_EMPTY_STR if options.empty?
         | 
| 33 | 
            -
                
         | 
| 34 | 
            -
                str( length: {min: 1}, **options )
         | 
| 35 | 
            -
              end # .non_empty_str
         | 
| 70 | 
            +
              EMPTY_STR = str( name: 'EmptyStringType', length: 0 ).freeze
         | 
| 36 71 |  | 
| 37 72 | 
             
              NON_EMPTY_STR = non_empty_str( name: 'NonEmptyStr' ).freeze
         | 
| 38 73 |  | 
    
        data/lib/nrser/types/tuples.rb
    CHANGED
    
    
    
        data/lib/nrser/types/type.rb
    CHANGED
    
    | @@ -35,7 +35,7 @@ module NRSER::Types | |
| 35 35 | 
             
                # @param [nil | #call | #to_proc] to_data:
         | 
| 36 36 | 
             
                #   
         | 
| 37 37 | 
             
                # 
         | 
| 38 | 
            -
                def initialize name: nil, from_s: nil, to_data: nil
         | 
| 38 | 
            +
                def initialize name: nil, from_s: nil, to_data: nil, from_data: nil
         | 
| 39 39 | 
             
                  @name = name
         | 
| 40 40 | 
             
                  @from_s = from_s
         | 
| 41 41 |  | 
| @@ -46,10 +46,37 @@ module NRSER::Types | |
| 46 46 | 
             
                  elsif to_data.respond_to?( :to_proc )
         | 
| 47 47 | 
             
                    to_data.to_proc
         | 
| 48 48 | 
             
                  else
         | 
| 49 | 
            -
                    raise TypeError. | 
| 50 | 
            -
                      `to_data:` keyword arg must be `nil`, respond to  | 
| 51 | 
            -
                      to  | 
| 52 | 
            -
             | 
| 49 | 
            +
                    raise TypeError.new binding.erb <<-ERB
         | 
| 50 | 
            +
                      `to_data:` keyword arg must be `nil`, respond to `#call` or respond
         | 
| 51 | 
            +
                      to `#to_proc`.
         | 
| 52 | 
            +
                      
         | 
| 53 | 
            +
                      Found value:
         | 
| 54 | 
            +
                      
         | 
| 55 | 
            +
                          <%= to_data.pretty_inspect %>
         | 
| 56 | 
            +
                      
         | 
| 57 | 
            +
                      (type <%= to_data.class %>)
         | 
| 58 | 
            +
                      
         | 
| 59 | 
            +
                    ERB
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                  
         | 
| 62 | 
            +
                  @from_data = if from_data.nil?
         | 
| 63 | 
            +
                    nil
         | 
| 64 | 
            +
                  elsif from_data.respond_to?( :call )
         | 
| 65 | 
            +
                    from_data
         | 
| 66 | 
            +
                  elsif from_data.respond_to?( :to_proc )
         | 
| 67 | 
            +
                    from_data.to_proc
         | 
| 68 | 
            +
                  else
         | 
| 69 | 
            +
                    raise TypeError.new binding.erb <<-ERB
         | 
| 70 | 
            +
                      `to_data:` keyword arg must be `nil`, respond to `#call` or respond
         | 
| 71 | 
            +
                      to `#to_proc`.
         | 
| 72 | 
            +
                      
         | 
| 73 | 
            +
                      Found value:
         | 
| 74 | 
            +
                      
         | 
| 75 | 
            +
                          <%= from_data.pretty_inspect %>
         | 
| 76 | 
            +
                      
         | 
| 77 | 
            +
                      (type <%= from_data.class %>)
         | 
| 78 | 
            +
                      
         | 
| 79 | 
            +
                    ERB
         | 
| 53 80 | 
             
                  end
         | 
| 54 81 | 
             
                end # #initialize
         | 
| 55 82 |  | 
| @@ -152,6 +179,15 @@ module NRSER::Types | |
| 152 179 | 
             
                end
         | 
| 153 180 |  | 
| 154 181 |  | 
| 182 | 
            +
                def from_data data
         | 
| 183 | 
            +
                  if @from_data.nil?
         | 
| 184 | 
            +
                    raise NoMethodError, "#from_data not defined"
         | 
| 185 | 
            +
                  end
         | 
| 186 | 
            +
                  
         | 
| 187 | 
            +
                  check @from_data.call( data )
         | 
| 188 | 
            +
                end
         | 
| 189 | 
            +
                
         | 
| 190 | 
            +
                
         | 
| 155 191 | 
             
                # Test if the type knows how to load values from strings.
         | 
| 156 192 | 
             
                # 
         | 
| 157 193 | 
             
                # If this method returns `true`, then we expect {#from_s} to succeed.
         | 
| @@ -176,6 +212,11 @@ module NRSER::Types | |
| 176 212 | 
             
                end # #has_to_data?
         | 
| 177 213 |  | 
| 178 214 |  | 
| 215 | 
            +
                def has_from_data?
         | 
| 216 | 
            +
                  ! @from_data.nil?
         | 
| 217 | 
            +
                end
         | 
| 218 | 
            +
                
         | 
| 219 | 
            +
                
         | 
| 179 220 | 
             
                # Dumps a value of this type to "data" - structures and values suitable
         | 
| 180 221 | 
             
                # for transport and storage, such as dumping to JSON or YAML, etc.
         | 
| 181 222 | 
             
                # 
         | 
| @@ -186,7 +227,7 @@ module NRSER::Types | |
| 186 227 | 
             
                #   The data representation of the value.
         | 
| 187 228 | 
             
                # 
         | 
| 188 229 | 
             
                def to_data value
         | 
| 189 | 
            -
                  if @ | 
| 230 | 
            +
                  if @to_data.nil?
         | 
| 190 231 | 
             
                    raise NoMethodError, "#to_data not defined"
         | 
| 191 232 | 
             
                  end
         | 
| 192 233 |  | 
    
        data/lib/nrser/version.rb
    CHANGED
    
    
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module NRSER::TestFixtures::AbstractMethodError
         | 
| 3 | 
            +
              
         | 
| 4 | 
            +
              class Base
         | 
| 5 | 
            +
                def f
         | 
| 6 | 
            +
                  raise NRSER::AbstractMethodError.new( self, __method__ )
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
              
         | 
| 10 | 
            +
              class Sub < Base; end
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
            end # module NRSER::TestFixtures::AbstractMethodError
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            describe_class NRSER::AbstractMethodError do
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              context(
         | 
| 18 | 
            +
                "when raising method is invoked through instance of defining class"
         | 
| 19 | 
            +
              ) do
         | 
| 20 | 
            +
                
         | 
| 21 | 
            +
                it "explains that the instance's class is abstract" do
         | 
| 22 | 
            +
                  expect {
         | 
| 23 | 
            +
                    NRSER::TestFixtures::AbstractMethodError::Base.new.f
         | 
| 24 | 
            +
                  }.to raise_error(
         | 
| 25 | 
            +
                    NRSER::AbstractMethodError,
         | 
| 26 | 
            +
                    /Base is an abstract class/
         | 
| 27 | 
            +
                  )
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
                
         | 
| 30 | 
            +
              end # when raising method is invoked through instance of defining class
         | 
| 31 | 
            +
              
         | 
| 32 | 
            +
              context "when raising method is invoked through instance of a subclass" do
         | 
| 33 | 
            +
                
         | 
| 34 | 
            +
                it "explains that an implementing class needs to be found or written" do
         | 
| 35 | 
            +
                  expect {
         | 
| 36 | 
            +
                    NRSER::TestFixtures::AbstractMethodError::Sub.new.f
         | 
| 37 | 
            +
                  }.to raise_error(
         | 
| 38 | 
            +
                    NRSER::AbstractMethodError,
         | 
| 39 | 
            +
                    /find a subclass of .*Sub to instantiate or write your own/
         | 
| 40 | 
            +
                  )
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                
         | 
| 43 | 
            +
              end # when raising method is invoked through instance of a subclass
         | 
| 44 | 
            +
              
         | 
| 45 | 
            +
              
         | 
| 46 | 
            +
            end # Class NRSER::AbstractMethodError Description
         | 
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            require 'nrser/meta/props'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'nrser/refinements'
         | 
| 4 | 
            +
            using NRSER
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            require 'nrser/refinements/types'
         | 
| 7 | 
            +
            using NRSER::Types
         | 
| 8 | 
            +
             | 
| 9 | 
            +
             | 
| 10 | 
            +
            describe NRSER::Meta::Props do
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
              describe_section "to and from data" do
         | 
| 13 | 
            +
              # ========================================================================
         | 
| 14 | 
            +
                
         | 
| 15 | 
            +
                before( :all ) {
         | 
| 16 | 
            +
                  @cat_class = Class.new( NRSER::Meta::Props::Base ) do
         | 
| 17 | 
            +
                    prop :name, type: t.non_empty_str
         | 
| 18 | 
            +
                    prop :breed, type: t.non_empty_str
         | 
| 19 | 
            +
                    prop :age, type: t.unsigned
         | 
| 20 | 
            +
                    
         | 
| 21 | 
            +
                    def self.name; 'Cat'; end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                }
         | 
| 24 | 
            +
                
         | 
| 25 | 
            +
                describe_group "simple nesting" do
         | 
| 26 | 
            +
                  
         | 
| 27 | 
            +
                  before( :all ) {
         | 
| 28 | 
            +
                    # IMPORTANT!!!  must bind *outside* the class declaration; can't use
         | 
| 29 | 
            +
                    #               @cat_class in there because it resolves to a (nil)
         | 
| 30 | 
            +
                    #               instance variable of the new class.
         | 
| 31 | 
            +
                    cat_class = @cat_class
         | 
| 32 | 
            +
                    
         | 
| 33 | 
            +
                    @owner_class = Class.new( NRSER::Meta::Props::Base ) do
         | 
| 34 | 
            +
                      prop :name, type: t.non_empty_str
         | 
| 35 | 
            +
                      
         | 
| 36 | 
            +
                      prop :cat, type: cat_class
         | 
| 37 | 
            +
                      
         | 
| 38 | 
            +
                      def self.name; 'Owner'; end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                    
         | 
| 41 | 
            +
                    @cat = @cat_class.new name: "Hooty", breed: "American Shorthair", age: 2
         | 
| 42 | 
            +
                    
         | 
| 43 | 
            +
                    @owner = @owner_class.new name: "Neil", cat: @cat
         | 
| 44 | 
            +
                  }
         | 
| 45 | 
            +
                  
         | 
| 46 | 
            +
                  it "is setup correctly" do
         | 
| 47 | 
            +
                    expect( @cat_class ).to be_a Class
         | 
| 48 | 
            +
                    expect( @cat_class.is_a? ::Class ).to be true
         | 
| 49 | 
            +
                    expect( @cat_class.name ).to eq "Cat"
         | 
| 50 | 
            +
                    expect( t.make @cat_class ).to be_a NRSER::Types::IsA
         | 
| 51 | 
            +
                    
         | 
| 52 | 
            +
                    name_prop = @owner_class.props[:name]
         | 
| 53 | 
            +
                    expect( name_prop.type ).to be t.non_empty_str
         | 
| 54 | 
            +
                    
         | 
| 55 | 
            +
                    cat_prop = @owner_class.props[:cat]
         | 
| 56 | 
            +
                    expect( cat_prop.type ).to be_a NRSER::Types::IsA
         | 
| 57 | 
            +
                    expect( cat_prop.type.klass ).to be @cat_class
         | 
| 58 | 
            +
                    expect( @cat_class.respond_to? :from_data ).to be true
         | 
| 59 | 
            +
                    expect( cat_prop.type.has_from_data? ).to be true
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                  
         | 
| 62 | 
            +
                  it "dumps to and loads from data" do
         | 
| 63 | 
            +
                    data = @owner.to_data        
         | 
| 64 | 
            +
                    restored = @owner_class.from_data data
         | 
| 65 | 
            +
                    expect( restored.to_data ).to eq data
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
                  
         | 
| 68 | 
            +
                end # Group "simple nesting" Description
         | 
| 69 | 
            +
                
         | 
| 70 | 
            +
                
         | 
| 71 | 
            +
              end # section to and from data
         | 
| 72 | 
            +
              # ************************************************************************
         | 
| 73 | 
            +
              
         | 
| 74 | 
            +
            end
         |