ocean-dynamo 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.rdoc +51 -24
- data/lib/ocean-dynamo/associations/has_many.rb +3 -2
- data/lib/ocean-dynamo/attributes.rb +1 -0
- data/lib/ocean-dynamo/class_variables.rb +3 -0
- data/lib/ocean-dynamo/queries.rb +12 -5
- data/lib/ocean-dynamo/schema.rb +20 -0
- data/lib/ocean-dynamo/tables.rb +40 -18
- data/lib/ocean-dynamo/version.rb +1 -1
- metadata +15 -15
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0a277c429cc29e02d55452ba4bca425a2b330cd4
         | 
| 4 | 
            +
              data.tar.gz: d21e7ae3f0dcd90e5cf993bc43f5ccb4e6148e26
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: eac3188b5e301a633ee829651adae2c9f228f824e35d3ffb798abb3ff6e382ca76b9ed0e985957aebdd83207875608fc2e31843cbe25cf8547988a3a44dc4885
         | 
| 7 | 
            +
              data.tar.gz: 42b49827d66a23bb4a65ec9ed55c24ad25a34fdebca03b61648b6615aed753c5339e737eca41e6f58ab3057d381defc3887946df00cfb632350dedfbcf853c98
         | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -33,7 +33,7 @@ with FactoryGirl. | |
| 33 33 |  | 
| 34 34 | 
             
            === Current State
         | 
| 35 35 |  | 
| 36 | 
            -
            *  | 
| 36 | 
            +
            * Secondary indices are now supported! See below for more information.
         | 
| 37 37 | 
             
            * Version 2 of the AWS Ruby SDK is now used. This required an internal reorganisation, 
         | 
| 38 38 | 
             
              but it also gives us access to local and global secondary indices.
         | 
| 39 39 | 
             
            * Work begun on association proxies, etc.
         | 
| @@ -76,9 +76,9 @@ will not be considered unless all tests pass and coverage is equally high or hig | |
| 76 76 | 
             
            All contributed code must therefore also be exhaustively tested.
         | 
| 77 77 |  | 
| 78 78 |  | 
| 79 | 
            -
             | 
| 79 | 
            +
            == Examples
         | 
| 80 80 |  | 
| 81 | 
            -
             | 
| 81 | 
            +
            === Basic syntax
         | 
| 82 82 |  | 
| 83 83 | 
             
            The following example shows the basic syntax for declaring a DynamoDB-based schema. 
         | 
| 84 84 |  | 
| @@ -104,7 +104,7 @@ The following example shows the basic syntax for declaring a DynamoDB-based sche | |
| 104 104 |  | 
| 105 105 | 
             
              end
         | 
| 106 106 |  | 
| 107 | 
            -
             | 
| 107 | 
            +
            === Attributes
         | 
| 108 108 |  | 
| 109 109 | 
             
            Each attribute has a name, a type (+:string+, +:integer+, +:float+, +:datetime+, +:boolean+, 
         | 
| 110 110 | 
             
            or +:serialized+) where +:string+ is the default. Each attribute also optionally has a default 
         | 
| @@ -117,7 +117,7 @@ Sets are represented as arrays, may not contain duplicates and may not be empty. | |
| 117 117 | 
             
            All attributes except the +:string+ type can take the value +nil+. Storing +nil+ for a string
         | 
| 118 118 | 
             
            value will return the empty string, <tt>""</tt>.
         | 
| 119 119 |  | 
| 120 | 
            -
             | 
| 120 | 
            +
            === Schema args and options
         | 
| 121 121 |  | 
| 122 122 | 
             
            +dynamo_schema+ takes args and many options. Here's the full syntax:
         | 
| 123 123 |  | 
| @@ -139,9 +139,9 @@ value will return the empty string, <tt>""</tt>. | |
| 139 139 | 
             
               ...
         | 
| 140 140 | 
             
             end
         | 
| 141 141 |  | 
| 142 | 
            -
             | 
| 142 | 
            +
            == +has_many+ and +belongs_to+
         | 
| 143 143 |  | 
| 144 | 
            -
             | 
| 144 | 
            +
            === Example
         | 
| 145 145 |  | 
| 146 146 | 
             
            The following example shows how to set up +has_many+ / +belongs_to+ relations:
         | 
