obfusk-data 0.0.2.SNAPSHOT.20130211214657 → 0.0.2.SNAPSHOT.20130212031255
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.
- data/README.md +26 -4
- data/Rakefile +7 -2
- data/lib/obfusk/data/base.rb +49 -0
- data/lib/obfusk/data/hamster.rb +65 -0
- data/lib/obfusk/data/hash.rb +70 -0
- data/lib/obfusk/data/version.rb +1 -1
- data/spec/_data.rb +94 -0
- data/spec/obfusk/data/hamster_spec.rb +84 -0
- data/spec/obfusk/data/hash_spec.rb +70 -0
- data/spec/obfusk/data_spec.rb +58 -134
- metadata +13 -7
    
        data/README.md
    CHANGED
    
    | @@ -51,6 +51,32 @@ Obfusk::Data.valid? tree, | |
| 51 51 | 
             
            # => true
         | 
| 52 52 | 
             
            ```
         | 
| 53 53 |  | 
| 54 | 
            +
            ```ruby
         | 
| 55 | 
            +
            class X < Obfusk::Data::ValidHash
         | 
| 56 | 
            +
              data do
         | 
| 57 | 
            +
                field :spam, []
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            class Y < Obfusk::Data::ValidHamster
         | 
| 62 | 
            +
              data do
         | 
| 63 | 
            +
                field :spam, []
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
            end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            x = X.new spam: 99; x[:spam] = 88
         | 
| 68 | 
            +
            # OK
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            X.new
         | 
| 71 | 
            +
            # raises Obfusk::Data::ValidHash::InvalidError
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            y = Y.new spam: 'yuck!'
         | 
| 74 | 
            +
            # OK
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            Y.put :invalid, 'oops.'
         | 
| 77 | 
            +
            # raises Obfusk::Data::ValidHamster::InvalidError
         | 
