Dynamo::Record
Provides helpful rake tasks and model extensions on top of aws-record.
Installation
Add this line to your application's Gemfile:
gem 'dynamo-record'
And then execute:
$ bundle
Or install it yourself as:
$ gem install dynamo-record
Usage
Models
In app/models
, create a class that includes Dynamo::Record::Model
and contains
one or more of the
standard set
of attribute declarations, along with the following new composite attribute
types:
composite_string_attr
composite_integer_attr
An example file:
class MyModel
include Dynamo::Record::Model
composite_string_attr(
:model_key,
hash_key: true,
parts: [:model_id, :account_id]
)
integer_attr :position, range_key: true
string_attr :user_id
float_attr :score
map_attr :map_value
end
The partition key is labeled with hash_key: true
. The sort key is labeled with
range_key: true
.
Declaring secondary indexes are included in aws-record
and are defined
here.
As an example, a global secondary index can be defined as follows:
global_secondary_index(
:user_idx,
hash_key: :user_id,
range_key: :score,
projection: {
projection_type: 'INCLUDE',
non_key_attributes: [
:map_value
]
}
)
As an example, a local secondary index can be defined as follows:
local_secondary_index(
:score_idx,
range_key: :score,
projection: {
projection_type: 'INCLUDE',
non_key_attributes: [
:map_value
]
}
)
The full documentation for projection_type
and non_key_attributes
can be
found here.
Query Helpers
Query helpers are included as class methods.
composite_key(*args)
For models that have composite attributes, create a composite key value from the individual attribute parts:
hash_key = MyModel.composite_key('model_1', 'account_1')
split_composite(string)
Split a composite attribute value into its individual attribute parts:
model_id, acccount_id = MyModel.split_composite(hash_key)
find_all_by_hash_key(hash_key_value, opts = {})
Find all item instances that match a given hash key value. opts
are options
passed to the underlying query.
MyModel.find_all_by_hash_key(hash_key)
find_all_by_gsi_hash_key(gsi_name, hash_key_value, opts = {})
Find all item instances using a global secondary instance using a hash key
value. opts
are options passed to the underlying query.
MyModel.find_all_by_gsi_hash_key('user_idx', 'user_1')
find_all_by_gsi_hash_and_range_keys(gsi_name, hash_key_value, range_key_value)
Find all item instances using a global secondary instance using a hash key value and range key value.
MyModel.find_all_by_gsi_hash_key('user_idx', 'user_1', 0.0)
find_all_by_lsi_hash_key(lsi_name, hash_key_value, opts = {})
Find all item instances using a local secondary instance using a hash key value.
opts
are options passed to the underlying query.
MyModel.find_all_by_lsi_hash_key('score_idx', 'user_1')
find_all_by_lsi_hash_and_range_keys(lsi_name, hash_key_value, range_key_value)
Find all item instances using a local secondary instance using a hash key value and range key value.
MyModel.find_all_by_lsi_hash_key('score_idx', 'user_1', 0.0)
Migrations
Dynamo migration files are stored in db/dynamo_migrate
. The name of the file
follows the style of standard Rails migration files like
YYYYMMDDHHMMSS_create_model_1.rb
. A migration file that creates a Dynamo table
looks like:
module DynamoMigrate
class CreateMyModel < Dynamo::Record::TableMigration
def self.up
migrate(MyModel) do |migration|
migration.create!(
provisioned_throughput: {
read_capacity_units: 1,
write_capacity_units: 1
},
global_secondary_index_throughput: {
user_idx: {
read_capacity_units: 1,
write_capacity_units: 1
}
}
)
end
end
end
end
Note that the throughput of the table can be configured separately from the throughput of the secondary index.
A migration file that creates a Dynamo stream looks like:
module DynamoMigrate
class AddMyModelStream < Dynamo::Record::TableMigration
def self.update
add_stream(MyModel)
end
end
end
Development
A simple docker environment has been provided for spinning up and testing this gem with multiple versions of Ruby. This requires docker and docker-compose to be installed. To get started, run the following:
./build.sh
This will install the gem in a docker image with all versions of Ruby installed, and install all gem dependencies in the Ruby 2.4 set of gems. It will also download and spin up a DynamoDB Local container for use with specs. Finally, it will run wwtd, which runs all specs across all supported version of Ruby and Rails, bundling gems for each combination along the way.
The first build will take a long time, however, docker images and gems are cached, making additional runs significantly faster.
Individual spec runs can be started like so:
docker-compose run --rm app /bin/bash -l -c \
"BUNDLE_GEMFILE=spec/gemfiles/rails-5.0.gemfile rvm-exec 2.4 bundle exec rspec"
If you'd like to mount your git checkout within the docker container running tests so changes are easier to test, use the override provided:
cp docker-compose.override.example.yml docker-compose.override.yml
Making a new Release
To release a new version, update the version number in version.rb
, and then
just run gem build dynamo-record
, and push the .gem
file to
rubygems.org. To install this gem onto your local
machine, run gem install dynamo-record-*.gem
.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/instructure/dynamo-record.
License
The gem is available as open source under the terms of the MIT License.