dynomite 1.2.7 → 2.0.1

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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -2
  3. data/CHANGELOG.md +21 -0
  4. data/Gemfile +1 -5
  5. data/LICENSE.txt +22 -0
  6. data/README.md +6 -190
  7. data/Rakefile +13 -1
  8. data/dynomite.gemspec +9 -2
  9. data/exe/dynomite +14 -0
  10. data/lib/dynomite/associations/association.rb +126 -0
  11. data/lib/dynomite/associations/belongs_to.rb +35 -0
  12. data/lib/dynomite/associations/has_and_belongs_to_many.rb +19 -0
  13. data/lib/dynomite/associations/has_many.rb +19 -0
  14. data/lib/dynomite/associations/has_one.rb +19 -0
  15. data/lib/dynomite/associations/many_association.rb +257 -0
  16. data/lib/dynomite/associations/single_association.rb +157 -0
  17. data/lib/dynomite/associations.rb +248 -0
  18. data/lib/dynomite/autoloader.rb +25 -0
  19. data/lib/dynomite/cli.rb +48 -0
  20. data/lib/dynomite/client.rb +118 -0
  21. data/lib/dynomite/command.rb +89 -0
  22. data/lib/dynomite/completer/script.rb +6 -0
  23. data/lib/dynomite/completer/script.sh +10 -0
  24. data/lib/dynomite/completer.rb +159 -0
  25. data/lib/dynomite/config.rb +39 -0
  26. data/lib/dynomite/core.rb +18 -19
  27. data/lib/dynomite/engine.rb +15 -0
  28. data/lib/dynomite/erb.rb +5 -3
  29. data/lib/dynomite/error.rb +12 -0
  30. data/lib/dynomite/help/completion.md +20 -0
  31. data/lib/dynomite/help/completion_script.md +3 -0
  32. data/lib/dynomite/help/migrate.md +3 -0
  33. data/lib/dynomite/help.rb +9 -0
  34. data/lib/dynomite/install.rb +4 -0
  35. data/lib/dynomite/item/abstract.rb +15 -0
  36. data/lib/dynomite/item/components.rb +33 -0
  37. data/lib/dynomite/item/dsl.rb +101 -0
  38. data/lib/dynomite/item/id.rb +41 -0
  39. data/lib/dynomite/item/indexes/finder.rb +58 -0
  40. data/lib/dynomite/item/indexes/index.rb +21 -0
  41. data/lib/dynomite/item/indexes/primary_index.rb +18 -0
  42. data/lib/dynomite/item/indexes.rb +25 -0
  43. data/lib/dynomite/item/locking.rb +53 -0
  44. data/lib/dynomite/item/magic_fields.rb +66 -0
  45. data/lib/dynomite/item/primary_key.rb +85 -0
  46. data/lib/dynomite/item/query/delegates.rb +28 -0
  47. data/lib/dynomite/item/query/params/base.rb +42 -0
  48. data/lib/dynomite/item/query/params/expression_attribute.rb +79 -0
  49. data/lib/dynomite/item/query/params/filter.rb +41 -0
  50. data/lib/dynomite/item/query/params/function/attribute_exists.rb +21 -0
  51. data/lib/dynomite/item/query/params/function/attribute_type.rb +30 -0
  52. data/lib/dynomite/item/query/params/function/base.rb +33 -0
  53. data/lib/dynomite/item/query/params/function/begins_with.rb +32 -0
  54. data/lib/dynomite/item/query/params/function/contains.rb +7 -0
  55. data/lib/dynomite/item/query/params/function/size_fn.rb +37 -0
  56. data/lib/dynomite/item/query/params/helpers.rb +94 -0
  57. data/lib/dynomite/item/query/params/key_condition.rb +34 -0
  58. data/lib/dynomite/item/query/params.rb +115 -0
  59. data/lib/dynomite/item/query/partiql/executer.rb +72 -0
  60. data/lib/dynomite/item/query/partiql.rb +67 -0
  61. data/lib/dynomite/item/query/relation/chain.rb +125 -0
  62. data/lib/dynomite/item/query/relation/comparision_expression.rb +21 -0
  63. data/lib/dynomite/item/query/relation/comparision_map.rb +19 -0
  64. data/lib/dynomite/item/query/relation/delete.rb +38 -0
  65. data/lib/dynomite/item/query/relation/ids.rb +21 -0
  66. data/lib/dynomite/item/query/relation/math.rb +19 -0
  67. data/lib/dynomite/item/query/relation/where_field.rb +32 -0
  68. data/lib/dynomite/item/query/relation/where_group.rb +78 -0
  69. data/lib/dynomite/item/query/relation.rb +127 -0
  70. data/lib/dynomite/item/query.rb +7 -0
  71. data/lib/dynomite/item/read/find.rb +196 -0
  72. data/lib/dynomite/item/read/find_with_event.rb +42 -0
  73. data/lib/dynomite/item/read.rb +90 -0
  74. data/lib/dynomite/item/sti.rb +43 -0
  75. data/lib/dynomite/item/table_namespace.rb +43 -0
  76. data/lib/dynomite/item/typecaster.rb +106 -0
  77. data/lib/dynomite/item/waiter_methods.rb +18 -0
  78. data/lib/dynomite/item/write/base.rb +15 -0
  79. data/lib/dynomite/item/write/delete_item.rb +14 -0
  80. data/lib/dynomite/item/write/put_item.rb +99 -0
  81. data/lib/dynomite/item/write/update_item.rb +73 -0
  82. data/lib/dynomite/item/write.rb +204 -0
  83. data/lib/dynomite/item.rb +113 -286
  84. data/lib/dynomite/migration/dsl/accessor.rb +19 -0
  85. data/lib/dynomite/migration/dsl/index/base.rb +42 -0
  86. data/lib/dynomite/migration/dsl/index/gsi.rb +59 -0
  87. data/lib/dynomite/migration/dsl/index/lsi.rb +27 -0
  88. data/lib/dynomite/migration/dsl/index.rb +72 -0
  89. data/lib/dynomite/migration/dsl/primary_key.rb +62 -0
  90. data/lib/dynomite/migration/dsl/provisioned_throughput.rb +38 -0
  91. data/lib/dynomite/migration/dsl.rb +89 -142
  92. data/lib/dynomite/migration/file_info.rb +28 -0
  93. data/lib/dynomite/migration/generator.rb +30 -16
  94. data/lib/dynomite/migration/helpers.rb +7 -0
  95. data/lib/dynomite/migration/internal/migrate/create_schema_migrations.rb +17 -0
  96. data/lib/dynomite/migration/internal/models/schema_migration.rb +6 -0
  97. data/lib/dynomite/migration/runner.rb +179 -0
  98. data/lib/dynomite/migration/templates/create_table.rb +7 -23
  99. data/lib/dynomite/migration/templates/delete_table.rb +7 -0
  100. data/lib/dynomite/migration/templates/update_table.rb +3 -18
  101. data/lib/dynomite/migration.rb +53 -10
  102. data/lib/dynomite/reserved_words.rb +13 -3
  103. data/lib/dynomite/seed.rb +13 -0
  104. data/lib/dynomite/types.rb +22 -0
  105. data/lib/dynomite/version.rb +1 -1
  106. data/lib/dynomite/waiter.rb +40 -0
  107. data/lib/dynomite.rb +11 -17
  108. data/lib/generators/application_item/application_item_generator.rb +30 -0
  109. data/lib/generators/application_item/templates/application_item.rb.tt +4 -0
  110. data/lib/jets/commands/dynamodb_command.rb +29 -0
  111. data/lib/jets/commands/help/generate.md +33 -0
  112. data/lib/jets/commands/help/migrate.md +3 -0
  113. metadata +201 -17
  114. data/docs/migrations/long-example.rb +0 -127
  115. data/docs/migrations/short-example.rb +0 -40
  116. data/lib/dynomite/db_config.rb +0 -121
  117. data/lib/dynomite/errors.rb +0 -15
  118. data/lib/dynomite/log.rb +0 -15
  119. data/lib/dynomite/migration/common.rb +0 -86
  120. data/lib/dynomite/migration/dsl/base_secondary_index.rb +0 -73
  121. data/lib/dynomite/migration/dsl/global_secondary_index.rb +0 -4
  122. data/lib/dynomite/migration/dsl/local_secondary_index.rb +0 -8
  123. data/lib/dynomite/migration/executor.rb +0 -38