| 78 | 
            +
            ```
         | 
| 79 | 
            +
             | 
| 54 80 | 
             
            []: }}}1
         | 
| 55 81 |  | 
| 56 82 | 
             
            ## Specs & Docs
         | 
| @@ -64,10 +90,6 @@ Obfusk::Data.valid? tree, | |
| 64 90 | 
             
            ## TODO
         | 
| 65 91 | 
             
            []: {{{1
         | 
| 66 92 |  | 
| 67 | 
            -
              * add more ruby-ish api ?
         | 
| 68 | 
            -
             | 
| 69 | 
            -
            #
         | 
| 70 | 
            -
             | 
| 71 93 | 
             
              * write more specs
         | 
| 72 94 | 
             
              * write more docs
         | 
| 73 95 | 
             
              * show isa errors
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -1,5 +1,10 @@ | |
| 1 1 | 
             
            desc 'Run specs'
         | 
| 2 2 | 
             
            task :spec do
         | 
| 3 | 
            +
              sh 'rspec -c'
         | 
| 4 | 
            +
            end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            desc 'Run specs verbosely'
         | 
| 7 | 
            +
            task 'spec:verbose' do
         | 
| 3 8 | 
             
              sh 'rspec -cfd'
         | 
| 4 9 | 
             
            end
         | 
| 5 10 |  | 
| @@ -9,7 +14,7 @@ task :docs do | |
| 9 14 | 
             
            end
         | 
| 10 15 |  | 
| 11 16 | 
             
            desc 'List undocumented objects'
         | 
| 12 | 
            -
            task : | 
| 17 | 
            +
            task 'docs:undoc' do
         | 
| 13 18 | 
             
              sh 'yard stats --list-undoc'
         | 
| 14 19 | 
             
            end
         | 
| 15 20 |  | 
| @@ -27,6 +32,6 @@ task :snapshot do | |
| 27 32 | 
             
            end
         | 
| 28 33 |  | 
| 29 34 | 
             
            desc 'Undo SNAPSHOT gem'
         | 
| 30 | 
            -
            task 'snapshot | 
| 35 | 
            +
            task 'snapshot:undo' do
         | 
| 31 36 | 
             
              sh 'git checkout -- lib/obfusk/data/version.rb'
         | 
| 32 37 | 
             
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            # --                                                            ; {{{1
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # File        : obfusk/data/base.rb
         | 
| 4 | 
            +
            # Maintainer  : Felix C. Stegerman <flx@obfusk.net>
         | 
| 5 | 
            +
            # Date        : 2013-02-11
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # Copyright   : Copyright (C) 2013  Felix C. Stegerman
         | 
| 8 | 
            +
            # Licence     : GPLv2 or EPLv1
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # --                                                            ; }}}1
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'obfusk/data'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Obfusk
         | 
| 15 | 
            +
              module Data
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                module Base
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def self.included (base)
         | 
| 20 | 
            +
                    base.extend ClassMethods
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  module ClassMethods
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def data (*a, &b)
         | 
| 26 | 
            +
                      const_set :VALIDATOR, Obfusk::Data.data(*a, &b)
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    def union (*a, &b)
         | 
| 30 | 
            +
                      const_set :VALIDATOR, Obfusk::Data.union(*a, &b)
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def validate!
         | 
| 36 | 
            +
                    e = Obfusk::Data.validate self.class::VALIDATOR, self
         | 
| 37 | 
            +
                    raise self.class::InvalidError, e.join('; ') if e
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def valid?
         | 
| 41 | 
            +
                    Obfusk::Data.valid? self.class::VALIDATOR, self
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            # vim: set tw=70 sw=2 sts=2 et fdm=marker :
         | 
| @@ -0,0 +1,65 @@ | |
| 1 | 
            +
            # --                                                            ; {{{1
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # File        : obfusk/data/hamster.rb
         | 
| 4 | 
            +
            # Maintainer  : Felix C. Stegerman <flx@obfusk.net>
         | 
| 5 | 
            +
            # Date        : 2013-02-11
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # Copyright   : Copyright (C) 2013  Felix C. Stegerman
         | 
| 8 | 
            +
            # Licence     : GPLv2 or EPLv1
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # --                                                            ; }}}1
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'obfusk/data/base'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Obfusk
         | 
| 15 | 
            +
              module Data
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # @todo document
         | 
| 18 | 
            +
                # @note
         | 
| 19 | 
            +
                #   getting this to work depends on Hamster implementation details
         | 
| 20 | 
            +
                #   as well as some black magic ;-(
         | 
| 21 | 
            +
                class ValidHamster < Hamster::Hash                          # {{{1
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  include Base
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  class InvalidError < RuntimeError; end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def self.__from_hamster (x)
         | 
| 28 | 
            +
                    data  = x.instance_eval { [@trie, @default] }
         | 
| 29 | 
            +
                    y     = allocate
         | 
| 30 | 
            +
                    y.instance_eval { @trie, @default = data }
         | 
| 31 | 
            +
                    y
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def self.__to_hamster (x)
         | 
| 35 | 
            +
                    data  = x.instance_eval { [@trie, @default] }
         | 
| 36 | 
            +
                    y     = Hamster::Hash.allocate
         | 
| 37 | 
            +
                    y.instance_eval { @trie, @default = data }
         | 
| 38 | 
            +
                    y
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def self.new (*a, &b)
         | 
| 42 | 
            +
                    x = __from_hamster Hamster::Hash.new(*a, &b)
         | 
| 43 | 
            +
                    x.validate!; x
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def self.empty
         | 
| 47 | 
            +
                    x = @empty ||= new; x.validate!; x
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  def except (*a, &b)
         | 
| 51 | 
            +
                    y = self.class.__to_hamster self
         | 
| 52 | 
            +
                    x = self.class.__from_hamster y.except(*a, &b)
         | 
| 53 | 
            +
                    x.validate!; x
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  def transform (*a, &b)
         | 
| 57 | 
            +
                    x = super; x.validate!; x
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                end                                                         # }}}1
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            # vim: set tw=70 sw=2 sts=2 et fdm=marker :
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            # --                                                            ; {{{1
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # File        : obfusk/data/hash.rb
         | 
| 4 | 
            +
            # Maintainer  : Felix C. Stegerman <flx@obfusk.net>
         | 
| 5 | 
            +
            # Date        : 2013-02-11
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # Copyright   : Copyright (C) 2013  Felix C. Stegerman
         | 
| 8 | 
            +
            # Licence     : GPLv2 or EPLv1
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # --                                                            ; }}}1
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'obfusk/data/base'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Obfusk
         | 
| 15 | 
            +
              module Data
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # @todo document
         | 
| 18 | 
            +
                class ValidHash < Hash                                      # {{{1
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  include Base
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  class InvalidError < RuntimeError; end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  %w{
         | 
| 25 | 
            +
                    []= clear delete delete_if keep_if merge! reject! replace
         | 
| 26 | 
            +
                    select! shift store update
         | 
| 27 | 
            +
                  }.map(&:to_sym).each do |m|
         | 
| 28 | 
            +
                    define_method m do |*a, &b|
         | 
| 29 | 
            +
                      r = super(*a, &b); validate!; r
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def self.[] (*a, &b)
         | 
| 34 | 
            +
                    x = super; x.validate!; x
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def initialize (data = {}, &block)
         | 
| 38 | 
            +
                    super(&block); self.merge! data
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def compare_by_identity
         | 
| 42 | 
            +
                    raise NotImplementedError
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def invert
         | 
| 46 | 
            +
                    Hash[self].invert
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def merge (*a, &b)
         | 
| 50 | 
            +
                    x = super; x.validate!; x
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  def reject (*a, &b)
         | 
| 54 | 
            +
                    x = super; x.validate!; x
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def select (*a, &b)
         | 
| 58 | 
            +
                    x = self.class[super]; x.validate!; x                   # TODO
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  def to_hash
         | 
| 62 | 
            +
                    Hash[self]
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                end                                                         # }}}1
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            # vim: set tw=70 sw=2 sts=2 et fdm=marker :
         | 
    
        data/lib/obfusk/data/version.rb
    CHANGED
    
    
    
        data/spec/_data.rb
    ADDED
    
    | @@ -0,0 +1,94 @@ | |
| 1 | 
            +
            # --                                                            ; {{{1
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # File        : _data.rb
         | 
| 4 | 
            +
            # Maintainer  : Felix C. Stegerman <flx@obfusk.net>
         | 
| 5 | 
            +
            # Date        : 2013-02-11
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # Copyright   : Copyright (C) 2013  Felix C. Stegerman
         | 
| 8 | 
            +
            # Licence     : GPLv2 or EPLv1
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # --                                                            ; }}}1
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'obfusk/data'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Obfusk::Data__Spec
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              isa       = ->(cls, obj) { cls === obj } .curry
         | 
| 17 | 
            +
              is_string = isa[String]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              is_email  = ->(x) { %r{^.*@.*\.[a-z]+$}.match x }
         | 
| 20 | 
            +
              is_url    = ->(x) { %r{^https?://.*$}.match x }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              is_object_id = ->(x) {
         | 
| 23 | 
            +
                is_string[x] && x.length == 16 &&
         | 
| 24 | 
            +
                  x.chars.all? { |c| %{^[a-zA-Z0-9]$}.match c }
         | 
| 25 | 
            +
              }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              is_id_seq = ->(x) { isa[Enumberable, x] && x.all?(&is_object_id) }
         | 
| 28 | 
            +
              is_id_map = ->(m) {
         | 
| 29 | 
            +
                isa[Hash, m] && m.all? { |k,v| is_string[k] && is_object_id[v] }
         | 
| 30 | 
            +
              }
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              # --
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              Foo = Obfusk::Data.data other_fields: ->(x) { %r{^data_}.match x }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              Tree = Obfusk::Data.union :type do |_tree|
         | 
| 37 | 
            +
                data :empty
         | 
| 38 | 
            +
                data :leaf do
         | 
| 39 | 
            +
                  field :value, []
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
                data :node do
         | 
| 42 | 
            +
                  field [:left, :right], [], isa: [_tree]
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              # --
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              Address = Obfusk::Data.data do
         | 
| 49 | 
            +
                field [:street, :number, :postal_code, :town], [is_string]
         | 
| 50 | 
            +
                field :country, [is_string], optional: true
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              Person = Obfusk::Data.data do
         | 
| 54 | 
            +
                field [:first_name, :last_name, :phone_number], [is_string]
         | 
| 55 | 
            +
                field :email, [is_string, is_email]
         | 
| 56 | 
            +
                field :address, [], isa: [Address]
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              # --
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              Collection = Obfusk::Data.data do
         | 
| 62 | 
            +
                field :_id  , [is_object_id]
         | 
| 63 | 
            +
                field :app  , [is_string]
         | 
| 64 | 
            +
                field :icon , [is_object_id]
         | 
| 65 | 
            +
                field :items, [is_id_seq]
         | 
| 66 | 
            +
                field :title, [is_string], optional: true
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              Item = Obfusk::Data.data do
         | 
| 70 | 
            +
                field :_id            , [is_object_id]
         | 
| 71 | 
            +
                field :type           , [is_string]
         | 
| 72 | 
            +
                field :icon           , [is_object_id], nil: true
         | 
| 73 | 
            +
                field :data           , []            , optional: true
         | 
| 74 | 
            +
                field :title          , [is_string]   , optional: true
         | 
| 75 | 
            +
                field :url            , [is_url]      , optional: true
         | 
| 76 | 
            +
                field [:refs, :files] , [is_id_map]   , optional: true
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                # (not= (contains? x :url)
         | 
| 79 | 
            +
                #       (contains? (get x :files {}) :url))                 ; TODO
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              Item_files = Obfusk::Data.data do
         | 
| 83 | 
            +
                field :url, [is_url], optional: true
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              Image_item = Obfusk::Data.data isa: [Item] do
         | 
| 87 | 
            +
                field :icon , [:nil?]
         | 
| 88 | 
            +
                field :data , [:nil?], optional: true
         | 
| 89 | 
            +
                field :files, isa: [Item_files]
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            # vim: set tw=70 sw=2 sts=2 et fdm=marker :
         | 
| @@ -0,0 +1,84 @@ | |
| 1 | 
            +
            # --                                                            ; {{{1
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # File        : obfusk/data/hamster_spec.rb
         | 
| 4 | 
            +
            # Maintainer  : Felix C. Stegerman <flx@obfusk.net>
         | 
| 5 | 
            +
            # Date        : 2013-02-11
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # Copyright   : Copyright (C) 2013  Felix C. Stegerman
         | 
| 8 | 
            +
            # Licence     : GPLv2 or EPLv1
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # --                                                            ; }}}1
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'obfusk/data/hamster'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Obfusk::Data::Hamster__Spec
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              class Bar < Obfusk::Data::ValidHamster
         | 
| 17 | 
            +
                data other_fields: ->(x) { /other/.match x } do
         | 
| 18 | 
            +
                  field :bar, [->(x) { /bar/.match x }], optional: true
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              class Baz < Obfusk::Data::ValidHamster
         | 
| 23 | 
            +
                data do
         | 
| 24 | 
            +
                  field :baz  , []
         | 
| 25 | 
            +
                  field :maybe, [], optional: true
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              E = Obfusk::Data::ValidHamster::InvalidError
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              # --
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              describe Obfusk::Data::ValidHamster do
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                context 'Bar' do                                            # {{{1
         | 
| 36 | 
            +
                  it 'valid empty Bar (2x)' do
         | 
| 37 | 
            +
                    Bar.new; Bar.empty
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                  it 'valid Bar' do
         | 
| 40 | 
            +
                    Bar.new bar: 'bar?!'
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                  it 'valid Bar w/ other field' do
         | 
| 43 | 
            +
                    Bar.new some_other_field: 37
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                  it 'invalid Bar' do
         | 
| 46 | 
            +
                    expect { Bar.new baz: 42 }.to raise_error E
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                  it 'invalid Bar merge' do
         | 
| 49 | 
            +
                    b = Bar.new
         | 
| 50 | 
            +
                    expect { b.merge Hamster.hash baz: 42 }.to raise_error E
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                  it 'invalid Bar put' do
         | 
| 53 | 
            +
                    b = Bar.new
         | 
| 54 | 
            +
                    expect { b.put :bar, 'hi!' }.to raise_error E
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end                                                         # }}}1
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                context 'Baz' do                                            # {{{1
         | 
| 59 | 
            +
                  it 'valid Baz' do
         | 
| 60 | 
            +
                    Baz.new baz: 'ok!'
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                  it 'valid Baz except' do
         | 
| 63 | 
            +
                    b = Baz.new baz: 1, maybe: 2
         | 
| 64 | 
            +
                    b.except :maybe
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                  it 'invalid empty Baz (new)' do
         | 
| 67 | 
            +
                    expect { Baz.new }.to raise_error E
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                  it 'invalid empty Baz (empty)' do
         | 
| 70 | 
            +
                    expect { Baz.empty }.to raise_error E
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                  it 'invalid Baz except' do
         | 
| 73 | 
            +
                    b = Baz.new baz: 1, maybe: 2
         | 
| 74 | 
            +
                    expect { b.except :baz }.to raise_error E
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end                                                         # }}}1
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                # ... TODO ...
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            # vim: set tw=70 sw=2 sts=2 et fdm=marker :
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            # --                                                            ; {{{1
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # File        : obfusk/data/hash_spec.rb
         | 
| 4 | 
            +
            # Maintainer  : Felix C. Stegerman <flx@obfusk.net>
         | 
| 5 | 
            +
            # Date        : 2013-02-11
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # Copyright   : Copyright (C) 2013  Felix C. Stegerman
         | 
| 8 | 
            +
            # Licence     : GPLv2 or EPLv1
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # --                                                            ; }}}1
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'obfusk/data/hash'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Obfusk::Data::Hash__Spec
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              class Bar < Obfusk::Data::ValidHash
         | 
| 17 | 
            +
                data other_fields: ->(x) { /other/.match x } do
         | 
| 18 | 
            +
                  field :bar, [->(x) { /bar/.match x }], optional: true
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              class Baz < Obfusk::Data::ValidHash
         | 
| 23 | 
            +
                data do
         | 
| 24 | 
            +
                  field :baz, []
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              E = Obfusk::Data::ValidHash::InvalidError
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              # --
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              describe Obfusk::Data::ValidHash do
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                context 'Bar' do                                            # {{{1
         | 
| 35 | 
            +
                  it 'valid empty Bar' do
         | 
| 36 | 
            +
                    Bar.new
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                  it 'valid Bar' do
         | 
| 39 | 
            +
                    Bar.new bar: 'bar?!'
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                  it 'valid Bar w/ other field' do
         | 
| 42 | 
            +
                    Bar.new some_other_field: 37
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                  it 'invalid Bar' do
         | 
| 45 | 
            +
                    expect { Bar.new baz: 42 }.to raise_error E
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                  it 'invalid Bar merge' do
         | 
| 48 | 
            +
                    b = Bar.new
         | 
| 49 | 
            +
                    expect { b.merge baz: 42 }.to raise_error E
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                  it 'invalid Bar []=' do
         | 
| 52 | 
            +
                    b = Bar.new
         | 
| 53 | 
            +
                    expect { b[:bar] = 'hi!' }.to raise_error E
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end                                                         # }}}1
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                context 'Baz' do                                            # {{{1
         | 
| 58 | 
            +
                  it 'invalid Baz clear' do
         | 
| 59 | 
            +
                    b = Baz.new baz: 'ok'
         | 
| 60 | 
            +
                    expect { b.clear }.to raise_error E
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                end                                                         # }}}1
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                # ... TODO ...
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            # vim: set tw=70 sw=2 sts=2 et fdm=marker :
         | 
    
        data/spec/obfusk/data_spec.rb
    CHANGED
    
    | @@ -1,148 +1,72 @@ | |
| 1 1 | 
             
            # --                                                            ; {{{1
         | 
| 2 2 | 
             
            #
         | 
| 3 | 
            -
            # File        : obfusk/ | 
| 3 | 
            +
            # File        : obfusk/data_spec.rb
         | 
| 4 4 | 
             
            # Maintainer  : Felix C. Stegerman <flx@obfusk.net>
         | 
| 5 | 
            -
            # Date        : 2013-02- | 
| 5 | 
            +
            # Date        : 2013-02-11
         | 
| 6 6 | 
             
            #
         | 
| 7 7 | 
             
            # Copyright   : Copyright (C) 2013  Felix C. Stegerman
         | 
| 8 8 | 
             
            # Licence     : GPLv2 or EPLv1
         | 
| 9 9 | 
             
            #
         | 
| 10 10 | 
             
            # --                                                            ; }}}1
         | 
| 11 11 |  | 
| 12 | 
            -
            require ' | 
| 12 | 
            +
            require './spec/_data'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Obfusk::Data__Spec
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              describe Obfusk::Data do
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                context 'Foo' do                                            # {{{1
         | 
| 19 | 
            +
                  it 'valid empty Foo' do
         | 
| 20 | 
            +
                    should be_valid Foo, {}
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  it 'valid Foo' do
         | 
| 23 | 
            +
                    should be_valid Foo, { data_bar: 37 }
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                  it 'invalid Foo' do
         | 
| 26 | 
            +
                    should_not be_valid Foo, { baz: 42 }
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end                                                         # }}}1
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                context 'Tree' do                                           # {{{1
         | 
| 31 | 
            +
                  it 'valid empty Tree' do
         | 
| 32 | 
            +
                    should be_valid Tree, { type: :empty }
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                  it 'invalid empty Tree' do
         | 
| 35 | 
            +
                    should_not be_valid Tree, { type: :empty, Foo: 'hi!' }
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                  it 'valid Tree leaf' do
         | 
| 38 | 
            +
                    should be_valid Tree, { type: :leaf, value: 3.14 }
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                  it 'invalid Tree leaf' do
         | 
| 41 | 
            +
                    should_not be_valid Tree, { type: :leaf }
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                  it 'valid Tree node' do
         | 
| 44 | 
            +
                    should be_valid Tree,
         | 
| 45 | 
            +
                      { type: :node,
         | 
| 46 | 
            +
                        left: { type: :empty },
         | 
| 47 | 
            +
                        right: { type: :leaf, value: 'spam!' } }
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                  it 'invalid Tree node' do
         | 
| 50 | 
            +
                    should_not be_valid Tree,
         | 
| 51 | 
            +
                      { type: :node, left: { type: :empty }, right: nil }
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end                                                         # }}}1
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                context 'Address' do                                        # {{{1
         | 
| 56 | 
            +
                  it 'valid Address' do
         | 
| 57 | 
            +
                    should be_valid Address,
         | 
| 58 | 
            +
                      { street: 'baker street', number: '221b',
         | 
| 59 | 
            +
                        town: 'london', postal_code: '???', country: 'uk' }
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                  it 'invalid Address' do
         | 
| 62 | 
            +
                    should_not be_valid Address,
         | 
| 63 | 
            +
                      { street: 'baker street', number: 404 }
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end                                                         # }}}1
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                # ... TODO ...
         | 
| 13 68 |  | 
| 14 | 
            -
            # --
         | 
| 15 | 
            -
             | 
| 16 | 
            -
            isa       = ->(cls, obj) { cls === obj } .curry
         | 
| 17 | 
            -
            is_string = isa[String]
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            is_email  = ->(x) { %r{^.*@.*\.[a-z]+$}.match x }
         | 
| 20 | 
            -
            is_url    = ->(x) { %r{^https?://.*$}.match x }
         | 
| 21 | 
            -
             | 
| 22 | 
            -
            is_object_id = ->(x) {
         | 
| 23 | 
            -
              is_string[x] && x.length == 16 &&
         | 
| 24 | 
            -
                x.chars.all? { |c| %{^[a-zA-Z0-9]$}.match c }
         | 
| 25 | 
            -
            }
         | 
| 26 | 
            -
             | 
| 27 | 
            -
            is_id_seq = ->(x) { isa[Enumberable, x] && x.all?(&is_object_id) }
         | 
| 28 | 
            -
            is_id_map = ->(m) {
         | 
| 29 | 
            -
              isa[Hash, m] && m.all? { |k,v| is_string[k] && is_object_id[v] }
         | 
| 30 | 
            -
            }
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            # --
         | 
| 33 | 
            -
             | 
| 34 | 
            -
            foo = Obfusk::Data.data other_fields: ->(x) { %r{^data_}.match x }
         | 
| 35 | 
            -
             | 
| 36 | 
            -
            tree = Obfusk::Data.union :type do |_tree|
         | 
| 37 | 
            -
              data :empty
         | 
| 38 | 
            -
              data :leaf do
         | 
| 39 | 
            -
                field :value, []
         | 
| 40 | 
            -
              end
         | 
| 41 | 
            -
              data :node do
         | 
| 42 | 
            -
                field [:left, :right], [], isa: [_tree]
         | 
| 43 69 | 
             
              end
         | 
| 44 | 
            -
            end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
            # --
         | 
| 47 | 
            -
             | 
| 48 | 
            -
            address = Obfusk::Data.data do
         | 
| 49 | 
            -
              field [:street, :number, :postal_code, :town], [is_string]
         | 
| 50 | 
            -
              field :country, [is_string], optional: true
         | 
| 51 | 
            -
            end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
            person = Obfusk::Data.data do
         | 
| 54 | 
            -
              field [:first_name, :last_name, :phone_number], [is_string]
         | 
| 55 | 
            -
              field :email, [is_string, is_email]
         | 
| 56 | 
            -
              field :address, [], isa: [address]
         | 
| 57 | 
            -
            end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
            # --
         | 
| 60 | 
            -
             | 
| 61 | 
            -
            collection = Obfusk::Data.data do
         | 
| 62 | 
            -
              field :_id  , [is_object_id]
         | 
| 63 | 
            -
              field :app  , [is_string]
         | 
| 64 | 
            -
              field :icon , [is_object_id]
         | 
| 65 | 
            -
              field :items, [is_id_seq]
         | 
| 66 | 
            -
              field :title, [is_string], optional: true
         | 
| 67 | 
            -
            end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
            item = Obfusk::Data.data do
         | 
| 70 | 
            -
              field :_id            , [is_object_id]
         | 
| 71 | 
            -
              field :type           , [is_string]
         | 
| 72 | 
            -
              field :icon           , [is_object_id], nil: true
         | 
| 73 | 
            -
              field :data           , []            , optional: true
         | 
| 74 | 
            -
              field :title          , [is_string]   , optional: true
         | 
| 75 | 
            -
              field :url            , [is_url]      , optional: true
         | 
| 76 | 
            -
              field [:refs, :files] , [is_id_map]   , optional: true
         | 
| 77 | 
            -
             | 
| 78 | 
            -
              # (not= (contains? x :url)
         | 
| 79 | 
            -
              #       (contains? (get x :files {}) :url))                   ; TODO
         | 
| 80 | 
            -
            end
         | 
| 81 | 
            -
             | 
| 82 | 
            -
            item_files = Obfusk::Data.data do
         | 
| 83 | 
            -
              field :url, [is_url], optional: true
         | 
| 84 | 
            -
            end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
            image_item = Obfusk::Data.data isa: [item] do
         | 
| 87 | 
            -
              field :icon , [:nil?]
         | 
| 88 | 
            -
              field :data , [:nil?], optional: true
         | 
| 89 | 
            -
              field :files, isa: [item_files]
         | 
| 90 | 
            -
            end
         | 
| 91 | 
            -
             | 
| 92 | 
            -
            # --
         | 
| 93 | 
            -
             | 
| 94 | 
            -
            describe Obfusk::Data do
         | 
| 95 | 
            -
             | 
| 96 | 
            -
              context 'foo' do                                              # {{{1
         | 
| 97 | 
            -
                it 'valid empty foo' do
         | 
| 98 | 
            -
                  should be_valid foo, {}
         | 
| 99 | 
            -
                end
         | 
| 100 | 
            -
                it 'valid foo' do
         | 
| 101 | 
            -
                  should be_valid foo, { data_bar: 37 }
         | 
| 102 | 
            -
                end
         | 
| 103 | 
            -
                it 'invalid foo' do
         | 
| 104 | 
            -
                  should_not be_valid foo, { baz: 42 }
         | 
| 105 | 
            -
                end
         | 
| 106 | 
            -
              end                                                           # }}}1
         | 
| 107 | 
            -
             | 
| 108 | 
            -
              context 'tree' do                                             # {{{1
         | 
| 109 | 
            -
                it 'valid empty tree' do
         | 
| 110 | 
            -
                  should be_valid tree, { type: :empty }
         | 
| 111 | 
            -
                end
         | 
| 112 | 
            -
                it 'invalid empty tree' do
         | 
| 113 | 
            -
                  should_not be_valid tree, { type: :empty, foo: 'hi!' }
         | 
| 114 | 
            -
                end
         | 
| 115 | 
            -
                it 'valid tree leaf' do
         | 
| 116 | 
            -
                  should be_valid tree, { type: :leaf, value: 3.14 }
         | 
| 117 | 
            -
                end
         | 
| 118 | 
            -
                it 'invalid tree leaf' do
         | 
| 119 | 
            -
                  should_not be_valid tree, { type: :leaf }
         | 
| 120 | 
            -
                end
         | 
| 121 | 
            -
                it 'valid tree node' do
         | 
| 122 | 
            -
                  should be_valid tree,
         | 
| 123 | 
            -
                    { type: :node,
         | 
| 124 | 
            -
                      left: { type: :empty },
         | 
| 125 | 
            -
                      right: { type: :leaf, value: 'spam!' } }
         | 
| 126 | 
            -
                end
         | 
| 127 | 
            -
                it 'invalid tree node' do
         | 
| 128 | 
            -
                  should_not be_valid tree,
         | 
| 129 | 
            -
                    { type: :node, left: { type: :empty }, right: nil }
         | 
| 130 | 
            -
                end
         | 
| 131 | 
            -
              end                                                           # }}}1
         | 
| 132 | 
            -
             | 
| 133 | 
            -
              context 'address' do                                          # {{{1
         | 
| 134 | 
            -
                it 'valid address' do
         | 
| 135 | 
            -
                  should be_valid address,
         | 
| 136 | 
            -
                    { street: 'baker street', number: '221b',
         | 
| 137 | 
            -
                      town: 'london', postal_code: '???', country: 'uk' }
         | 
| 138 | 
            -
                end
         | 
| 139 | 
            -
                it 'invalid address' do
         | 
| 140 | 
            -
                  should_not be_valid address,
         | 
| 141 | 
            -
                    { street: 'baker street', number: 404 }
         | 
| 142 | 
            -
                end
         | 
| 143 | 
            -
              end                                                           # }}}1
         | 
| 144 | 
            -
             | 
| 145 | 
            -
              # ... TODO ...
         | 
| 146 70 |  | 
| 147 71 | 
             
            end
         | 
| 148 72 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: obfusk-data
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0.2.SNAPSHOT. | 
| 4 | 
            +
              version: 0.0.2.SNAPSHOT.20130212031255
         | 
| 5 5 | 
             
              prerelease: 6
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -13,7 +13,7 @@ date: 2013-02-11 00:00:00.000000000 Z | |
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: hamster
         | 
| 16 | 
            -
              requirement: & | 
| 16 | 
            +
              requirement: &20985220 !ruby/object:Gem::Requirement
         | 
| 17 17 | 
             
                none: false
         | 
| 18 18 | 
             
                requirements:
         | 
| 19 19 | 
             
                - - ! '>='
         | 
| @@ -21,10 +21,10 @@ dependencies: | |
| 21 21 | 
             
                    version: '0'
         | 
| 22 22 | 
             
              type: :runtime
         | 
| 23 23 | 
             
              prerelease: false
         | 
| 24 | 
            -
              version_requirements: * | 
| 24 | 
            +
              version_requirements: *20985220
         | 
| 25 25 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 26 26 | 
             
              name: rake
         | 
| 27 | 
            -
              requirement: & | 
| 27 | 
            +
              requirement: &20928520 !ruby/object:Gem::Requirement
         | 
| 28 28 | 
             
                none: false
         | 
| 29 29 | 
             
                requirements:
         | 
| 30 30 | 
             
                - - ! '>='
         | 
| @@ -32,10 +32,10 @@ dependencies: | |
| 32 32 | 
             
                    version: '0'
         | 
| 33 33 | 
             
              type: :development
         | 
| 34 34 | 
             
              prerelease: false
         | 
| 35 | 
            -
              version_requirements: * | 
| 35 | 
            +
              version_requirements: *20928520
         | 
| 36 36 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 37 37 | 
             
              name: rspec
         | 
| 38 | 
            -
              requirement: & | 
| 38 | 
            +
              requirement: &20927780 !ruby/object:Gem::Requirement
         | 
| 39 39 | 
             
                none: false
         | 
| 40 40 | 
             
                requirements:
         | 
| 41 41 | 
             
                - - ! '>='
         | 
| @@ -43,7 +43,7 @@ dependencies: | |
| 43 43 | 
             
                    version: '0'
         | 
| 44 44 | 
             
              type: :development
         | 
| 45 45 | 
             
              prerelease: false
         | 
| 46 | 
            -
              version_requirements: * | 
| 46 | 
            +
              version_requirements: *20927780
         | 
| 47 47 | 
             
            description: ! '...
         | 
| 48 48 |  | 
| 49 49 | 
             
            '
         | 
| @@ -56,8 +56,14 @@ files: | |
| 56 56 | 
             
            - .yardopts
         | 
| 57 57 | 
             
            - README.md
         | 
| 58 58 | 
             
            - Rakefile
         | 
| 59 | 
            +
            - lib/obfusk/data/hamster.rb
         | 
| 59 60 | 
             
            - lib/obfusk/data/version.rb
         | 
| 61 | 
            +
            - lib/obfusk/data/hash.rb
         | 
| 62 | 
            +
            - lib/obfusk/data/base.rb
         | 
| 60 63 | 
             
            - lib/obfusk/data.rb
         | 
| 64 | 
            +
            - spec/_data.rb
         | 
| 65 | 
            +
            - spec/obfusk/data/hash_spec.rb
         | 
| 66 | 
            +
            - spec/obfusk/data/hamster_spec.rb
         | 
| 61 67 | 
             
            - spec/obfusk/data_spec.rb
         | 
| 62 68 | 
             
            - obfusk-data.gemspec
         | 
| 63 69 | 
             
            homepage: https://github.com/obfusk/rb-obfusk-data
         |