dynamodb_model 0.3.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e369807797f7eeb8eef8476828b0760a85e8076
4
- data.tar.gz: 23f014fb766cda2c085bbc932ab9961946155150
3
+ metadata.gz: 355ffd3eb3d0d42649b31239c6297464be46d260
4
+ data.tar.gz: e6ec2b09237a89b6e0c617d0e0f888c5578a52a5
5
5
  SHA512:
6
- metadata.gz: aa48e2bf21ff32e98640a3264f35c2b9e77ae51d1e8638c912404041fc68b1da336b24c3005dc703457ff013eec49fea9234ea516ac1473d611b90dc5f59cd06
7
- data.tar.gz: eaebb86f390ce9e2035af5e50f71f3235c5459284ee4cf540425272f0d511b826b568ad925da367fa9b47c2749e950bac56692901f805a3247cb31cc9e43818e
6
+ metadata.gz: 57b068c88fbf47de849a3980be63a98411f0103bc979c2457248b71e3d17b7d7bec0fc9a45a3f99d7a939ac5f811f0c5ee814907def64105bd678465af5e3721
7
+ data.tar.gz: c0c1ba569bbc4a1e411b3cc6821abd96a003a0fdba71dc56b6846f30275d3fd309ac8b6f524658b990045c1ec4745fd77880dbed2dc5a57665eecb847a4e0a45
data/CHANGELOG.md CHANGED
@@ -3,6 +3,11 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [1.0.0]
7
+ - LSI support
8
+ - automatically infer table_name
9
+ - automatically infer create_table and update_table migrations types
10
+
6
11
  ## [0.3.0]
7
12
  - DSL methods now available: create_table, update_table
8
13
  - Also can add GSI indexes within update_table with: i.gsi
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DynamodbModel
2
2
 
3
- A simple wrapper library to make DynamoDB usage a little more friendly. The modeling is ActiveRecord-ish but not exactly because DynamoDB is a different type of database. Examples and the [item_spec.rb](spec/lib/dynamodb_model/item_spec.rb) explain it best:
3
+ A simple wrapper library to make DynamoDB usage a little more friendly. The modeling is ActiveRecord-ish but not exactly because DynamoDB is a different type of database. Examples below explain it best:
4
4
 
5
5
  ## Examples
6
6
 
@@ -69,6 +69,26 @@ posts = Post.scan(options)
69
69
  posts # Array of Post items. [Post.new, Post.new, ...]