@@ -0,0 +1,179 @@
1
+ require "timeout"
2
+ require_relative "internal/migrate/create_schema_migrations"
3
+ require_relative "internal/models/schema_migration"
4
+
5
+ class Dynomite::Migration
6
+ class Runner
7
+ include Dynomite::Item::WaiterMethods
8
+
9
+ def initialize(options={})
10
+ @options = options
11
+ Dynomite.config.log_level = :info unless ENV['DYNOMITE_DEBUG']
12
+ end
13
+
14
+ def run
15
+ puts "Running Dynomite migrations"
16
+ ensure_schema_migrations_exist!
17
+ clear_error_schema_migrations! if ENV['CLEAR_ERRORS']
18
+ check_for_migration_errors!
19
+ Dynomite::Migration::FileInfo.all_files.each do |path|
20
+ migrate(path)
21
+ end
22
+ end
23
+
24
+ def migrate(path)
25
+ # load migration class definition
26
+ # CreatePosts#up (up is called below)
27
+ file_info = FileInfo.new(path)
28
+
29
+ schema_migration = SchemaMigration.find_by(version: file_info.version)
30
+ if schema_migration
31
+ teriminal_statuses = %w[complete error]
32
+ if teriminal_statuses.include?(schema_migration.status)
33
+ return
34
+ else
35
+ action = with_timeout(message: "Timed out. You must respond within 60s.") do
36
+ uncompleted_migration_prompt(file_info, schema_migration)
37
+ end
38
+ end
39
+ end
40
+
41
+ case action
42
+ when :skip
43
+ return
44
+ when :delete
45
+ schema_migration.delete
46
+ when :completed
47
+ schema_migration.status = "completed"
48
+ schema_migration.save
49
+ return
50
+ when :exit
51
+ puts "Exiting"
52
+ exit
53
+ end
54
+
55
+ puts "Running migration: #{file_info.pretty_path}"
56
+ load path
57
+
58
+ # INSERT schema_migration table - in_progress
59
+ unless schema_migration
60
+ schema_migration = SchemaMigration.new(version: file_info.version, status: "in_progress", path: file_info.pretty_path)
61
+ schema_migration.save
62
+ end
63
+ start_time = Time.now
64
+
65
+ # Run actual migration
66
+ migration_class = file_info.migration_class
67
+ error_message = nil
68
+ begin
69
+ # Runs migration up command. Example:
70
+ # CreatePosts#up
71
+ # Migration#create_table
72
+ # Migration#execute (wait happens here)
73
+ migration_class.new.up # wait happens within create_table or update_table
74
+ rescue Aws::DynamoDB::Errors::ServiceError => error
75
+ puts "Unable to #{@method_name.to_s.gsub('_',' ')}: #{error.message}".color(:red)
76
+ error_message = error.message
77
+ end
78
+
79
+ # UPDATE schema_migrations table - complete status
80
+ if error_message
81
+ schema_migration.status = "error"
82
+ schema_migration.error_message = error_message
83
+ else
84
+ schema_migration.status = "complete"
85
+ end
86
+
87
+ schema_migration.time_took = (Time.now - start_time).to_i
88
+ schema_migration.save
89
+ # schema_migration.delete # HACK
90
+ puts "Time took: #{pretty_time_took(schema_migration.time_took)}"
91
+ exit 1 if error_message # otherwise continue to next migration file
92
+ end
93
+
94
+ def with_timeout(options={}, &block)
95
+ seconds = options[:seconds] || 60
96
+ message = options[:message] || "Timed out after #{seconds}s."
97
+ Timeout::timeout(seconds, &block)
98
+ rescue Timeout::Error => e
99
+ puts "#{e.class}: #{e.message}"
100
+ puts message
101
+ exit 1
102
+ end
103
+
104
+ def uncompleted_migration_prompt(file_info, schema_migration)
105
+ choice = nil
106
+ until %w[s d c e].include?(choice)
107
+ puts(<<~EOL)
108
+ The #{file_info.pretty_path} migration status is incomplete. Status: #{schema_migration.status}
109
+ This can happen and if it was interrupted by a CTRL-C.
110
+ Please check the migration to help determine what to do next.
111
+
112
+ Options:
113
+
114
+ s - skip and continue. leaves schema_migrations item as-is
115
+ d - delete and continue. deletes the schema_migrations item
116
+ c - mark as successful completed and continue. updates the schema_migrations item as completed.
117
+ e - exit
118
+
119
+ EOL
120
+ print "Choose an option (s/d/c/e): "
121
+ choice = $stdin.gets.strip
122
+ end
123
+
124
+ map = {
125
+ "s" => :skip,
126
+ "d" => :delete,
127
+ "c" => :completed,
128
+ "e" => :exit,
129
+ }
130
+ map[choice]
131
+ end
132
+
133
+ def ensure_schema_migrations_exist!
134
+ migration = CreateSchemaMigrations.new
135
+ return if migration.table_exist?(SchemaMigration.table_name)
136
+ puts "Creating #{SchemaMigration.table_name} table for the first time"
137
+ migration.up
138
+ end
139
+
140
+ def clear_error_schema_migrations!
141
+ SchemaMigration.warn_on_scan(false).where(status: "error").each do |schema_migration|
142
+ schema_migration.delete
143
+ puts "Deleted error schema_migration: #{schema_migration.path}"
144
+ end
145
+ end
146
+
147
+ def check_for_migration_errors!
148
+ errors = SchemaMigration.warn_on_scan(false).where(status: "error")
149
+ errors_info = SchemaMigration.warn_on_scan(false).where(status: "error").map do |schema_migration|
150
+ " #{schema_migration.path} - #{schema_migration.error_message}"
151
+ end.join("\n")
152
+ if errors.count > 0
153
+ puts <<~EOL
154
+ Found error migrations. Please review the migration erors fix before continuing.
155
+ You can clear them out manually by deleting them from the #{SchemaMigration.table_name} table.
156
+
157
+ #{errors_info}
158
+
159
+ You can also clear them with the following command:
160
+
161
+ CLEAR_ERRORS=1 jets dynamodb:migrate
162
+
163
+ EOL
164
+ exit 1
165
+ end
166
+ end
167
+
168
+ # http://stackoverflow.com/questions/4175733/convert-duration-to-hoursminutesseconds-or-similar-in-rails-3-or-ruby
169
+ def pretty_time_took(total_seconds)
170
+ minutes = (total_seconds / 60) % 60
171
+ seconds = total_seconds % 60
172
+ if total_seconds < 60
173
+ "#{seconds.to_i}s"
174
+ else
175
+ "#{minutes.to_i}m #{seconds.to_i}s"
176
+ end
177
+ end
178
+ end
179
+ end
@@ -1,33 +1,17 @@
1
1
  class <%= @migration_class_name %> < Dynomite::Migration
