ocean-dynamo 1.2.4 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.rdoc +18 -27
- data/lib/ocean-dynamo/associations/association.rb +6 -4
- data/lib/ocean-dynamo/associations/associations.rb +10 -0
- data/lib/ocean-dynamo/associations/belongs_to.rb +1 -1
- data/lib/ocean-dynamo/associations/collection_association.rb +7 -5
- data/lib/ocean-dynamo/associations/collection_proxy.rb +2 -3
- data/lib/ocean-dynamo/associations/has_many.rb +10 -4
- data/lib/ocean-dynamo/associations/relation.rb +0 -1
- data/lib/ocean-dynamo/attributes.rb +1 -0
- data/lib/ocean-dynamo/version.rb +1 -1
- metadata +18 -18
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0e5d649565fd30bee32f1b8d80c7f6117009229e
         | 
| 4 | 
            +
              data.tar.gz: e281cb72d49607d53e9ddd7053462f50c29b0604
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: cf608c59e414e273d9e13cf30070e3e2c3ba6ef79e343900b66d7fc1dbc08dd903332fe9297310fbebb5dbc1c9050957130178fe864dafc316ced76e397c629c
         | 
| 7 | 
            +
              data.tar.gz: 708e7170927244786d84e20bc2b7ffc99206263d210f3fe4e73ee4306be3bb659b1383b01cb9631b91ef85c4d378a03947a28b3a4cb60f3f5dbbf896c99c34cf
         | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -40,16 +40,16 @@ with FactoryGirl. | |
| 40 40 |  | 
| 41 41 | 
             
            === Future milestones
         | 
| 42 42 |  | 
| 43 | 
            -
            *  | 
| 43 | 
            +
            * Direct support for the DynamoDB JSON attribute types for arrays and hashes
         | 
| 44 | 
            +
            * Collection proxies, to implement ActiveRecord-style method chaining, e.g.: 
         | 
| 44 45 | 
             
              <code>blog_entry.comments.build(body: "Cool!").save!</code>
         | 
| 45 46 | 
             
            * The +has_and_belongs_to_many+ assocation. 
         | 
| 46 | 
            -
            * A generator to install the <tt>config/aws.yml</tt> file.
         | 
| 47 47 |  | 
| 48 48 |  | 
| 49 49 | 
             
            === Current use
         | 
| 50 50 |  | 
| 51 51 | 
             
            OceanDynamo is used as a central component in Ocean, a Rails framework and development 
         | 
| 52 | 
            -
            pipeline for creating  | 
| 52 | 
            +
            pipeline for creating massively scalable HATEOAS microservice SOAs in the cloud.
         | 
| 53 53 | 
             
            * http://wiki.oceanframework.net
         | 
| 54 54 |  | 
| 55 55 | 
             
            Ocean uses OceanDynamo to implement highly scalable job queues and authentication. 
         | 
| @@ -99,6 +99,8 @@ The following example shows the basic syntax for declaring a DynamoDB-based sche | |
| 99 99 | 
             
                  attribute :succeeded,            :boolean,    default: false
         | 
| 100 100 | 
             
                  attribute :failed,               :boolean,    default: false
         | 
| 101 101 | 
             
                  attribute :poison,               :boolean,    default: false
         | 
| 102 | 
            +
                  
         | 
| 103 | 
            +
                  global_secondary_index :token, projection: :all
         | 
| 102 104 | 
             
                end
         | 
| 103 105 |  | 
| 104 106 | 
             
              end
         | 
| @@ -210,13 +212,9 @@ which means that secondary indices won't be necessary for the vast majority of | |
| 210 212 | 
             
            DynamoDB tables. This ultimately means reduced operational costs, as well as
         | 
| 211 213 | 
             
            reduced complexity.
         | 
| 212 214 |  | 
| 213 | 
            -
            Nevertheless, as we now have switched to v2 of the DynamoDB API, we will be adding
         | 
| 214 | 
            -
            the possibility to define both local and secondary indices for Tables. 
         | 
| 215 215 |  | 
| 216 216 | 
             
            == Secondary Indices
         | 
| 217 217 |  | 
| 218 | 
            -
            We now have support for secondary indices.
         | 
| 219 | 
            -
             | 
| 220 218 | 
             
            === Local Secondary Indices
         | 
| 221 219 |  | 
| 222 220 | 
             
            Up to five attributes can be declared as local secondary indices, in the following manner:
         | 
