dynamodb_model 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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