store 0.0.5 → 0.0.6
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/.gitignore +1 -0
- data/.travis.yml +6 -0
- data/README.md +6 -1
- data/example.rb +29 -10
- data/lib/store.rb +28 -62
- data/lib/store/entity_references.rb +17 -0
- data/lib/store/repo.rb +7 -2
- data/lib/store/resolver.rb +18 -0
- data/lib/store/resolver/data_mapper.rb +22 -0
- data/lib/store/resolver/entity_mapper.rb +23 -0
- data/lib/store/version.rb +1 -1
- data/spec/entity_references_spec.rb +39 -0
- data/spec/helper.rb +14 -0
- data/spec/resolver/data_mapper_spec.rb +50 -0
- data/spec/resolver/entity_mapper_spec.rb +51 -0
- data/spec/resolver/resolver_spec.rb +30 -0
- data/spec/store_repo_spec.rb +34 -5
- data/store.gemspec +1 -0
- metadata +29 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 6f95b1ab0e7baa12a07c3b53d297f42da47440ac
         | 
| 4 | 
            +
              data.tar.gz: 0dcaa59a8fe5af7d4678bb9ab714c335cd95894d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a224bbb8c5330b40ae561c85e65c3fc05669afd2eb2b026acc40eddc2b099ca0719fde7e9acad7227afbc309ae3840beb4d559d82ffc0fc881c3145776e4334d
         | 
| 7 | 
            +
              data.tar.gz: 4c9595417be360e5b12d35bb6bbcc4f8c36037071027d32af0bdefd513775a4d932198aceeda1f55fdbd2914dce12dea8d92ba8191813eb2f8b32cd8666228c1
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,7 +1,12 @@ | |
| 1 | 
            -
            # Store | 