| @@ -242,9 +240,9 @@ combination of keys. Secondary indices don't require the range key to be unique | |
| 242 240 | 
             
            the same hash key. This means that secondary index searches always will return a
         | 
| 243 241 | 
             
            collection.
         | 
| 244 242 |  | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 243 | 
            +
            Local secondary indices are queried through +find_local_each+ and +find_local+. 
         | 
| 244 | 
            +
            They take the same arguments; the former yields to a block for each item, 
         | 
| 245 | 
            +
            the other returns all items in an array.
         | 
| 248 246 |  | 
| 249 247 | 
             
            The following finds all Authentications where +:username+ is "joe" and +:token+ is "quux":
         | 
| 250 248 |  | 
| @@ -259,9 +257,6 @@ The same thing but with the only the item with the highest token value: | |
| 259 257 | 
             
             Authentication.find_local(:username, "joe", :token, ">=", "0",
         | 
| 260 258 | 
             
                                       scan_index_forward: false, limit: 1)
         | 
| 261 259 |  | 
| 262 | 
            -
            For more information, see the documentation for
         | 
| 263 | 
            -
            +find_local_each+ and +find_local+.
         | 
| 264 | 
            -
             | 
| 265 260 |  | 
| 266 261 | 
             
            === Global Secondary Indices
         | 
| 267 262 |  | 
| @@ -282,37 +277,34 @@ block: | |
| 282 277 | 
             
                end
         | 
| 283 278 | 
             
              end
         | 
| 284 279 |  | 
| 285 | 
            -
            Each +global_secondary_index+ clause  | 
| 280 | 
            +
            Each +global_secondary_index+ clause (there can be a maximum of 5 per table) takes 
         | 
| 281 | 
            +
            the following arguments:
         | 
| 286 282 | 
             
            * +hash_value+ (required), 
         | 
| 287 283 | 
             
            * +range_value+ (optional), 
         | 