2
2
  def up
3
3
  create_table :<%= @table_name %> do |t|
4
- t.partition_key "<%= @partition_key %>" # required
4
+ t.partition_key :<%= @partition_key %>
5
5
  <% if @sort_key # so extra spaces are not added when generated -%>
6
6
  t.sort_key "<%= @sort_key %>" # optional
7
7
  <% end -%>
8
- t.billing_mode(:PROVISIONED)
9
- t.provisioned_throughput(<%= @provisioned_throughput %>) # sets both read and write, defaults to 5 when not set
10
-
11
- # Instead of using partition_key and sort_key you can set the
12
- # key schema directly also
13
- # t.key_schema([
14
- # {attribute_name: "id", :key_type=>"HASH"},
15
- # {attribute_name: "created_at", :key_type=>"RANGE"}
16
- # ])
17
- # t.attribute_definitions([
18
- # {attribute_name: "id", attribute_type: "N"},
19
- # {attribute_name: "created_at", attribute_type: "S"}
20
- # ])
21
-
22
- # other ways to set provisioned_throughput
23
- # t.provisioned_throughput(:read, 10)
24
- # t.provisioned_throughput(:write, 10)
25
- # t.provisioned_throughput(
26
- # read_capacity_units: 5,
27
- # write_capacity_units: 5
28
- # )
8
+ <% if %w[id id:string].include?(@partition_key) -%>
9
+ t.add_gsi :updated_at
10
+ <% else %>
11
+ t.add_gsi :id
12
+ <% end -%>
29
13
  end