| 147 147 |  | 
| @@ -175,7 +175,7 @@ is required as the Topic class itself has a +belongs_to+ relation and thus has | |
| 175 175 | 
             
            a composite key. This must be declared in the child class as it needs to know
         | 
| 176 176 | 
             
            how to retrieve its parent.
         | 
| 177 177 |  | 
| 178 | 
            -
             | 
| 178 | 
            +
            === Restrictions
         | 
| 179 179 |  | 
| 180 180 | 
             
            Restrictions for +belongs_to+ tables: 
         | 
| 181 181 | 
             
            * The hash key must be specified and must not be +:id+. 
         | 
| @@ -189,7 +189,7 @@ Restrictions for +has_many+ tables: | |
| 189 189 | 
             
            These restrictions allow OceanDynamo to implement the +has_many+ / +belongs_to+ 
         | 
| 190 190 | 
             
            relation in a very efficient and massively scalable way. 
         | 
| 191 191 |  | 
| 192 | 
            -
             | 
| 192 | 
            +
            === Implementation
         | 
| 193 193 |  | 
| 194 194 | 
             
            +belongs_to+ claims the range key and uses it to store its own id, which normally
         | 
| 195 195 | 
             
            would be stored in the hash key attribute. Instead, the hash key attribute holds the
         | 
| @@ -214,16 +214,24 @@ reduced complexity. | |
| 214 214 | 
             
            Nevertheless, as we now have switched to v2 of the DynamoDB API, we will be adding
         | 
| 215 215 | 
             
            the possibility to define both local and secondary indices for Tables. 
         | 
| 216 216 |  | 
| 217 | 
            +
            == Secondary Indices
         | 
| 218 | 
            +
             | 
| 219 | 
            +
            We now have basic support for secondary indices. 
         | 
| 220 | 
            +
             | 
| 221 | 
            +
            We will add high-level support for specifying that a secondary index is to be used 
         | 
| 222 | 
            +
            in +in_batches+ and +find_each+ etc, but for now you will have to specify that a
         | 
| 223 | 
            +
            secondary index is to be used explicitly in the options passed to +in_batches+, 
         | 
| 224 | 
            +
            +query+, and +scan+. 
         | 
| 225 | 
            +
            * +query+: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Table.html#query-instance_method
         | 
| 226 | 
            +
            * +scan+: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Table.html#scan-instance_method
         | 
| 227 | 
            +
            * +in_batches+, +find_each+: lib/ocean-dynamo/queries.rb
         | 
| 217 228 |  | 
| 218 229 | 
             
            === Local Secondary Indices
         | 
| 219 230 |  | 
| 220 | 
            -
             | 
| 221 | 
            -
            be declared as local secondary indices, in the following manner:
         | 
| 231 | 
            +
            Up to five attributes can be declared as local secondary indices, in the following manner:
         | 
| 222 232 |  | 
| 223 233 | 
             
              class Authentication < OceanDynamo::Table
         | 
| 224 | 
            -
                dynamo_schema(:username, :expires_at | 
| 225 | 
            -
                              timestamps: nil, locking: false
         | 
| 226 | 
            -
                              table_name_suffix: Api.basename_suffix) do
         | 
| 234 | 
            +
                dynamo_schema(:username, :expires_at) do
         | 
| 227 235 | 
             
                  attribute :token,       :string,   local_secondary_index: true
         | 
| 228 236 | 
             
                  attribute :max_age,     :integer
         | 
| 229 237 | 
             
                  attribute :created_at,  :datetime
         | 
| @@ -232,23 +240,42 @@ be declared as local secondary indices, in the following manner: | |
| 232 240 | 
             
                end
         | 
| 233 241 | 
             
              end
         | 
| 234 242 |  | 
| 235 | 
            -
            The items of the above table can be accessed by using the hash key  | 
| 236 | 
            -
            the range key  | 
| 237 | 
            -
            to access items using the same hash key  | 
| 243 | 
            +
            The items of the above table can be accessed by using the hash key +:username+ and
         | 
| 244 | 
            +
            the range key +:expires_at+. The +local_secondary_index+ declaration makes it possible
         | 
| 245 | 
            +
            to access items using the same hash key +:username+ but with +:token+ as an alternate
         | 
| 238 246 | 
             
            range key. Local secondary indices all use the same hash key as the primary index,
         | 