| 288 | 
            -
            * +:projection+ (default  | 
| 284 | 
            +
            * +:projection+ (default +:keys_only+, +:all+ for all attributes)
         | 
| 289 285 | 
             
            * +:read_capacity_units+ (defaults to the table's read capacity, normally 10)
         | 
| 290 286 | 
             
            * +:write_capacity_units+ (default to the table's write capacity, normally 5)
         | 
| 291 287 |  | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
             | 
| 288 | 
            +
            Global secondary indices are queried through +find_global_each+ and +find_global+. 
         | 
| 289 | 
            +
            They take the same arguments; the former yields to a block for each item, 
         | 
| 290 | 
            +
            the other returns all items in an array.
         | 
| 295 291 |  | 
| 296 | 
            -
            The following finds all Authentications whose +:token+ is "quux"
         | 
| 292 | 
            +
            The following finds all Authentications whose +:token+ is +"quux"+:
         | 
| 297 293 |  | 
| 298 294 | 
             
             Authentication.find_global(:token, "quux")
         | 
| 299 295 |  | 
| 300 | 
            -
            This retrieves all Authentications belonging to the user with the ID "dfstw-ruyhdf-ewijf" | 
| 296 | 
            +
            This retrieves all Authentications belonging to the user with the ID +"dfstw-ruyhdf-ewijf"+, 
         | 
| 301 297 | 
             
            sorted in ascending order of the +:expires_at+ attribute:
         | 
| 302 298 |  | 
| 303 299 | 
             
             Authentication.find_global(:api_user_id, "dfstw-ruyhdf-ewijf", 
         | 
| 304 300 | 
             
                                        :expires_at, ">=", 0)
         | 
| 305 301 |  | 
| 306 | 
            -
            To get the highest +:expires_at+ record | 
| 302 | 
            +
            To get the highest +:expires_at+ record:
         | 
| 307 303 |  | 
| 308 304 | 
             
             Authentication.find_global(:api_user_id, "dfstw-ruyhdf-ewijf", 
         | 
| 309 305 | 
             
                                        :expires_at, ">=", 0,
         | 
| 310 306 | 
             
                                        scan_index_forward: false, limit: 1)
         | 
| 311 307 |  | 
| 312 | 
            -
            The combination of hash and range key must have been explicitly declared using
         | 
| 313 | 
            -
            +global_secondary_index+. For more information, see the documentation for
         | 
| 314 | 
            -
            +find_global_each+ and +find_global+.
         | 
| 315 | 
            -
             | 
| 316 308 |  | 
| 317 309 | 
             
            == Installation
         | 
| 318 310 |  | 
| @@ -335,8 +327,7 @@ to both the following locations in your project: | |
| 335 327 | 
             
             config/aws.yml.example
         | 
| 336 328 | 
             
             config/aws.yml
         | 
| 337 329 |  | 
| 338 | 
            -
            Enter your AWS credentials in the latter file. | 
| 339 | 
            -
            will be a generator to copy these files for you, but for now you need to do it manually. 
         | 
| 330 | 
            +
            Enter your AWS credentials in the latter file.
         | 
| 340 331 |  | 
| 341 332 |  | 
| 342 333 | 
             
            == Running the specs
         | 
| @@ -1,13 +1,15 @@ | |
| 1 1 | 
             
            module OceanDynamo
         | 
| 2 2 | 
             
              module Associations
         | 
| 3 | 
            +
             | 
| 3 4 | 
             
                #
         | 
| 4 5 | 
             
                # This is the root class of all Associations.
         | 
| 5 6 | 
             
                # The class structure is exactly like in ActiveRecord:
         | 
| 6 7 | 
             
                #
         | 
| 7 | 
            -
                #    | 
| 8 | 
            -
                #      | 
| 9 | 
            -
                #        | 
| 10 | 
            -
                # | 
| 8 | 
            +
                #   Associations
         | 
| 9 | 
            +
                #     Association
         | 
| 10 | 
            +
                #       CollectionAssociation
         | 
| 11 | 
            +
                #         HasAndBelongsToManyAssociation
         | 
| 12 | 
            +
                #         HasManyAssociation
         | 
| 11 13 | 
             
                #
         | 
| 12 14 | 
             
                # It should be noted, however, that the ActiveRecord documentation  
         | 
| 13 15 | 
             
                # is misleading: belongs_to and has_one no longer are implemented using
         | 
| @@ -151,7 +151,7 @@ module OceanDynamo | |
| 151 151 | 
             
                  #
         | 
| 152 152 | 
             
                  def assert_range_key_not_specified!  # :nodoc:
         | 
| 153 153 | 
             
                    raise RangeKeyMustNotBeSpecified, 
         | 
| 154 | 
            -
                          "Tables with belongs_to relations may not specify  | 
| 154 | 
            +
                          "Tables with belongs_to relations may not specify a range key" if table_range_key
         | 
| 155 155 | 
             
                  end
         | 
| 156 156 |  | 
| 157 157 |  | 
| @@ -1,15 +1,17 @@ | |
| 1 1 | 
             
            module OceanDynamo 
         | 
| 2 2 | 
             
              module Associations 
         | 
| 3 | 
            +
                
         | 
| 3 4 | 
             
                #
         | 
| 4 5 | 
             
                # CollectionAssociation is an abstract class that provides common stuff to
         | 
| 5 6 | 
             
                # ease the implementation of association proxies that represent
         | 
| 6 7 | 
             
                # collections. See the class hierarchy in AssociationProxy.
         | 
| 7 8 | 
             
                #
         | 
| 8 | 
            -
                #   | 
| 9 | 
            -
                #     | 
| 10 | 
            -
                #       | 
| 11 | 
            -
                # | 
| 12 | 
            -
                #         | 
| 9 | 
            +
                #  Associations
         | 
| 10 | 
            +
                #    Association
         | 
| 11 | 
            +
                #      CollectionAssociation:
         | 
| 12 | 
            +
                #        HasAndBelongsToManyAssociation => has_and_belongs_to_many
         | 
| 13 | 
            +
                #        HasManyAssociation => has_many
         | 
| 14 | 
            +
                #          HasManyThroughAssociation + ThroughAssociation => has_many :through
         | 
| 13 15 | 
             
                #
         | 
| 14 16 | 
             
                # CollectionAssociation class provides common methods to the collections
         | 
| 15 17 | 
             
                # defined by +has_and_belongs_to_many+, +has_many+ or +has_many+ with
         | 
| @@ -19,9 +19,8 @@ module OceanDynamo | |
| 19 19 | 
             
                # <tt>@owner</tt>, the collection of its posts as <tt>@target</tt>, and
         | 
| 20 20 | 
             
                # the <tt>@reflection</tt> object represents a <tt>:has_many</tt> macro.
         | 
| 21 21 | 
             
                #
         | 
| 22 | 
            -
                # This class delegates unknown methods to <tt>@target</tt>  | 
| 23 | 
            -
                #  | 
| 24 | 
            -
                # but through explicit proxy methods for each separate operation.
         | 
| 22 | 
            +
                # This class delegates unknown methods to <tt>@target</tt> through explicit 
         | 
| 23 | 
            +
                # proxy methods for each separate operation.
         | 
| 25 24 | 
             
                #
         | 
| 26 25 | 
             
                # The <tt>@target</tt> object is not \loaded until needed. As it turns out,
         | 
| 27 26 | 
             
                # the key to this lazy loading scheme is <tt>to_ary</tt>.
         | 
| @@ -19,11 +19,13 @@ module OceanDynamo | |
| 19 19 | 
             
                  # Defines a +has_many+ relation to a +belongs_to+ class.
         | 
| 20 20 | 
             
                  #
         | 
| 21 21 | 
             
                  # The +dependent:+ keyword arg may be +:destroy+, +:delete+ or +:nullify+
         | 
| 22 | 
            -
                  # and have the same semantics as in ActiveRecord. | 
| 23 | 
            -
                  # the hash key is set to the string "NULL" rather than binary NULL, as
         | 
| 24 | 
            -
                  # DynamoDB doesn't permit storing empty fields.
         | 
| 22 | 
            +
                  # and have the same semantics as in ActiveRecord.
         | 
| 25 23 | 
             
                  #
         | 
| 26 | 
            -
                   | 
| 24 | 
            +
                  # Using +:nullify+ is a Bad Idea on DynamoDB, as it has to first read, 
         | 
| 25 | 
            +
                  # then delete, and finally recreate each record. You should redesign your 
         | 
| 26 | 
            +
                  # application to user either +:delete+ (the default) or +:destroy+ instead. 
         | 
| 27 | 
            +
                  #
         | 
| 28 | 
            +
                  def has_many(children, dependent: :delete)             # :children
         | 
| 27 29 | 
             
                    children_attr = children.to_s.underscore             # "children"
         | 
| 28 30 | 
             
                    class_name = children_attr.classify                  # "Child"
         | 
| 29 31 | 
             
                    define_class_if_not_defined(class_name)
         | 
| @@ -176,6 +178,10 @@ module OceanDynamo | |
| 176 178 | 
             
                # into orphans. Note that we're not setting the key to NULL as this isn't possible
         | 
| 177 179 | 
             
                # in DynamoDB. Instead, we're using the literal string "NULL".
         | 
| 178 180 | 
             
                #
         | 
| 181 | 
            +
                # Using +:nullify+ is a Bad Idea on DynamoDB, as it has to first read, then delete, and
         | 
| 182 | 
            +
                # then recreate each record. You should redesign your application to user either
         | 
| 183 | 
            +
                # +:delete? (the default) or +:destroy+ instead. 
         | 
| 184 | 
            +
                #
         | 
| 179 185 | 
             
                def nullify_children(child_class)
         | 
| 180 186 | 
             
                  return if new_record?
         | 
| 181 187 | 
             
                  opts = condition_options(child_class)
         | 
    
        data/lib/ocean-dynamo/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ocean-dynamo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Peter Bengtson
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2015-09 | 
| 11 | 
            +
            date: 2015-12-09 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: aws-sdk
         | 
| @@ -28,30 +28,30 @@ dependencies: | |
| 28 28 | 
             
              name: activemodel
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 30 | 
             
                requirements:
         | 
| 31 | 
            -
                - - " | 
| 31 | 
            +
                - - "~>"
         | 
| 32 32 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            -
                    version: ' | 
| 33 | 
            +
                    version: '4'
         | 
| 34 34 | 
             
              type: :runtime
         | 
| 35 35 | 
             
              prerelease: false
         | 
| 36 36 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 37 | 
             
                requirements:
         | 
| 38 | 
            -
                - - " | 
| 38 | 
            +
                - - "~>"
         | 
| 39 39 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            -
                    version: ' | 
| 40 | 
            +
                    version: '4'
         | 
| 41 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 42 42 | 
             
              name: activesupport
         | 
| 43 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 44 | 
             
                requirements:
         | 
| 45 | 
            -
                - - " | 
| 45 | 
            +
                - - "~>"
         | 
| 46 46 | 
             
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            -
                    version: ' | 
| 47 | 
            +
                    version: '4'
         | 
| 48 48 | 
             
              type: :runtime
         | 
| 49 49 | 
             
              prerelease: false
         | 
| 50 50 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 51 | 
             
                requirements:
         | 
| 52 | 
            -
                - - " | 
| 52 | 
            +
                - - "~>"
         | 
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            -
                    version: ' | 
| 54 | 
            +
                    version: '4'
         | 
| 55 55 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 56 56 | 
             
              name: rails
         | 
| 57 57 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -114,14 +114,14 @@ dependencies: | |
| 114 114 | 
             
                requirements:
         | 
| 115 115 | 
             
                - - "~>"
         | 
| 116 116 | 
             
                  - !ruby/object:Gem::Version
         | 
| 117 | 
            -
                    version: '4 | 
| 117 | 
            +
                    version: '4'
         | 
| 118 118 | 
             
              type: :development
         | 
| 119 119 | 
             
              prerelease: false
         | 
| 120 120 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 121 121 | 
             
                requirements:
         | 
| 122 122 | 
             
                - - "~>"
         | 
| 123 123 | 
             
                  - !ruby/object:Gem::Version
         | 
| 124 | 
            -
                    version: '4 | 
| 124 | 
            +
                    version: '4'
         | 
| 125 125 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 126 126 | 
             
              name: ocean-rails
         | 
| 127 127 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -140,18 +140,18 @@ description: "== OceanDynamo\n\nAs one important use case for OceanDynamo is to | |
| 140 140 | 
             
              the conversion of SQL\ndatabases to no-SQL DynamoDB databases, it is important that
         | 
| 141 141 | 
             
              the syntax and semantics\nof OceanDynamo are as close as possible to those of ActiveRecord.
         | 
| 142 142 | 
             
              This includes\ncallbacks, exceptions and method chaining semantics. OceanDynamo
         | 
| 143 | 
            -
              follows this pattern \nclosely and is of course based on ActiveModel.\n\nThe attribute
         | 
| 143 | 
            +
              follows this pattern \nclosely and is of course based on ActiveModel.\n\n\nThe attribute
         | 
| 144 144 | 
             
              and persistence layer of OceanDynamo is modeled on that of ActiveRecord:\nthere's
         | 
| 145 145 | 
             
              +save+, +save!+, +create+, +update+, +update!+, +update_attributes+, +find_each+,\n+destroy_all+,
         | 
| 146 146 | 
             
              +delete_all+, +read_attribute+, +write_attribute+ and all the other \nmethods you're
         | 
| 147 147 | 
             
              used to. The design goal is always to implement as much of the ActiveRecord\ninterface
         | 
| 148 148 | 
             
              as possible, without compromising scalability. This makes the task of switching
         | 
| 149 | 
            -
              \nfrom SQL to no-SQL much easier.\n\nOceanDynamo uses only primary indices to | 
| 150 | 
            -
              related table items and collections, \nwhich means it will scale without | 
| 151 | 
            -
              is fully usable as an ActiveModel and can be used by Rails\ncontrollers. | 
| 152 | 
            -
              to its structural similarity to ActiveRecord, OceanDynamo works \nwith FactoryGirl.\n\nSee
         | 
| 149 | 
            +
              \nfrom SQL to no-SQL much easier.\n\n\nOceanDynamo uses only primary indices to
         | 
| 150 | 
            +
              retrieve related table items and collections, \nwhich means it will scale without
         | 
| 151 | 
            +
              limits.\n\n\nOceanDynamo is fully usable as an ActiveModel and can be used by Rails\ncontrollers.
         | 
| 152 | 
            +
              Thanks to its structural similarity to ActiveRecord, OceanDynamo works \nwith FactoryGirl.\n\n\nSee
         | 
| 153 153 | 
             
              also Ocean, a Rails framework for creating highly scalable SOAs in the cloud, in
         | 
| 154 | 
            -
              which\nocean-dynamo is used as a central component: http://wiki.oceanframework.net"
         | 
| 154 | 
            +
              which\nocean-dynamo is used as a central component: http://wiki.oceanframework.net\n"
         | 
| 155 155 | 
             
            email:
         | 
| 156 156 | 
             
            - peter@peterbengtson.com
         | 
| 157 157 | 
             
            executables: []
         |