30
14
  end
31
15
  end
32
16
 
33
- # More examples: https://github.com/tongueroo/dynomite/tree/master/docs
17
+ # More examples: https://rubyonjets.com/docs/database/dynamodb/migration/
@@ -0,0 +1,7 @@
1
+ class <%= @migration_class_name %> < Dynomite::Migration
2
+ def up
3
+ delete_table :<%= @table_name %>
4
+ end
5
+ end
6
+
7
+ # More examples: https://rubyonjets.com/docs/database/dynamodb/migration/
@@ -1,26 +1,11 @@
1
1
  class <%= @migration_class_name %> < Dynomite::Migration
2
2
  def up
3
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 -%>
4
+ t.add_gsi(partition_key: "<%= @partition_key %>", sort_key: "<%= @sort_key || 'updated_at' %>")
9
5
 
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.
6
+ # t.remove_gsi(partition_key: "<%= @partition_key %>", sort_key: "<%= @sort_key || 'updated_at' %>")
22
7
  end
23
8
  end
24
9
  end
25
10
 
26
- # More examples: https://github.com/tongueroo/dynomite/tree/master/docs
11
+ # More examples: https://rubyonjets.com/docs/database/dynamodb/migration/
@@ -1,27 +1,70 @@
1
1
  module Dynomite