| 239 247 | 
             
            substituting another attribute instead as the range key.
         | 
| 240 248 |  | 
| 241 | 
            -
            NB: The primary index [:username, :expires_at] requires all items to have a unique
         | 
| 249 | 
            +
            NB: The primary index <tt>[:username, :expires_at]</tt> requires all items to have a unique
         | 
| 242 250 | 
             
            combination of keys. Secondary indices don't require the range key to be unique for
         | 
| 243 251 | 
             
            the same hash key. This means that secondary index searches always will return a
         | 
| 244 252 | 
             
            collection.
         | 
| 245 253 |  | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 254 | 
            +
            === Global Secondary Indices
         | 
| 255 | 
            +
             | 
| 256 | 
            +
            Global secondary indices are declared after all attributes, but still within the +do+
         | 
| 257 | 
            +
            block:
         | 
| 258 | 
            +
             | 
| 259 | 
            +
              class Authentication < OceanDynamo::Table
         | 
| 260 | 
            +
                dynamo_schema(:username, :expires_at) do
         | 
| 261 | 
            +
                  attribute :token,       :string,   local_secondary_index: true
         | 
| 262 | 
            +
                  attribute :max_age,     :integer
         | 
| 263 | 
            +
                  attribute :created_at,  :datetime
         | 
| 264 | 
            +
                  attribute :expires_at,  :datetime
         | 
| 265 | 
            +
                  attribute :api_user_id, :string
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                  global_secondary_index :token, projection: :all
         | 
| 268 | 
            +
                  global_secondary_index :api_user_id, :expires_at, read_capacity_units: 100
         | 
| 269 | 
            +
                  global_secondary_index :expires_at, write_capacity_units: 50
         | 
| 270 | 
            +
                end
         | 
| 271 | 
            +
              end
         | 
| 272 | 
            +
             | 
| 273 | 
            +
            Each +global_secondary_index+ clause takes the following arguments:
         | 
| 274 | 
            +
            * +hash_value+ (required), 
         | 
| 275 | 
            +
            * +range_value+ (optional), 
         | 
| 276 | 
            +
            * +:projection (default :keys_only, :all for all attributes)
         | 
| 277 | 
            +
            * read_capacity_units (default 10)
         | 
| 278 | 
            +
            * write_capacity_units (default 5)
         | 
| 252 279 |  | 
| 253 280 |  | 
| 254 281 | 
             
            == Installation
         | 
| @@ -119,6 +119,7 @@ module OceanDynamo | |
| 119 119 | 
             
                  }
         | 
| 120 120 | 
             
                end
         | 
| 121 121 |  | 
| 122 | 
            +
             | 
| 122 123 | 
             
                #
         | 
| 123 124 | 
             
                # Reads all children of a has_many relation.
         | 
| 124 125 | 
             
                #
         | 
| @@ -184,9 +185,9 @@ module OceanDynamo | |
| 184 185 | 
             
                  child_hash_key = child_class.table_hash_key.to_s
         | 
| 185 186 | 
             
                  child_range_key = child_class.table_range_key && child_class.table_range_key.to_s
         | 
| 186 187 | 
             
                  child_class.in_batches :query, opts do |attrs|
         | 
| 187 | 
            -
                    # There is no way in the DynamoDB API to update a key attribute.  | 
| 188 | 
            +
                    # There is no way in the DynamoDB API to update a primary key attribute. 
         | 
| 189 | 
            +
                    # Delete the child item and recreate it with the updated key.
         | 
| 188 190 | 
             
                    child_class.delete attrs[child_hash_key], child_range_key && attrs[child_range_key]
         | 
| 189 | 
            -
                    # Create a new one with NULL for key
         | 
| 190 191 | 
             
                    attrs[child_hash_key] = "NULL"
         | 
| 191 192 | 
             
                    child_class.dynamo_table.put_item(item: attrs)
         | 
| 192 193 | 
             
                  end
         | 
| @@ -25,6 +25,7 @@ module OceanDynamo | |
| 25 25 | 
             
                    # Init
         | 
| 26 26 | 
             
                    self.fields = HashWithIndifferentAccess.new
         | 
| 27 27 | 
             
                    attribute(table_hash_key, :string, default: "")
         | 
| 28 | 
            +
                    self.global_secondary_indexes = Hash.new
         | 