| 1 | 
            +
            # Store
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            [](http://badge.fury.io/rb/store) [](https://travis-ci.org/holderbaum/store)
         | 
| 2 4 |  | 
| 3 5 | 
             
            Implementations for using the Repository- and Data Mapper Pattern in ruby
         | 
| 4 6 |  | 
| 7 | 
            +
            **Important:** We are still ignoring dirty tracking, so this is not for
         | 
| 8 | 
            +
            heavy-load environments! [Issue](https://github.com/holderbaum/store/issues/1)
         | 
| 9 | 
            +
             | 
| 5 10 | 
             
            ## Installation
         | 
| 6 11 |  | 
| 7 12 | 
             
            Add this line to your application's Gemfile:
         | 
    
        data/example.rb
    CHANGED
    
    | @@ -18,7 +18,15 @@ class Catalog | |
| 18 18 | 
             
            end
         | 
| 19 19 |  | 
| 20 20 | 
             
            class Product
         | 
| 21 | 
            -
              attr_accessor :name, :price
         | 
| 21 | 
            +
              attr_accessor :name, :price, :discount
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def discounted_price
         | 
| 24 | 
            +
                price * (1 - discount)
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              def discount
         | 
| 28 | 
            +
                @discount || 0
         | 
| 29 | 
            +
              end
         | 
| 22 30 | 
             
            end
         | 
| 23 31 |  | 
| 24 32 | 
             
            # EntityMappers ################################################################
         | 
| @@ -59,15 +67,17 @@ class ProductEntityMapper < Store::EntityMapper | |
| 59 67 | 
             
              def map(product)
         | 
| 60 68 | 
             
                {
         | 
| 61 69 | 
             
                  'name' => product.name,
         | 
| 62 | 
            -
                  'price' => product.price
         | 
| 70 | 
            +
                  'price' => product.price,
         | 
| 71 | 
            +
                  'discount' => product.discount
         | 
| 63 72 | 
             
                }
         | 
| 64 73 | 
             
              end
         | 
| 65 74 |  | 
| 66 75 | 
             
              def unmap(cls, mapped)
         | 
| 67 | 
            -
                 | 
| 68 | 
            -
                 | 
| 69 | 
            -
                 | 
| 70 | 
            -
                 | 
| 76 | 
            +
                product = cls.new
         | 
| 77 | 
            +
                product.name = mapped['name']
         | 
| 78 | 
            +
                product.price = mapped['price']
         | 
| 79 | 
            +
                product.discount = mapped['discount']
         | 
| 80 | 
            +
                product
         | 
| 71 81 | 
             
              end
         | 
| 72 82 | 
             
            end
         | 
| 73 83 |  | 
| @@ -95,12 +105,12 @@ class MemoryDataMapper < Store::DataMapper | |
| 95 105 | 
             
                id
         | 
| 96 106 | 
             
              end
         | 
| 97 107 |  | 
| 98 | 
            -
              def single_find( | 
| 99 | 
            -
                dup(@items[ | 
| 108 | 
            +
              def single_find(id)
         | 
| 109 | 
            +
                dup(@items[id])
         | 
| 100 110 | 
             
              end
         | 
| 101 111 |  | 
| 102 | 
            -
              def bulk_find( | 
| 103 | 
            -
                @items.values_at(* | 
| 112 | 
            +
              def bulk_find(ids)
         | 
| 113 | 
            +
                @items.values_at(*ids).map do |data|
         | 
| 104 114 | 
             
                  dup data
         | 
| 105 115 | 
             
                end
         | 
| 106 116 | 
             
              end
         | 
| @@ -171,6 +181,12 @@ class Repo < Store::Repo | |
| 171 181 | 
             
              end
         | 
| 172 182 | 
             
            end
         | 
| 173 183 |  | 
| 184 | 
            +
            class DiscountedProductFactory < Struct.new(:repo)
         | 
| 185 | 
            +
              def build(name, price = 100)
         | 
| 186 | 
            +
                repo.build 'Product', :name => name, :price => price, :discount => 0.25
         | 
| 187 | 
            +
              end
         | 
| 188 | 
            +
            end
         | 
| 189 | 
            +
             | 
| 174 190 | 
             
            repo = Repo.new(entities, data_mappers, entity_mappers)
         | 
| 175 191 |  | 
| 176 192 | 
             
            # Usage ########################################################################
         | 
| @@ -179,8 +195,11 @@ editor = repo.build 'User', :name => 'Mr. Repo' | |
| 179 195 |  | 
| 180 196 | 
             
            catalog = repo.build 'Catalog', :name => 'Catalog 1', :editor => editor
         | 
| 181 197 |  | 
| 198 | 
            +
            factory = DiscountedProductFactory.new(repo)
         | 
| 199 | 
            +
             | 
| 182 200 | 
             
            catalog.add_product repo.build('Product', :name => 'Pickaxe', :price => 100)
         | 
| 183 201 | 
             
            catalog.add_product repo.build('Product', :name => 'Scredriver', :price => 400)
         | 
| 202 | 
            +
            catalog.add_product factory.build('Pair of shoes')
         | 
| 184 203 |  | 
| 185 204 | 
             
            p 'save call'
         | 
| 186 205 | 
             
            repo.save(catalog)
         | 
    
        data/lib/store.rb
    CHANGED
    
    | @@ -2,14 +2,15 @@ require 'store/repo' | |
| 2 2 | 
             
            require 'store/ref'
         | 
| 3 3 | 
             
            require 'store/entity_mapper'
         | 
| 4 4 | 
             
            require 'store/data_mapper'
         | 
| 5 | 
            +
            require 'store/resolver'
         | 
| 6 | 
            +
            require 'store/entity_references'
         | 
| 5 7 |  | 
| 6 8 | 
             
            class Store
         | 
| 7 9 | 
             
              def initialize(entity_classes, data_mapping, entity_mapping)
         | 
| 8 | 
            -
                @entity_classes | 
| 9 | 
            -
                @ | 
| 10 | 
            -
                @ | 
| 11 | 
            -
             | 
| 12 | 
            -
                @entity_references = Hash.new
         | 
| 10 | 
            +
                @entity_classes         = entity_classes
         | 
| 11 | 
            +
                @resolver_data_mapper   = Resolver::DataMapper.new(data_mapping)
         | 
| 12 | 
            +
                @resolver_entity_mapper = Resolver::EntityMapper.new(self, entity_mapping)
         | 
| 13 | 
            +
                @entity_references      = EntityReferences.new
         | 
| 13 14 | 
             
              end
         | 
| 14 15 |  | 
| 15 16 | 
             
              def build(entity_class_name, attributes = {})
         | 
| @@ -34,7 +35,7 @@ class Store | |
| 34 35 | 
             
              end
         | 
| 35 36 |  | 
| 36 37 | 
             
              def remove(entity)
         | 
| 37 | 
            -
                data_mapper =  | 
| 38 | 
            +
                data_mapper = data_mapper(entity)
         | 
| 38 39 | 
             
                raise_unless_data_mapper_found(entity, data_mapper)
         | 
| 39 40 |  | 
| 40 41 | 
             
                reference = find_entity_reference(entity)
         | 
| @@ -44,8 +45,7 @@ class Store | |
| 44 45 | 
             
              end
         | 
| 45 46 |  | 
| 46 47 | 
             
              def query(query)
         | 
| 47 | 
            -
                data_mapper =  | 
| 48 | 
            -
                entity_mapper = entity_mapper_for_query(query)
         | 
| 48 | 
            +
                data_mapper = data_mapper(query)
         | 
| 49 49 | 
             
                entity_class = @entity_classes[query.entity]
         | 
| 50 50 |  | 
| 51 51 | 
             
                raise_unless_data_mapper_found(query, data_mapper)
         | 
| @@ -53,7 +53,7 @@ class Store | |
| 53 53 | 
             
                mapped_entities_with_references = data_mapper.select(query) || {}
         | 
| 54 54 |  | 
| 55 55 | 
             
                mapped_entities_with_references.map do |reference, mapped_entity|
         | 
| 56 | 
            -
                  entity = entity_mapper | 
| 56 | 
            +
                  entity = entity_mapper(query).unmap(entity_class, mapped_entity)
         | 
| 57 57 | 
             
                  save_entity_reference reference, entity
         | 
| 58 58 | 
             
                  entity
         | 
| 59 59 | 
             
                end
         | 
| @@ -68,21 +68,19 @@ class Store | |
| 68 68 | 
             
              end
         | 
| 69 69 |  | 
| 70 70 | 
             
              def single_load(ref)
         | 
| 71 | 
            -
                data_mapper =  | 
| 72 | 
            -
                entity_mapper = entity_mapper_for_ref(ref)
         | 
| 71 | 
            +
                data_mapper = data_mapper(ref)
         | 
| 73 72 | 
             
                entity_class = @entity_classes[ref.entity_type]
         | 
| 74 73 | 
             
                reference = ref.reference
         | 
| 75 74 |  | 
| 76 75 | 
             
                mapped_entity = data_mapper.single_find(reference)
         | 
| 77 76 |  | 
| 78 | 
            -
                entity = entity_mapper | 
| 77 | 
            +
                entity = entity_mapper(ref).unmap(entity_class, mapped_entity)
         | 
| 79 78 | 
             
                save_entity_reference reference, entity
         | 
| 80 79 | 
             
                entity
         | 
| 81 80 | 
             
              end
         | 
| 82 81 |  | 
| 83 82 | 
             
              def bulk_load(refs)
         | 
| 84 | 
            -
                data_mapper =  | 
| 85 | 
            -
                entity_mapper = entity_mapper_for_ref(refs.first)
         | 
| 83 | 
            +
                data_mapper = data_mapper(refs.first)
         | 
| 86 84 | 
             
                entity_class = @entity_classes[refs.first.entity_type]
         | 
| 87 85 |  | 
| 88 86 | 
             
                references = refs.map(&:reference)
         | 
| @@ -93,7 +91,7 @@ class Store | |
| 93 91 | 
             
                references.each_with_index do |reference, i|
         | 
| 94 92 | 
             
                  mapped_entity = mapped_entities[i]
         | 
| 95 93 |  | 
| 96 | 
            -
                  entity = entity_mapper. | 
| 94 | 
            +
                  entity = entity_mapper(refs.first).unmap(entity_class, mapped_entity)
         | 
| 97 95 | 
             
                  save_entity_reference reference, entity
         | 
| 98 96 | 
             
                  entities << entity
         | 
| 99 97 | 
             
                end
         | 
| @@ -105,82 +103,50 @@ class Store | |
| 105 103 | 
             
              def save_entity(entity)
         | 
| 106 104 | 
             
                return nil unless entity
         | 
| 107 105 |  | 
| 108 | 
            -
                data_mapper =  | 
| 106 | 
            +
                data_mapper = data_mapper(entity)
         | 
| 109 107 | 
             
                raise_unless_data_mapper_found(entity, data_mapper)
         | 
| 110 108 |  | 
| 111 109 | 
             
                reference = find_entity_reference(entity)
         | 
| 112 110 | 
             
                if reference.nil?
         | 
| 113 | 
            -
                  reference = data_mapper.insert( | 
| 111 | 
            +
                  reference = data_mapper.insert(extract_entity_attributes(entity))
         | 
| 114 112 | 
             
                  save_entity_reference(reference, entity)
         | 
| 115 113 | 
             
                else
         | 
| 116 | 
            -
                  data_mapper.update(reference,  | 
| 114 | 
            +
                  data_mapper.update(reference, extract_entity_attributes(entity))
         | 
| 117 115 | 
             
                end
         | 
| 118 116 |  | 
| 119 | 
            -
                Ref.new( | 
| 117 | 
            +
                Ref.new(extract_entity_class_name(entity), reference)
         | 
| 120 118 | 
             
              end
         | 
| 121 119 |  | 
| 122 120 | 
             
              def raise_unless_data_mapper_found(source, data_mapper)
         | 
| 123 121 | 
             
                raise "No data_mapper for #{source.inspect} found" unless data_mapper
         | 
| 124 122 | 
             
              end
         | 
| 125 123 |  | 
| 126 | 
            -
              def  | 
| 127 | 
            -
                 | 
| 128 | 
            -
                entity_mapper.new(self).map(entity)
         | 
| 129 | 
            -
              end
         | 
| 130 | 
            -
             | 
| 131 | 
            -
              def entity_mapper_for_entity(entity)
         | 
| 132 | 
            -
                type = entity_type(entity)
         | 
| 133 | 
            -
                entity_mapper_for_type(type)
         | 
| 134 | 
            -
              end
         | 
| 135 | 
            -
             | 
| 136 | 
            -
              def entity_mapper_for_query(query)
         | 
| 137 | 
            -
                type = query.entity
         | 
| 138 | 
            -
                entity_mapper_for_type(type)
         | 
| 139 | 
            -
              end
         | 
| 140 | 
            -
             | 
| 141 | 
            -
              def entity_mapper_for_ref(ref)
         | 
| 142 | 
            -
                type = ref.entity_type
         | 
| 143 | 
            -
                entity_mapper_for_type(type)
         | 
| 144 | 
            -
              end
         | 
| 145 | 
            -
             | 
| 146 | 
            -
              def entity_mapper_for_type(type)
         | 
| 147 | 
            -
                @entity_mapping[type]
         | 
| 148 | 
            -
              end
         | 
| 149 | 
            -
             | 
| 150 | 
            -
              def entity_type(entity)
         | 
| 151 | 
            -
                entity_class = entity.class
         | 
| 152 | 
            -
                entity_class.name.split('::').last
         | 
| 153 | 
            -
              end
         | 
| 154 | 
            -
             | 
| 155 | 
            -
              def data_mapper_for_entity(entity)
         | 
| 156 | 
            -
                type = entity_type(entity)
         | 
| 157 | 
            -
                data_mapper_for_type type
         | 
| 124 | 
            +
              def data_mapper(obj)
         | 
| 125 | 
            +
                @resolver_data_mapper.resolve_data_mapper(obj)
         | 
| 158 126 | 
             
              end
         | 
| 159 127 |  | 
| 160 | 
            -
              def  | 
| 161 | 
            -
                 | 
| 162 | 
            -
                data_mapper_for_type type
         | 
| 128 | 
            +
              def entity_mapper(obj)
         | 
| 129 | 
            +
                @resolver_entity_mapper.resolve_entity_mapper(obj)
         | 
| 163 130 | 
             
              end
         | 
| 164 131 |  | 
| 165 | 
            -
              def  | 
| 166 | 
            -
                 | 
| 167 | 
            -
                data_mapper_for_type type
         | 
| 132 | 
            +
              def extract_entity_attributes(entity)
         | 
| 133 | 
            +
                entity_mapper(entity).map(entity)
         | 
| 168 134 | 
             
              end
         | 
| 169 135 |  | 
| 170 | 
            -
              def  | 
| 171 | 
            -
                @ | 
| 136 | 
            +
              def extract_entity_class_name(obj)
         | 
| 137 | 
            +
                @resolver_entity_mapper.extract_entity_class_name_from_object(obj)
         | 
| 172 138 | 
             
              end
         | 
| 173 139 |  | 
| 174 140 | 
             
              def find_entity_reference(entity)
         | 
| 175 | 
            -
                @entity_references | 
| 141 | 
            +
                @entity_references.find(entity)
         | 
| 176 142 | 
             
              end
         | 
| 177 143 |  | 
| 178 144 | 
             
              def save_entity_reference(reference, entity)
         | 
| 179 | 
            -
                @entity_references | 
| 145 | 
            +
                @entity_references.save(reference, entity)
         | 
| 180 146 | 
             
              end
         | 
| 181 147 |  | 
| 182 148 | 
             
              def remove_entity_reference(entity)
         | 
| 183 | 
            -
                @entity_references. | 
| 149 | 
            +
                @entity_references.remove entity
         | 
| 184 150 | 
             
              end
         | 
| 185 151 |  | 
| 186 152 | 
             
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            class EntityReferences
         | 
| 2 | 
            +
              def initialize
         | 
| 3 | 
            +
                @hash = Hash.new
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def save(id, entity)
         | 
| 7 | 
            +
                @hash[entity.object_id] = id
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def find(entity)
         | 
| 11 | 
            +
                @hash[entity.object_id]
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def remove(entity)
         | 
| 15 | 
            +
                @hash.delete entity.object_id
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
    
        data/lib/store/repo.rb
    CHANGED
    
    | @@ -10,11 +10,16 @@ class Store | |
| 10 10 | 
             
                  @store.build(entity, *args)
         | 
| 11 11 | 
             
                end
         | 
| 12 12 |  | 
| 13 | 
            -
                def save( | 
| 14 | 
            -
                  @store.save( | 
| 13 | 
            +
                def save(entities)
         | 
| 14 | 
            +
                  @store.save(entities)
         | 
| 15 15 | 
             
                  true
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 | 
            +
                def save_and_load(entities)
         | 
| 19 | 
            +
                  refs = @store.save(entities)
         | 
| 20 | 
            +
                  @store.load(refs)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 18 23 | 
             
                def remove(entity)
         | 
| 19 24 | 
             
                  @store.remove(entity)
         | 
| 20 25 | 
             
                  true
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            require 'store/resolver/entity_mapper'
         | 
| 2 | 
            +
            require 'store/resolver/data_mapper'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Resolver
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def extract_entity_class_name_from_ref(ref)
         | 
| 7 | 
            +
                ref.entity_type
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def extract_entity_class_name_from_query(query)
         | 
| 11 | 
            +
                query.entity
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def extract_entity_class_name_from_object(obj)
         | 
| 15 | 
            +
                obj.class.name.split('::').last
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            module Resolver
         | 
| 2 | 
            +
              class DataMapper
         | 
| 3 | 
            +
                include Resolver
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
                def initialize(mapping)
         | 
| 6 | 
            +
                  @mapping = mapping
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
              
         | 
| 9 | 
            +
                def resolve_data_mapper(obj)
         | 
| 10 | 
            +
                  @mapping[
         | 
| 11 | 
            +
                    if obj.kind_of? Store::Ref
         | 
| 12 | 
            +
                      extract_entity_class_name_from_ref(obj)
         | 
| 13 | 
            +
                    elsif obj.kind_of? Store::Query
         | 
| 14 | 
            +
                      extract_entity_class_name_from_query(obj)
         | 
| 15 | 
            +
                    else
         | 
| 16 | 
            +
                      extract_entity_class_name_from_object(obj)
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  ]
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            module Resolver
         | 
| 2 | 
            +
              class EntityMapper
         | 
| 3 | 
            +
                include Resolver
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
                def initialize(store, mapping)
         | 
| 6 | 
            +
                  @store = store
         | 
| 7 | 
            +
                  @mapping = mapping
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              
         | 
| 10 | 
            +
                def resolve_entity_mapper(obj)
         | 
| 11 | 
            +
                  @mapping[
         | 
| 12 | 
            +
                    if obj.kind_of? Store::Ref
         | 
| 13 | 
            +
                      extract_entity_class_name_from_ref(obj)
         | 
| 14 | 
            +
                    elsif obj.kind_of? Store::Query
         | 
| 15 | 
            +
                      extract_entity_class_name_from_query(obj)
         | 
| 16 | 
            +
                    else
         | 
| 17 | 
            +
                      extract_entity_class_name_from_object(obj)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  ].new(@store)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
    
        data/lib/store/version.rb
    CHANGED
    
    
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'entity references' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { EntityReferences.new }
         | 
| 6 | 
            +
              let(:id) { 43 }
         | 
| 7 | 
            +
              let(:object_id) { 42 }
         | 
| 8 | 
            +
              let(:entity) { Struct.new(:object_id).new(object_id) }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              describe 'save' do
         | 
| 11 | 
            +
                it 'returns the passed id' do
         | 
| 12 | 
            +
                  assert_equal id, subject.save(id, entity)
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              describe 'find' do
         | 
| 17 | 
            +
                it 'returns the passed id' do
         | 
| 18 | 
            +
                  subject.save(id, entity)
         | 
| 19 | 
            +
                  assert_equal id, subject.find(entity)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              describe 'remove' do
         | 
| 24 | 
            +
                it 'returns the passed id' do
         | 
| 25 | 
            +
                  subject.save(id, entity)
         | 
| 26 | 
            +
                  assert_equal id, subject.remove(entity)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              describe 'integration' do
         | 
| 31 | 
            +
                it 'saves an entity, finds it and removes it after that' do
         | 
| 32 | 
            +
                  subject.save(id, entity)
         | 
| 33 | 
            +
                  assert_equal id, subject.find(entity)
         | 
| 34 | 
            +
                  subject.remove(entity)
         | 
| 35 | 
            +
                  assert_nil subject.find(entity)
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            end
         | 
    
        data/spec/helper.rb
    CHANGED
    
    | @@ -10,3 +10,17 @@ require 'ostruct' | |
| 10 10 |  | 
| 11 11 | 
             
            require 'store'
         | 
| 12 12 |  | 
| 13 | 
            +
            class MiniTest::Spec
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def faked_class(class_name)
         | 
| 16 | 
            +
                faked_class = Class.new do
         | 
| 17 | 
            +
                  class << self
         | 
| 18 | 
            +
                    attr_accessor :name
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                faked_class.name = class_name
         | 
| 23 | 
            +
                faked_class
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            end
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Resolver::DataMapper do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { Resolver::DataMapper.new(mapping) }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              # entites
         | 
| 8 | 
            +
              let(:foo) { faked_class('Foo').new }
         | 
| 9 | 
            +
              let(:bar) { faked_class('Nested::Bar').new }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              # data mapper
         | 
| 12 | 
            +
              FooDataMapper = Class.new(Store::DataMapper)
         | 
| 13 | 
            +
              BarDataMapper = Class.new(Store::DataMapper)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              let(:mapping) do
         | 
| 16 | 
            +
                {
         | 
| 17 | 
            +
                'Foo' => FooDataMapper,
         | 
| 18 | 
            +
                'Bar' => BarDataMapper,
         | 
| 19 | 
            +
                }
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              it 'validates the subject' do
         | 
| 23 | 
            +
                assert_instance_of Resolver::DataMapper, subject
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              it 'resolves data mapper class from Store::Ref' do
         | 
| 27 | 
            +
                ref = Store::Ref.new('Foo', 42)
         | 
| 28 | 
            +
                assert_equal FooDataMapper, subject.resolve_data_mapper(ref)
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              it 'resolves data mapper class from Store::Query' do
         | 
| 32 | 
            +
                query = Store::Query.new('Foo', :query_name, :some, :args)
         | 
| 33 | 
            +
                assert_equal FooDataMapper, subject.resolve_data_mapper(query)
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              it 'resolves data mapper class from object' do
         | 
| 37 | 
            +
                assert_equal FooDataMapper, subject.resolve_data_mapper(foo)
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              it 'resolves data mapper class from namespaced object' do
         | 
| 41 | 
            +
                assert_equal BarDataMapper, subject.resolve_data_mapper(bar)
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              it 'includes Resolver module' do
         | 
| 45 | 
            +
                assert subject.respond_to? :extract_entity_class_name_from_ref
         | 
| 46 | 
            +
                assert subject.respond_to? :extract_entity_class_name_from_query
         | 
| 47 | 
            +
                assert subject.respond_to? :extract_entity_class_name_from_object
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            end
         | 
| @@ -0,0 +1,51 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Resolver::EntityMapper do
         | 
| 4 | 
            +
              subject { Resolver::EntityMapper.new(store, mapping) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # entites
         | 
| 7 | 
            +
              let(:foo) { faked_class('Foo').new }
         | 
| 8 | 
            +
              let(:bar) { faked_class('Nested::Bar').new }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              # entity mapper
         | 
| 11 | 
            +
              FooEntityMapper = Class.new(Store::EntityMapper)
         | 
| 12 | 
            +
              BarEntityMapper = Class.new(Store::EntityMapper)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              let(:mapping) do
         | 
| 15 | 
            +
                {
         | 
| 16 | 
            +
                'Foo' => FooEntityMapper,
         | 
| 17 | 
            +
                'Bar' => BarEntityMapper,
         | 
| 18 | 
            +
                }
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              let(:store) { Object.new }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              it 'validates the subject' do
         | 
| 24 | 
            +
                assert_instance_of Resolver::EntityMapper, subject
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              it 'resolves entity mapper instance from Store::Ref' do
         | 
| 28 | 
            +
                ref = Store::Ref.new('Foo', 42)
         | 
| 29 | 
            +
                assert_instance_of FooEntityMapper, subject.resolve_entity_mapper(ref)
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              it 'resolves entity mapper instance from Store::Query' do
         | 
| 33 | 
            +
                query = Store::Query.new('Foo', :query_name, :some, :args)
         | 
| 34 | 
            +
                assert_instance_of FooEntityMapper, subject.resolve_entity_mapper(query)
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              it 'resolves entity mapper instance from object' do
         | 
| 38 | 
            +
                assert_instance_of FooEntityMapper, subject.resolve_entity_mapper(foo)
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              it 'resolves entity mapper instance from namespaced object' do
         | 
| 42 | 
            +
                assert_instance_of BarEntityMapper, subject.resolve_entity_mapper(bar)
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              it 'includes Resolver module' do
         | 
| 46 | 
            +
                assert subject.respond_to? :extract_entity_class_name_from_ref
         | 
| 47 | 
            +
                assert subject.respond_to? :extract_entity_class_name_from_query
         | 
| 48 | 
            +
                assert subject.respond_to? :extract_entity_class_name_from_object
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Resolver do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              let(:subject_class) { Class.new { include Resolver } }
         | 
| 6 | 
            +
              subject { subject_class.new }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              # entites
         | 
| 9 | 
            +
              let(:foo) { faked_class('Foo').new }
         | 
| 10 | 
            +
              let(:bar) { faked_class('Nested::Bar').new }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              it 'extracts entity class name from Store::Ref' do
         | 
| 13 | 
            +
                ref = Store::Ref.new('Foo', 42)
         | 
| 14 | 
            +
                assert_equal 'Foo', subject.extract_entity_class_name_from_ref(ref)
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              it 'extracts entity class name from Store::Query' do
         | 
| 18 | 
            +
                query = Store::Query.new('Foo', :query_name, :some, :args)
         | 
| 19 | 
            +
                assert_equal 'Foo', subject.extract_entity_class_name_from_query(query)
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              it 'extracts entity class name from Object' do
         | 
| 23 | 
            +
                assert_equal 'Foo', subject.extract_entity_class_name_from_object(foo)
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              it 'extracts entity class from Nested::Object' do
         | 
| 27 | 
            +
                assert_equal 'Bar', subject.extract_entity_class_name_from_object(bar)
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            end
         | 
    
        data/spec/store_repo_spec.rb
    CHANGED
    
    | @@ -15,19 +15,48 @@ describe 'Store::Repo' do | |
| 15 15 |  | 
| 16 16 | 
             
              it 'delegeates save to @store and swallows result' do
         | 
| 17 17 | 
             
                store.expect :save, :result, [:arg]
         | 
| 18 | 
            -
             | 
| 18 | 
            +
             | 
| 19 | 
            +
                result = repo.save(:arg)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                assert store.verify
         | 
| 22 | 
            +
                assert_equal true, result
         | 
| 19 23 | 
             
              end
         | 
| 20 24 |  | 
| 21 25 | 
             
              it 'delegates remove to @store and swallows result' do
         | 
| 22 26 | 
             
                store.expect :remove, :result, [:arg]
         | 
| 23 | 
            -
                 | 
| 27 | 
            +
                
         | 
| 28 | 
            +
                result =  repo.remove(:arg)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                assert store.verify
         | 
| 31 | 
            +
                assert_equal true, result
         | 
| 24 32 | 
             
              end
         | 
| 25 33 |  | 
| 26 | 
            -
              it 'delegates build to @store and returns result' do
         | 
| 34 | 
            +
              it 'delegates build to @store and returns result without args' do
         | 
| 27 35 | 
             
                store.expect :build, :result, [:arg]
         | 
| 28 | 
            -
                assert_equal :result, repo.build(:arg)
         | 
| 29 36 |  | 
| 37 | 
            +
                result = repo.build(:arg)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                assert store.verify
         | 
| 40 | 
            +
                assert_equal :result, result
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              it 'delegates build to @store and returns result with args' do
         | 
| 30 44 | 
             
                store.expect :build, :result, [:arg, :a, :b]
         | 
| 31 | 
            -
             | 
| 45 | 
            +
             | 
| 46 | 
            +
                result = repo.build(:arg, :a, :b)
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                assert store.verify
         | 
| 49 | 
            +
                assert_equal :result, result
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              it 'delegates save_and_load to @store' do
         | 
| 53 | 
            +
                store.expect :save, :refs, [:arg]
         | 
| 54 | 
            +
                store.expect :load, :entities, [:refs]
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                result = repo.save_and_load(:arg)
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                assert store.verify
         | 
| 59 | 
            +
                assert_equal :entities, result 
         | 
| 32 60 | 
             
              end
         | 
| 61 | 
            +
             | 
| 33 62 | 
             
            end
         | 
    
        data/store.gemspec
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: store
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.6
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Jakob Holderbaum
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2013-07- | 
| 11 | 
            +
            date: 2013-07-31 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -52,6 +52,20 @@ dependencies: | |
| 52 52 | 
             
                - - '>='
         | 
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 54 | 
             
                    version: '0'
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: minitest
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - ~>
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '5.0'
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - ~>
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: '5.0'
         | 
| 55 69 | 
             
            description: 
         | 
| 56 70 | 
             
            email:
         | 
| 57 71 | 
             
            - jakob@featurefabrik.de
         | 
| @@ -60,6 +74,7 @@ extensions: [] | |
| 60 74 | 
             
            extra_rdoc_files: []
         | 
| 61 75 | 
             
            files:
         | 
| 62 76 | 
             
            - .gitignore
         | 
| 77 | 
            +
            - .travis.yml
         | 
| 63 78 | 
             
            - Gemfile
         | 
| 64 79 | 
             
            - README.md
         | 
| 65 80 | 
             
            - Rakefile
         | 
| @@ -67,11 +82,19 @@ files: | |
| 67 82 | 
             
            - lib/store.rb
         | 
| 68 83 | 
             
            - lib/store/data_mapper.rb
         | 
| 69 84 | 
             
            - lib/store/entity_mapper.rb
         | 
| 85 | 
            +
            - lib/store/entity_references.rb
         | 
| 70 86 | 
             
            - lib/store/query.rb
         | 
| 71 87 | 
             
            - lib/store/ref.rb
         | 
| 72 88 | 
             
            - lib/store/repo.rb
         | 
| 89 | 
            +
            - lib/store/resolver.rb
         | 
| 90 | 
            +
            - lib/store/resolver/data_mapper.rb
         | 
| 91 | 
            +
            - lib/store/resolver/entity_mapper.rb
         | 
| 73 92 | 
             
            - lib/store/version.rb
         | 
| 93 | 
            +
            - spec/entity_references_spec.rb
         | 
| 74 94 | 
             
            - spec/helper.rb
         | 
| 95 | 
            +
            - spec/resolver/data_mapper_spec.rb
         | 
| 96 | 
            +
            - spec/resolver/entity_mapper_spec.rb
         | 
| 97 | 
            +
            - spec/resolver/resolver_spec.rb
         | 
| 75 98 | 
             
            - spec/store_query_spec.rb
         | 
| 76 99 | 
             
            - spec/store_ref_spec.rb
         | 
| 77 100 | 
             
            - spec/store_repo_spec.rb
         | 
| @@ -102,7 +125,11 @@ signing_key: | |
| 102 125 | 
             
            specification_version: 4
         | 
| 103 126 | 
             
            summary: Repository Pattern and Data-Mapper Pattern
         | 
| 104 127 | 
             
            test_files:
         | 
| 128 | 
            +
            - spec/entity_references_spec.rb
         | 
| 105 129 | 
             
            - spec/helper.rb
         | 
| 130 | 
            +
            - spec/resolver/data_mapper_spec.rb
         | 
| 131 | 
            +
            - spec/resolver/entity_mapper_spec.rb
         | 
| 132 | 
            +
            - spec/resolver/resolver_spec.rb
         | 
| 106 133 | 
             
            - spec/store_query_spec.rb
         | 
| 107 134 | 
             
            - spec/store_ref_spec.rb
         | 
| 108 135 | 
             
            - spec/store_repo_spec.rb
         |