2
2
  class Migration
3
- autoload :Dsl, "dynomite/migration/dsl"
4
- autoload :Generator, "dynomite/migration/generator"
5
- autoload :Executor, "dynomite/migration/executor"
3
+ include Item::WaiterMethods
4
+ include Dynomite::Client
5
+ include Helpers
6
6
 
7
7
  def up
8
8
  puts "Should defined an up method for your migration: #{self.class.name}"
9
9
  end
10
10
 
11
11
  def create_table(table_name, &block)
12
- execute_with_dsl_params(table_name, :create_table, &block)
12
+ execute(table_name, :create_table, &block)
13
13
  end
14
14
 
15
15
  def update_table(table_name, &block)
16
- execute_with_dsl_params(table_name, :update_table, &block)
16
+ execute(table_name, :update_table, &block)
17
17
  end
18
18
 
19
+ def delete_table(table_name, &block)
20
+ execute(table_name, :delete_table, &block)
21
+ end
22
+
23
+ def add_gsi(table_name, *args)
24
+ update_table(table_name) do |t|
25
+ t.add_gsi(*args)
26
+ end
27
+ end
28
+
29
+ def remove_gsi(table_name, *args)
30
+ update_table(table_name) do |t|
31
+ t.remove_gsi(*args)
32
+ end
33
+ end
34
+
35
+ def update_gsi(table_name, *args)
36
+ update_table(table_name) do |t|
37
+ t.update_gsi(*args)
38
+ end
39
+ end
40
+
41
+ def update_time_to_live(table_name, time_to_live_specification={})
42
+ table_name = table_name_with_namespace(table_name)
43
+ client.update_time_to_live(
44
+ table_name: table_name,
45
+ time_to_live_specification: time_to_live_specification
46
+ )
47
+ # fast enough of an operation, no need to wait
48
+ end
49
+ alias update_ttl update_time_to_live
50
+
19
51
  private
20
- def execute_with_dsl_params(table_name, method_name, &block)
21
- dsl = Dsl.new(method_name, table_name, &block)
22
- params = dsl.params
23
- executor = Executor.new(table_name, method_name, params)
24
- executor.run
52
+ # execute with dsl params
53
+ # table name is short name and params[:table_name] is full namespaced name
54
+ def execute(table_name, method_name, &block)
55
+ params = Dsl.new(method_name, table_name, &block).params
56
+
57
+ puts "Running #{method_name} with:"
58
+ pp params
59
+ resp = client.send(method_name, params)
60
+ namespaced_table_name = params[:table_name] # full: demo-dev_posts short: posts
61
+ puts "DynamoDB Table: #{namespaced_table_name} Status: #{resp.table_description.table_status}"
62
+
63
+ if method_name.to_sym == :delete_table # already sym, to_sym just in case
64
+ waiter.wait_for_delete(params[:table_name])
65
+ else # create_table or update_table
66
+ waiter.wait(params[:table_name])
67
+ end
25
68
  end
26
69
  end
27
70
  end
@@ -1,18 +1,28 @@
1
1
  module Dynomite