| 28 29 | 
             
                    if table_range_key
         | 
| 29 30 | 
             
                      attribute(table_range_key, :string, default: "")
         | 
| 30 31 | 
             
                      self.validates(table_range_key, presence: true)
         | 
    
        data/lib/ocean-dynamo/queries.rb
    CHANGED
    
    | @@ -59,6 +59,10 @@ module OceanDynamo | |
| 59 59 | 
             
                # +message+ must be either :scan or :query.
         | 
| 60 60 | 
             
                # +options+ is the hash of options to pass to the scan or query operation.
         | 
| 61 61 | 
             
                #
         | 
| 62 | 
            +
                # TODO: Add support for
         | 
| 63 | 
            +
                #   index_name: "IndexName",
         | 
| 64 | 
            +
                #   select: "ALL_ATTRIBUTES", # ALL_ATTRIBUTES, ALL_PROJECTED_ATTRIBUTES, SPECIFIC_ATTRIBUTES, COUNT
         | 
| 65 | 
            +
                #
         | 
| 62 66 | 
             
                def in_batches(message, options, &block)
         | 
| 63 67 | 
             
                  _late_connect?
         | 
| 64 68 | 
             
                  loop do
         | 
| @@ -74,14 +78,17 @@ module OceanDynamo | |
| 74 78 |  | 
| 75 79 | 
             
                #
         | 
| 76 80 | 
             
                # Looping through a collection of records from the database (using the +all+ method, 
         | 
| 77 | 
            -
                # for example) is very inefficient since it will try to instantiate all the objects at  | 
| 78 | 
            -
                #
         | 
| 79 | 
            -
                # In that case, batch processing methods allow you to work with the records in batches, 
         | 
| 81 | 
            +
                # for example) is very inefficient since it will try to instantiate all the objects at 
         | 
| 82 | 
            +
                # once. Batch processing methods allow you to work with the records in batches, 
         | 
| 80 83 | 
             
                # thereby greatly reducing memory consumption.
         | 
| 81 84 | 
             
                #
         | 
| 82 | 
            -
                 | 
| 85 | 
            +
                # TODO: Add support for
         | 
| 86 | 
            +
                #   index_name: "IndexName",
         | 
| 87 | 
            +
                #   select: "ALL_ATTRIBUTES", # ALL_ATTRIBUTES, ALL_PROJECTED_ATTRIBUTES, SPECIFIC_ATTRIBUTES, COUNT
         | 
| 88 | 
            +
                #
         | 
| 89 | 
            +
                def find_each(consistent: false, limit: nil, batch_size: nil)
         | 
| 83 90 | 
             
                  options = { consistent_read: consistent }
         | 
| 84 | 
            -
                  batch_size = limit if limit && limit < batch_size
         | 
| 91 | 
            +
                  batch_size = limit if limit && batch_size && limit < batch_size
         | 
| 85 92 | 
             
                  options[:limit] = batch_size if batch_size   
         | 
| 86 93 | 
             
                  in_batches :scan, options do |attrs|
         | 
| 87 94 | 
             
                    if limit
         | 
    
        data/lib/ocean-dynamo/schema.rb
    CHANGED
    
    | @@ -39,6 +39,26 @@ module OceanDynamo | |
| 39 39 | 
             
                end
         | 
| 40 40 |  | 
| 41 41 |  | 
| 42 | 
            +
                def global_secondary_index(hash_key, range_key=nil, 
         | 
| 43 | 
            +
                                           projection: :keys_only,
         | 
| 44 | 
            +
                                           read_capacity_units: 10,
         | 
| 45 | 
            +
                                           write_capacity_units: 5)
         | 
| 46 | 
            +
                  if range_key
         | 
| 47 | 
            +
                    name = "#{hash_key}_#{range_key}"
         | 
| 48 | 
            +
                    keys = [hash_key.to_s, range_key.to_s]
         | 
| 49 | 
            +
                  else
         | 
| 50 | 
            +
                    name = "#{hash_key}"
         | 
| 51 | 
            +
                    keys = [hash_key.to_s]
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                  self.global_secondary_indexes[name] = { 
         | 
| 54 | 
            +
                    "keys" => keys, 
         | 
| 55 | 
            +
                    "projection_type" => projection.to_s.upcase,
         | 
| 56 | 
            +
                    "read_capacity_units" => read_capacity_units,
         | 
| 57 | 
            +
                    "write_capacity_units" => write_capacity_units
         | 
| 58 | 
            +
                  }   
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
             | 