70
70
  ```
71
71
 
72
+ Examples are also in [item_spec.rb](spec/lib/dynamodb_model/item_spec.rb).
73
+
74
+ ## Migration Support
75
+
76
+ DynamodbModel supports ActiveRecord-like migrations. Here's a short example:
77
+
78
+ ```ruby
79
+ class CreateCommentsMigration < DynamodbModel::Migration
80
+ def up
81
+ create_table :comments do |t|
82
+ t.partition_key "post_id:string" # required
83
+ t.sort_key "created_at:string" # optional
84
+ t.provisioned_throughput(5) # sets both read and write, defaults to 5 when not set
85
+ end
86
+ end
87
+ end
88
+ ```
89
+
90
+ More examples are in the [docs/migrations](docs/migrations) folder.
91
+
72
92
  ## Installation
73
93
 
74
94
  Add this line to your application's Gemfile:
@@ -4,6 +4,13 @@ class CreateCommentsMigration < DynamodbModel::Migration
4
4
  t.partition_key "post_id:string" # required
5
5
  t.sort_key "created_at:string" # optional
6
6
  t.provisioned_throughput(5) # sets both read and write, defaults to 5 when not set
7
+
8
+ t.lsi do |i|
9
+ i.partition_key "user_id:string"
10
+ i.sort_key "updated_at:string" # optional
11
+
12
+ i.provisioned_throughput(10)
13
+ end
7
14
  end
8
15
  end
9
16
  end
@@ -2,11 +2,21 @@ $:.unshift(File.expand_path("../", __FILE__))
2
2
  require "dynamodb_model/version"
3
3
 
4
4
  module DynamodbModel
5
+ ATTRIBUTE_TYPES = {
6
+ 'string' => 'S',
7
+ 'number' => 'N',
8
+ 'binary' => 'B',
9
+ 's' => 'S',
10
+ 'n' => 'N',
11
+ 'b' => 'B',
12
+ }
13
+
5
14
  autoload :Migration, "dynamodb_model/migration"
6
15
  autoload :Dsl, "dynamodb_model/dsl"
7
16
  autoload :DbConfig, "dynamodb_model/db_config"
8
17
  autoload :Item, "dynamodb_model/item"
9
18
  autoload :Util, "dynamodb_model/util"
19
+ autoload :Erb, "dynamodb_model/erb"
10
20
 
11
21
  extend Util
12
22
  end
@@ -0,0 +1,51 @@
1
+ require 'erb'
2
+
3
+ # Renders Erb and provide better backtrace where there's an error
4
+ #
5
+ # Usage:
6
+ #
7
+ # result = DynamodbModel::Erb.result(path, key1: "val1", key2: "val2")
8
+ #
9
+ class DynamodbModel::Erb
10
+ class << self
11
+ def result(path, variables={})
12
+ set_template_variables(variables)
13
+ template = IO.read(path)
14
+ begin
15
+ ERB.new(template, nil, "-").result(binding)
16
+ rescue Exception => e
17
+ puts e
18
+ puts e.backtrace if ENV['DEBUG']
19
+
20
+ # how to know where ERB stopped? - https://www.ruby-forum.com/topic/182051
21
+ # syntax errors have the (erb):xxx info in e.message
22
+ # undefined variables have (erb):xxx info in e.backtrac
23
+ error_info = e.message.split("\n").grep(/\(erb\)/)[0]
24
+ error_info ||= e.backtrace.grep(/\(erb\)/)[0]
25
+ raise unless error_info # unable to find the (erb):xxx: error line
26
+ line = error_info.split(':')[1].to_i
27
+ puts "Error evaluating ERB template on line #{line.to_s.colorize(:red)} of: #{path.sub(/^\.\//, '').colorize(:green)}"
28
+
29
+ template_lines = template.split("\n")
30
+ context = 5 # lines of context
31
+ top, bottom = [line-context-1, 0].max, line+context-1
32
+ spacing = template_lines.size.to_s.size
33
+ template_lines[top..bottom].each_with_index do |line_content, index|
34
+ line_number = top+index+1
35
+ if line_number == line
36
+ printf("%#{spacing}d %s\n".colorize(:red), line_number, line_content)
37
+ else
38
+ printf("%#{spacing}d %s\n", line_number, line_content)
39
+ end
40
+ end
41
+ exit 1 unless ENV['TEST']
42
+ end
43
+ end
44
+
45
+ def set_template_variables(variables)
46
+ variables.each do |key, value|
47
+ instance_variable_set(:"@#{key}", value)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -120,7 +120,7 @@ module DynamodbModel
120
120
  #
121
121
  # AWS Docs examples: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Ruby.04.html
122
122
  def self.scan(params={})
123
- puts("Should not use scan for production. It's slow and expensive. You should create either a LSI or GSI and use query the index instead.")
123
+ puts("It's recommended to not use scan for production. It can be slow and expensive. You can a LSI or GSI and query the index instead.")
124
124
  params = { table_name: table_name }.merge(params)
125
125
  resp = db.scan(params)
126
126
  resp.items.map {|i| self.new(i) }
@@ -1,3 +1,5 @@
1
+ # Common methods to the *SecondaryIndex classes that handle gsi and lsi methods
2
+ # as well a the Dsl class that handles create_table and update_table methods.
1
3
  class DynamodbModel::Migration::Dsl
2
4
  module Common
3
5
  # http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Types/KeySchemaElement.html
@@ -31,7 +33,7 @@ class DynamodbModel::Migration::Dsl
31
33
 
32
34
  attribute_definition = {
33
35
  attribute_name: name,
34
- attribute_type: ATTRIBUTE_TYPE_MAP[attribute_type]
36
+ attribute_type: DynamodbModel::ATTRIBUTE_TYPES[attribute_type]
35
37
  }
36
38
  @attribute_definitions << attribute_definition
37
39
  end
@@ -73,7 +75,7 @@ class DynamodbModel::Migration::Dsl
73
75
  write: :write_capacity_units,
74
76
  }
75
77
 
76
- if capacity_type = :both
78
+ if capacity_type == :both
77
79
  @provisioned_throughput[map[:read]] = capacity_units
78
80
  @provisioned_throughput[map[:write]] = capacity_units
79
81
  else
@@ -1,20 +1,13 @@
1
1
  class DynamodbModel::Migration
2
2
  class Dsl
3
- autoload :GlobalSecondaryIndex, "dynamodb_model/migration/dsl/global_secondary_index"
4
3
  autoload :Common, "dynamodb_model/migration/common"
4
+ autoload :BaseSecondaryIndex, "dynamodb_model/migration/dsl/base_secondary_index"
5
+ autoload :LocalSecondaryIndex, "dynamodb_model/migration/dsl/local_secondary_index"
6
+ autoload :GlobalSecondaryIndex, "dynamodb_model/migration/dsl/global_secondary_index"
5
7
 
6
8
  include DynamodbModel::DbConfig
7
9
  include Common
8
10
 
9
- ATTRIBUTE_TYPE_MAP = {
10
- 'string' => 'S',
11
- 'number' => 'N',
12
- 'binary' => 'B',
13
- 's' => 'S',
14
- 'n' => 'N',
15
- 'b' => 'B',
16
- }
17
-
18
11
  attr_accessor :key_schema, :attribute_definitions
19
12
  attr_accessor :table_name
20
13
  def initialize(method_name, table_name, &block)
@@ -35,6 +28,7 @@ class DynamodbModel::Migration
35
28
 
36
29
  # Attributes for update_table only:
37
30
  @gsi_indexes = []
31
+ @lsi_indexes = []
38
32
  end
39
33
 
40
34
  # t.gsi(:create) do |i|
@@ -47,6 +41,17 @@ class DynamodbModel::Migration
47
41
  end
48
42
  alias_method :global_secondary_index, :gsi
49
43
 
44
+ # t.lsi(:create) do |i|
45
+ # i.partition_key = "category:string"
46
+ # i.sort_key = "created_at:string" # optional
47
+ # end
48
+ def lsi(action=:create, index_name=nil, &block)
49
+ # dont need action create but have it to keep the lsi and gsi method consistent
50
+ lsi_index = LocalSecondaryIndex.new(index_name, &block)
51
+ @lsi_indexes << lsi_index # store @lsi_index for the parent Dsl to use
52
+ end
53
+ alias_method :local_secondary_index, :gsi
54
+
50
55
  def evaluate
51
56
  return if @evaluated
52
57
  @block.call(self) if @block
@@ -69,20 +74,53 @@ class DynamodbModel::Migration
69
74
  end
70
75
 
71
76
  def params_create_table
72
- {
77
+ params = {
73
78
  table_name: namespaced_table_name,
74
79
  key_schema: @key_schema,
75
80
  attribute_definitions: @attribute_definitions,
76
81
  provisioned_throughput: @provisioned_throughput
77
82
  }
83
+
84
+ params[:local_secondary_index_creates] = local_secondary_index_creates unless @lsi_indexes.empty?
85
+ params
86
+ end
87
+
88
+ # Goes thorugh all the lsi_indexes that have been built up in memory.
89
+ # Find the lsi object that creates an index and then grab the
90
+ # attribute_definitions from it.
91
+ def lsi_create_attribute_definitions
92
+ lsi = @lsi_indexes.first # DynamoDB only supports adding one index at a time anyway. The reason @lsi_indexes is an Array is because we're sharing the same class code for LSI and GSI
93
+ if lsi
94
+ lsi.evaluate # force early evaluate since we need the params to
95
+ # add: gsi_attribute_definitions + lsi_attrs
96
+ lsi_attrs = lsi.attribute_definitions
97
+ end
98
+ all_attrs = if lsi_attrs
99
+ @attribute_definitions + lsi_attrs
100
+ else
101
+ @attribute_definitions
102
+ end
103
+ all_attrs.uniq
104
+ end
105
+
106
+ # maps each lsi to the hash structure expected by dynamodb update_table
107
+ # under the global_secondary_index_updates key:
108
+ #
109
+ # { create: {...} }
110
+ # { update: {...} }
111
+ # { delete: {...} }
112
+ def lsi_secondary_index_creates
113
+ @lsi_indexes.map do |lsi|
114
+ { lsi.action => lsi.params }
115
+ end
78
116
  end
79
117
 
80
118
  def params_update_table
81
119
  params = {
82
120
  table_name: namespaced_table_name,
121
+ attribute_definitions: gsi_create_attribute_definitions,
83
122
  # update table take values only some values for the "parent" table
84
- attribute_definitions: gsi_create_attribute_definitions, # This is only a partial
85
- # key_schema: @key_schema, # update_table does not handle key_schema for the "parent" table,
123
+ # no key_schema, update_table does not handle key_schema for the "parent" table
86
124
  }
87
125
  # only set "parent" table provisioned_throughput if user actually invoked
88
126
  # it in the dsl
@@ -98,13 +136,13 @@ class DynamodbModel::Migration
98
136
  gsi = @gsi_indexes.find { |gsi| gsi.action == :create }
99
137
  if gsi
100
138
  gsi.evaluate # force early evaluate since we need the params to
101
- # add: current_attribute_definitions + gsi_attrs
139
+ # add: gsi_attribute_definitions + gsi_attrs
102
140
  gsi_attrs = gsi.attribute_definitions
103
141
  end
104
142
  all_attrs = if gsi_attrs
105
- current_attribute_definitions + gsi_attrs
143
+ gsi_attribute_definitions + gsi_attrs
106
144
  else
107
- current_attribute_definitions
145
+ gsi_attribute_definitions
108
146
  end
109
147
  all_attrs.uniq
110
148
  end
@@ -124,11 +162,11 @@ class DynamodbModel::Migration
124
162
  # >> resp = Post.db.describe_table(table_name: "proj-dev-posts")
125
163
  # >> resp.table.attribute_definitions.map(&:to_h)
126
164
  # => [{:attribute_name=>"id", :attribute_type=>"S"}]
127
- def current_attribute_definitions
128
- return @current_attribute_definitions if @current_attribute_definitions
165
+ def gsi_attribute_definitions
166
+ return @gsi_attribute_definitions if @gsi_attribute_definitions
129
167
 
130
168
  resp = db.describe_table(table_name: namespaced_table_name)
131
- @current_attribute_definitions = resp.table.attribute_definitions.map(&:to_h)
169
+ @gsi_attribute_definitions = resp.table.attribute_definitions.map(&:to_h)
132
170
  end
133
171
  end
134
172
  end
@@ -0,0 +1,72 @@
1
+ # Base class for LocalSecondaryIndex and GlobalSecondaryIndex
2
+ class DynamodbModel::Migration::Dsl
3
+ class BaseSecondaryIndex
4
+ include Common
5
+
6
+ attr_accessor :action, :key_schema, :attribute_definitions
7
+ attr_accessor :index_name
8
+ def initialize(action, index_name=nil, &block)
9
+ @action = action.to_sym
10
+ # for gsi action can be: :create, :update, :delete
11
+ # for lsi action is always: :create
12
+ @index_name = index_name
13
+ @block = block
14
+
15
+ # Dsl fills these atttributes in as methods are called within
16
+ # the block
17
+ @key_schema = []
18
+ @attribute_definitions = []
19
+ # default provisioned_throughput
20
+ @provisioned_throughput = {
21
+ read_capacity_units: 5,
22
+ write_capacity_units: 5
23
+ }
24
+ end
25
+
26
+ def index_name
27
+ @index_name || conventional_index_name
28
+ end
29
+
30
+ def conventional_index_name
31
+ # @partition_key_identifier and @sort_key_identifier are set as immediately
32
+ # when the partition_key and sort_key methods are called in the dsl block.
33
+ # Usually look like this:
34
+ #
35
+ # @partition_key_identifier: post_id:string
36
+ # @sort_key_identifier: updated_at:string
37
+ #
38
+ # We strip the :string portion in case it is provided
39
+ #
40
+ partition_key = @partition_key_identifier.split(':').first
41
+ sort_key = @sort_key_identifier.split(':').first if @sort_key_identifier
42
+ [partition_key, sort_key, "index"].compact.join('-')
43
+ end
44
+
45
+ def evaluate
46
+ return if @evaluated
47
+ @block.call(self) if @block
48
+ @evaluated = true
49
+ end
50
+
51
+ def params
52
+ evaluate # lazy evaluation: wait until as long as possible before evaluating code block
53
+
54
+ params = { index_name: index_name } # required for all actions
55
+
56
+ if @action == :create
57
+ params[:key_schema] = @key_schema # required for create action
58
+ # hardcode to ALL for now
59
+ params[:projection] = { # required
60
+ projection_type: "ALL", # accepts ALL, KEYS_ONLY, INCLUDE
61
+ # non_key_attributes: ["NonKeyAttributeName"],
62
+ }
63
+ end
64
+
65
+ if [:create, :update].include?(@action)
66
+ params[:provisioned_throughput] = @provisioned_throughput
67
+ end
68
+
69
+ params
70
+ end
71
+ end
72
+ end
@@ -1,71 +1,4 @@
1
1
  class DynamodbModel::Migration::Dsl
2
- class GlobalSecondaryIndex
3
- include Common
4
-
5
- ATTRIBUTE_TYPE_MAP = DynamodbModel::Migration::Dsl::ATTRIBUTE_TYPE_MAP
6
-
7
- attr_accessor :action, :key_schema, :attribute_definitions
8
- attr_accessor :index_name
9
- def initialize(action, index_name=nil, &block)
10
- @action = action.to_sym # :create, :update, :index
11
- @index_name = index_name
12
- @block = block
13
-
14
- # Dsl fills these atttributes in as methods are called within
15
- # the block
16
- @key_schema = []
17
- @attribute_definitions = []
18
- # default provisioned_throughput
19
- @provisioned_throughput = {
20
- read_capacity_units: 5,
21
- write_capacity_units: 5
22
- }
23
- end
24
-
25
- def index_name
26
- @index_name || conventional_index_name
27
- end
28
-
29
- def conventional_index_name
30
- # @partition_key_identifier and @sort_key_identifier are set as immediately
31
- # when the partition_key and sort_key methods are called in the dsl block.
32
- # Usually look like this:
33
- #
34
- # @partition_key_identifier: post_id:string
35
- # @sort_key_identifier: updated_at:string
36
- #
37
- # We strip the :string portion in case it is provided
38
- #
39
- partition_key = @partition_key_identifier.split(':').first
40
- sort_key = @sort_key_identifier.split(':').first if @sort_key_identifier
41
- [partition_key, sort_key, "index"].compact.join('-')
42
- end
43
-
44
- def evaluate
45
- return if @evaluated
46
- @block.call(self) if @block
47
- @evaluated = true
48
- end
49
-
50
- def params
51
- evaluate # lazy evaluation: wait until as long as possible before evaluating code block
52
-
53
- params = { index_name: index_name } # required for all actions
54
-
55
- if @action == :create
56
- params[:key_schema] = @key_schema # required for create action
57
- # hardcode to ALL for now
58
- params[:projection] = { # required
59
- projection_type: "ALL", # accepts ALL, KEYS_ONLY, INCLUDE
60
- # non_key_attributes: ["NonKeyAttributeName"],
61
- }
62
- end
63
-
64
- if [:create, :update].include?(@action)
65
- params[:provisioned_throughput] = @provisioned_throughput
66
- end
67
-
68
- params
69
- end
2
+ class GlobalSecondaryIndex < BaseSecondaryIndex
70
3
  end
71
4
  end
@@ -0,0 +1,8 @@
1
+ class DynamodbModel::Migration::Dsl
2
+ class LocalSecondaryIndex < BaseSecondaryIndex
3
+ def initialize(index_name=nil, &block)
4
+ # Can only create local secondary index when creating a table
5
+ super(:create, index_name, &block)
6
+ end
7
+ end
8
+ end
@@ -5,9 +5,9 @@ class DynamodbModel::Migration
5
5
  class Generator
6
6
  include DynamodbModel::DbConfig
7
7
 
8
- attr_reader :table_name
9
- def initialize(table_name, options)
10
- @table_name = table_name.pluralize
8
+ attr_reader :migration_name, :table_name
9
+ def initialize(migration_name, options)
10
+ @migration_name = migration_name
11
11
  @options = options
12
12
  end
13
13
 
@@ -18,27 +18,47 @@ class DynamodbModel::Migration
18
18
  end
19
19
 
20
20
  def create_migration
21
- migration_relative_path = "db/migrate/#{migration_file_name}.rb"
22
- migration_path = "#{DynamodbModel.root}#{migration_relative_path}"
23
- dir = File.dirname(migration_path)
24
- FileUtils.mkdir_p(dir) unless File.exist?(dir)
21
+ FileUtils.mkdir_p(File.dirname(migration_path))
25
22
  IO.write(migration_path, migration_code)
26
- puts "Migration file created: #{migration_relative_path}. To run:"
27
- puts " jets db migrate #{migration_relative_path}"
23
+ puts "Migration file created: #{migration_path}. \nTo run:"
24
+ puts " jets dynamodb migrate #{migration_path}"
28
25
  end
29
26
 
30
27
  def migration_code
31
- # @table_name already set
32
- @migration_class_name = "#{@table_name}_migration".classify
33
- @partition_key = @options[:partition_key]
34
- @sort_key = @options[:sort_key]
35
- @provisioned_throughput = @options[:provisioned_throughput] || 5
36
- template = IO.read(File.expand_path("../template.rb", __FILE__))
37
- result = ERB.new(template, nil, "-").result(binding)
28
+ path = File.expand_path("../templates/#{table_action}.rb", __FILE__)
29
+ result = DynamodbModel::Erb.result(path,
30
+ migration_class_name: migration_class_name,
31
+ table_name: table_name,
32
+ partition_key: @options[:partition_key],
33
+ sort_key: @options[:sort_key],
34
+ provisioned_throughput: @options[:provisioned_throughput] || 5,
35
+ )
38
36
  end
39
37
 
40
- def migration_file_name
41
- "#{@table_name}_migration"
38
+ def table_action
39
+ @options[:table_action] || conventional_table_action
40
+ end
41
+
42
+ def conventional_table_action
43
+ @migration_name.include?("update") ? "update_table" : "create_table"
44
+ end
45
+
46
+ def table_name
47
+ @options[:table_name] || conventional_table_name
48
+ end
49
+
50
+ # create_posts => posts
51
+ # update_posts => posts
52
+ def conventional_table_name
53
+ @migration_name.sub(/^(create|update)_/, '')
54
+ end
55
+
56
+ def migration_class_name
57
+ "#{@migration_name}_migration".classify # doesnt include timestamp
58
+ end
59
+
60
+ def migration_path
61
+ "#{DynamodbModel.app_root}dynamodb/migrate/#{timestamp}-#{@migration_name}_migration.rb"
42
62
  end
43
63
 
44
64
  def timestamp
@@ -1,32 +1,3 @@
1
- # Note: table name created will be namespaced based on
2
- # DynamodbModel::Migration.table_namespace. This can be set in
3
- # config/dynamodb.yml
4
- #
5
- # development:
6
- # table_namespace: "mynamespace"
7
- #
8
- # This results in:
9
- # create_table "posts" => table name: "mynamespace-posts"
10
- #
11
- # When you're in a in Jets project you can set the namespace based on
12
- # Jets.config.table_namespace, which is based on the project name and
13
- # a short version of the environment. Example:
14
- #
15
- # `config/dynamodb.yml`:
16
- # development:
17
- # table_namespace: <%%= Jets.config.table_namespace %>
18
- #
19
- # If your project_name is proj and environment is production:
20
- # create_table "posts" => table name: "proj-prod-posts"
21
- #
22
- # If your project_name is proj and environment is staging:
23
- # create_table "posts" => table name: "proj-stag-posts"
24
- #
25
- # If your project_name is proj and environment is development:
26
- # create_table "posts" => table name: "proj-dev-posts"
27
- #
28
- # If the table_namespace is set to a blank string or nil, then a namespace
29
- # will not be prepended at all.
30
1
  class <%= @migration_class_name %> < DynamodbModel::Migration
31
2
  def up
32
3
  create_table :<%= @table_name %> do |t|
@@ -57,3 +28,5 @@ class <%= @migration_class_name %> < DynamodbModel::Migration
57
28
  end
58
29
  end
59
30
  end
31
+
32
+ # More examples: https://github.com/tongueroo/dynamodb_model/tree/master/docs
@@ -0,0 +1,26 @@
1
+ class <%= @migration_class_name %> < DynamodbModel::Migration
2
+ def up
3
+ update_table :<%= @table_name %> do |t|
4
+ t.gsi(:create) do |i|
5
+ i.partition_key "<%= @partition_key %>" # required
6
+ <% if @sort_key # so extra spaces are not added when generated -%>
7
+ t.sort_key "<%= @sort_key %>" # optional
8
+ <% end -%>
9
+
10
+ i.provisioned_throughput(5)
11
+ end
12
+
13
+ # Examples:
14
+ # t.gsi(:update, "update-me-index") do |i|
15
+ # i.provisioned_throughput(10)
16
+ # end
17
+
18
+ # t.gsi(:delete, "delete-me-index")
19
+
20
+ # Must use :create, :update, :delete one at a time in separate migration files.
21
+ # DynamoDB imposes this.
22
+ end
23
+ end
24
+ end
25
+
26
+ # More examples: https://github.com/tongueroo/dynamodb_model/tree/master/docs
@@ -4,12 +4,12 @@ module DynamodbModel::Util
4
4
  # Ensures trailing slash
5
5
  # Useful for appending a './' in front of a path or leaving it alone.
6
6
  # Returns: '/path/with/trailing/slash/' or './'
7
- @@root = nil
8
- def root
9
- return @@root if @@root
10
- @@root = ENV['PROJECT_ROOT'].to_s
11
- @@root = '.' if @@root == ''
12
- @@root = "#{@@root}/" unless @@root.ends_with?('/')
13
- @@root
7
+ @@app_root = nil
8
+ def app_root
9
+ return @@app_root if @@app_root
10
+ @@app_root = ENV['APP_ROOT'].to_s
11
+ @@app_root = '.' if @@app_root == ''
12
+ @@app_root = "#{@@app_root}/" unless @@app_root.ends_with?('/')
13
+ @@app_root
14
14
  end
15
15
  end
@@ -1,3 +1,3 @@
1
1
  module DynamodbModel
2
- VERSION = "0.3.0"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamodb_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-06 00:00:00.000000000 Z
11
+ date: 2017-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -95,19 +95,23 @@ files:
95
95
  - Rakefile
96
96
  - bin/console
97
97
  - bin/setup
98
- - docs/migrations-long.rb
99
- - docs/migrations-short.rb
98
+ - docs/migrations/long-example.rb
99
+ - docs/migrations/short-example.rb
100
100
  - dynamodb_model.gemspec
101
101
  - lib/dynamodb_model.rb
102
102
  - lib/dynamodb_model/db_config.rb
103
+ - lib/dynamodb_model/erb.rb
103
104
  - lib/dynamodb_model/item.rb
104
105
  - lib/dynamodb_model/migration.rb
105
106
  - lib/dynamodb_model/migration/common.rb
106
107
  - lib/dynamodb_model/migration/dsl.rb
108
+ - lib/dynamodb_model/migration/dsl/base_secondary_index.rb
107
109
  - lib/dynamodb_model/migration/dsl/global_secondary_index.rb
110
+ - lib/dynamodb_model/migration/dsl/local_secondary_index.rb
108
111
  - lib/dynamodb_model/migration/executor.rb
109
112
  - lib/dynamodb_model/migration/generator.rb
110
- - lib/dynamodb_model/migration/template.rb
113
+ - lib/dynamodb_model/migration/templates/create_table.rb
114
+ - lib/dynamodb_model/migration/templates/update_table.rb
111
115
  - lib/dynamodb_model/util.rb
112
116
  - lib/dynamodb_model/version.rb
113
117
  homepage: https://github.com/tongueroo/dynamodb_model