2
2
  RESERVED_WORDS = %w[
3
3
  as_json
4
- attrs
5
4
  attributes
6
- delete
5
+ attrs
7
6
  columns
7
+ destroy
8
+ fields
8
9
  find
9
10
  getter
11
+ hash_key
12
+ hash_key_field
13
+ key_schema
10
14
  new_record
11
15
  param_name
12
16
  partition_key
17
+ partition_key_field
18
+ range_key
19
+ range_key_field
13
20
  replace
14
- setter
21
+ save
15
22
  scan
23
+ setter
24
+ sort_key_field
25
+ sort_key_field_field
16
26
  table_name
17
27
  ].freeze
18
28
  end
@@ -0,0 +1,13 @@
1
+ module Dynomite
2
+ class Seed
3
+ def initialize(options={})
4
+ @options = options
5
+ Dynomite.config.log_level = :info unless ENV['DYNOMITE_DEBUG']
6
+ end
7
+
8
+ def run
9
+ file = "dynamodb/seeds.rb"
10
+ load(file) if File.exist?(file)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ module Dynomite
2
+ module Types
3
+ TYPE_MAP = {
4
+ string: 'S',
5
+ number: 'N',
6
+ binary: 'B',
7
+ boolean: 'BOOL',
8
+ null: 'NULL',
9
+ map: 'M',
10
+ list: 'L',
11
+ string_set: 'SS',
12
+ number_set: 'NS',
13
+ binary_set: 'BS',
14
+ }
15
+
16
+ # https://rubyonjets.com/docs/database/dynamodb/types/
17
+ # https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypeDescriptors
18
+ def type_map(attribute_type)
19
+ TYPE_MAP[attribute_type.to_s.downcase.to_sym] || attribute_type
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module Dynomite
2
- VERSION = "1.2.7"
2
+ VERSION = "2.0.1"
3
3
  end
@@ -0,0 +1,40 @@
1
+ module Dynomite
2
+ class Waiter
3
+ include Client
4
+
5
+ def wait(table_name)
6
+ logger.info "Waiting for #{table_name} table to be ready."
7
+ statuses = [:initial]
8
+ until statuses.all? { |s| s == "ACTIVE" } do
9
+ resp = client.describe_table(table_name: table_name)
10
+
11
+ table = resp.table
12
+ # table_status: CREATING UPDATING DELETING ACTIVE INACCESSIBLE_ENCRYPTION_CREDENTIALS ARCHIVING ARCHIVED
13
+ table_status = table.table_status
14
+ statuses = [table_status]
15
+ # index_status: CREATING UPDATING DELETING ACTIVE
16
+ indexes = table.global_secondary_indexes || []
17
+ statuses += indexes.map { |i| i.index_status }
18
+ print '.'
19
+ sleep pause_time
20
+ end
21
+ puts
22
+ end
23
+
24
+ def wait_for_delete(table_name)
25
+ logger.info "Waiting for #{table_name} table to be deleted."
26
+ begin
27
+ client.describe_table(table_name: table_name)
28
+ print '.'
29
+ sleep pause_time
30
+ rescue Aws::DynamoDB::Errors::ResourceNotFoundException => e
31
+ end
32
+ puts
33
+ end
34
+
35
+ private
36
+ def pause_time
37
+ 1
38
+ end
39
+ end
40
+ end
data/lib/dynomite.rb CHANGED
@@ -1,25 +1,19 @@
1
1
  $:.unshift(File.expand_path("../", __FILE__))
2
+ require "active_support"
3
+ require "active_support/concern"
4
+ require "active_support/core_ext/hash"
5
+ require "active_support/core_ext/string"
2
6
  require "dynomite/version"
7
+ require "memoist"
3
8
  require "rainbow/ext/string"
4
9
 
5
- module Dynomite
6
- ATTRIBUTE_TYPES = {
7
- 'string' => 'S',
8
- 'number' => 'N',
9
- 'binary' => 'B',
10
- 's' => 'S',
11
- 'n' => 'N',
12
- 'b' => 'B',
13
- }
10
+ require "dynomite/autoloader"
11
+ Dynomite::Autoloader.setup
14
12
 