| 42 62 | 
             
                protected
         | 
| 43 63 |  | 
| 44 64 | 
             
                def dangerous_attributes # :nodoc:
         | 
    
        data/lib/ocean-dynamo/tables.rb
    CHANGED
    
    | @@ -94,7 +94,7 @@ module OceanDynamo | |
| 94 94 | 
             
                  end
         | 
| 95 95 |  | 
| 96 96 |  | 
| 97 | 
            -
             | 
| 97 | 
            +
                  def create_table
         | 
| 98 98 | 
             
                    attrs = table_attribute_definitions  # This already includes secondary indices
         | 
| 99 99 | 
             
                    keys = table_key_schema
         | 
| 100 100 | 
             
                    options = {
         | 
| @@ -108,6 +108,8 @@ module OceanDynamo | |
| 108 108 | 
             
                    }
         | 
| 109 109 | 
             
                    lsi = local_secondary_indexes.collect { |n| local_secondary_index_declaration n }
         | 
| 110 110 | 
             
                    options[:local_secondary_indexes] = lsi unless lsi.blank?
         | 
| 111 | 
            +
                    gsi = global_secondary_indexes.collect { |k, v| global_secondary_index_declaration k, v }
         | 
| 112 | 
            +
                    options[:global_secondary_indexes] = gsi unless gsi.blank?
         | 
| 111 113 | 
             
                    dynamo_resource.create_table(options)
         | 
| 112 114 | 
             
                    sleep 1 until dynamo_table.table_status == "ACTIVE"
         | 
| 113 115 | 
             
                    setup_dynamo
         | 
| @@ -128,6 +130,31 @@ module OceanDynamo | |
| 128 130 | 
             
                  end
         | 
| 129 131 |  | 
| 130 132 |  | 
| 133 | 
            +
                  def table_attribute_definitions
         | 
| 134 | 
            +
                    attrs = []
         | 
| 135 | 
            +
                    attrs << { attribute_name: table_hash_key.to_s, attribute_type: attribute_type(table_hash_key) }
         | 
| 136 | 
            +
                    attrs << { attribute_name: table_range_key.to_s, attribute_type: attribute_type(table_range_key) }  if table_range_key
         | 
| 137 | 
            +
                    local_secondary_indexes.each do |name|
         | 
| 138 | 
            +
                      attrs << { attribute_name: name, attribute_type: attribute_type(name) }
         | 
| 139 | 
            +
                    end
         | 
| 140 | 
            +
                    global_secondary_indexes.each do |index_name, data|
         | 
| 141 | 
            +
                      data["keys"].each do |name| 
         | 
| 142 | 
            +
                        next if attrs.any? { |a| a[:attribute_name] == name }
         | 
| 143 | 
            +
                        attrs << { attribute_name: name, attribute_type: attribute_type(name) }
         | 
| 144 | 
            +
                      end
         | 
| 145 | 
            +
                    end
         | 
| 146 | 
            +
                    attrs
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
             | 
| 150 | 
            +
                  def table_key_schema(hash_key: table_hash_key, range_key: table_range_key)
         | 
| 151 | 
            +
                    keys = []
         | 
| 152 | 
            +
                    keys << { attribute_name: hash_key.to_s, key_type: "HASH" }
         | 
| 153 | 
            +
                    keys << { attribute_name: range_key.to_s, key_type: "RANGE" } if range_key
         | 
| 154 | 
            +
                    keys
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
             | 
| 131 158 | 
             
                  def local_secondary_indexes
         | 
| 132 159 | 
             
                    @local_secondary_indexes ||= begin
         | 
| 133 160 | 
             
                      result = []
         | 
| @@ -141,28 +168,23 @@ module OceanDynamo | |
| 141 168 |  | 
| 142 169 | 
             
                  def local_secondary_index_declaration(name)
         | 
| 143 170 | 
             
                    { index_name: name,
         | 
| 144 | 
            -
                      key_schema:  | 
| 145 | 
            -
                                   { attribute_name: name.to_s, key_type: "RANGE" }],
         | 
| 171 | 
            +
                      key_schema: table_key_schema(range_key: name),
         | 
| 146 172 | 
             
                      projection: { projection_type: "KEYS_ONLY" }
         | 
| 147 173 | 
             
                    }
         | 
| 148 174 | 
             
                  end
         | 
| 149 175 |  | 
| 150 176 |  | 
| 151 | 
            -
                  def  | 
| 152 | 
            -
                     | 
| 153 | 
            -
                     | 
| 154 | 
            -
                     | 
| 155 | 
            -
             | 
| 156 | 
            -
                       | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
                    keys = []
         | 
| 163 | 
            -
                    keys << { attribute_name: table_hash_key.to_s, key_type: "HASH" }
         | 
| 164 | 
            -
                    keys << { attribute_name: table_range_key.to_s, key_type: "RANGE" } if table_range_key
         | 
| 165 | 
            -
                    keys
         | 
| 177 | 
            +
                  def global_secondary_index_declaration(index_name, data)
         | 
| 178 | 
            +
                    hash_key, range_key = data["keys"]
         | 
| 179 | 
            +
                    key_schema = table_key_schema(hash_key: hash_key, range_key: range_key)
         | 
| 180 | 
            +
                    { index_name: index_name,
         | 
| 181 | 
            +
                      key_schema: key_schema,
         | 
| 182 | 
            +
                      projection: { projection_type: data["projection_type"] },
         | 
| 183 | 
            +
                      provisioned_throughput: {
         | 
| 184 | 
            +
                        read_capacity_units: data["read_capacity_units"],
         | 
| 185 | 
            +
                        write_capacity_units: data["write_capacity_units"]
         | 
| 186 | 
            +
                      }
         | 
| 187 | 
            +
                    }
         | 
| 166 188 | 
             
                  end
         | 
| 167 189 |  | 
| 168 190 |  | 
    
        data/lib/ocean-dynamo/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ocean-dynamo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Peter Bengtson
         | 
| @@ -136,20 +136,20 @@ dependencies: | |
| 136 136 | 
             
                - - ">="
         | 
| 137 137 | 
             
                  - !ruby/object:Gem::Version
         | 
| 138 138 | 
             
                    version: '0'
         | 
| 139 | 
            -
            description: "== OceanDynamo\n\ | 
| 140 | 
            -
               | 
| 141 | 
            -
               | 
| 142 | 
            -
               | 
| 143 | 
            -
               | 
| 144 | 
            -
               | 
| 145 | 
            -
               | 
| 146 | 
            -
               | 
| 147 | 
            -
               | 
| 148 | 
            -
               | 
| 149 | 
            -
               | 
| 150 | 
            -
               | 
| 151 | 
            -
               | 
| 152 | 
            -
               | 
| 139 | 
            +
            description: "== OceanDynamo\n\nAs one important use case for OceanDynamo is to facilitate
         | 
| 140 | 
            +
              the conversion of SQL\ndatabases to no-SQL DynamoDB databases, it is important that
         | 
| 141 | 
            +
              the syntax and semantics\nof OceanDynamo are as close as possible to those of ActiveRecord.
         | 
| 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
         | 
| 144 | 
            +
              and persistence layer of OceanDynamo is modeled on that of ActiveRecord:\nthere's
         | 
| 145 | 
            +
              +save+, +save!+, +create+, +update+, +update!+, +update_attributes+, +find_each+,\n+destroy_all+,
         | 
| 146 | 
            +
              +delete_all+, +read_attribute+, +write_attribute+ and all the other \nmethods you're
         | 
| 147 | 
            +
              used to. The design goal is always to implement as much of the ActiveRecord\ninterface
         | 
| 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 retrieve
         | 
| 150 | 
            +
              related table items and collections, \nwhich means it will scale without limits.\n\nOceanDynamo
         | 
| 151 | 
            +
              is fully usable as an ActiveModel and can be used by Rails\ncontrollers. Thanks
         | 
| 152 | 
            +
              to its structural similarity to ActiveRecord, OceanDynamo works \nwith FactoryGirl.\n\nSee
         | 
| 153 153 | 
             
              also Ocean, a Rails framework for creating highly scalable SOAs in the cloud, in
         | 
| 154 154 | 
             
              which\nocean-dynamo is used as a central component: http://wiki.oceanframework.net"
         | 
| 155 155 | 
             
            email:
         |