15
- autoload :Migration, "dynomite/migration"
16
- autoload :Dsl, "dynomite/dsl"
17
- autoload :DbConfig, "dynomite/db_config"
18
- autoload :Item, "dynomite/item"
19
- autoload :Core, "dynomite/core"
20
- autoload :Erb, "dynomite/erb"
21
- autoload :Log, "dynomite/log"
22
- autoload :Errors, "dynomite/errors"
13
+ require "dynomite/reserved_words"
23
14
 
15
+ module Dynomite
24
16
  extend Core
25
17
  end
18
+
19
+ require "dynomite/engine" if defined?(Jets)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ # Note: Currently have to use the Rails namespace to allow the Rails generator lookup to work.
6
+ # Would like to figure how to use Dynomite as the namespace instead
7
+ # Usage:
8
+ # jets generate application_item
9
+ module Rails
10
+ module Generators
11
+ class ApplicationItemGenerator < Rails::Generators::Base
12
+ source_root File.expand_path("templates", __dir__)
13
+
14
+ # FIXME: Change this file to a symlink once RubyGems 2.5.0 is required.
15
+ def create_application_item
16
+ template "application_item.rb", application_item_file_name
17
+ end
18
+
19
+ private
20
+ def application_item_file_name
21
+ @application_item_file_name ||=
22
+ if namespaced?
23
+ "app/models/#{namespaced_path}/application_item.rb"
24
+ else
25
+ "app/models/application_item.rb"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,4 @@
1
+ <% module_namespacing do -%>
2
+ class ApplicationItem < Dynomite::Item
3
+ end
4
+ <% end -%>
@@ -0,0 +1,29 @@
1
+ require "dynomite"
2
+
3
+ module Jets::Command
4
+ class Dynamodb < Base
5
+ desc "migrate", "Runs migrations"
6
+ long_desc Help.text('dynamodb:migrate')
7
+ def migrate
8
+ Jets.boot
9
+ Dynomite::Migration::Runner.new(options).run
10
+ end
11
+
12
+ desc "generate NAME", "Creates a migration for a DynamoDB table"
13
+ long_desc Help.text('dynamodb:generate')
14
+ option :action, desc: "create_table, update_table, delete_table. Defaults to convention based on the name of the migration."
15
+ option :partition_key, default: "id", desc: "table's partition key"
16
+ option :sort_key, default: nil, desc: "table's sort key"
17
+ option :table_name, desc: "override the the conventional table name"
18
+ def generate(name)
19
+ Dynomite::Migration::Generator.new(name, options).generate
20
+ end
21
+
22
+ desc "seed", "Seed data"
23
+ long_desc Help.text('dynamodb:seed')
24
+ def seed
25
+ Jets.boot
26
+ Dynomite::Seed.new(options).run
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ ## Examples
2
+
3
+ jets dynamodb:generate create_products --partition-key category --sort-key product_id:number
4
+ jets dynamodb:generate create_comments --partition-key post_id:string --sort-key created_at:string
5
+ jets dynamodb:generate create_posts --partition-key id # default attribute type is string
6
+ jets dynamodb:generate create_posts --partition-key id:number # attribute type will be number
7
+
8
+ ## Running migrations
9
+
10
+ $ jets dynamodb:migrate
11
+
12
+ To add global secondary indexes:
13
+
14
+ $ jets dynamodb:generate update_comments --partition-key user_id:string --sort-key created_at:string
15
+
16
+ To run:
17
+
18
+ $ jets dynamodb:migrate
19
+
20
+ ## Conventions
21
+
22
+ A create_table or update_table migration file is generated based name you provide. If `update` is included in the name then an update_table migration table is generated. If `create` is included in the name then a create_table migration table is generated.
23
+
24
+ The table_name is also inferred from the migration name you provide. Examples:
25
+
26
+ $ jets dynamodb:generate create_posts # table_name: posts
27
+ $ jets dynamodb:generate update_comments # table_name: comments
28
+
29
+ You can override both of these conventions:
30
+
31
+ $ jets dynamodb:generate create_my_posts --table-name posts
32
+ $ jets dynamodb:generate my_posts --action create_table --table-name posts
33
+ $ jets dynamodb:generate my_posts --action update_table --table-name posts
@@ -0,0 +1,3 @@
1
+ ## Examples
2
+
3
+ jets dynamodb:migrate