aws-sdk-rails 4.1.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +239 -0
  3. data/LICENSE.txt +12 -0
  4. data/VERSION +1 -1
  5. data/lib/aws/rails/action_mailbox/rspec.rb +6 -65
  6. data/lib/aws/rails/middleware/elastic_beanstalk_sqsd.rb +134 -0
  7. data/lib/aws/rails/notifications.rb +3 -6
  8. data/lib/aws/rails/railtie.rb +39 -40
  9. data/lib/aws-sdk-rails.rb +16 -8
  10. metadata +26 -152
  11. data/app/controllers/action_mailbox/ingresses/ses/inbound_emails_controller.rb +0 -79
  12. data/bin/aws_sqs_active_job +0 -6
  13. data/config/routes.rb +0 -8
  14. data/lib/action_dispatch/session/dynamodb_store.rb +0 -38
  15. data/lib/active_job/queue_adapters/sqs_adapter/params.rb +0 -78
  16. data/lib/active_job/queue_adapters/sqs_adapter.rb +0 -58
  17. data/lib/active_job/queue_adapters/sqs_async_adapter.rb +0 -39
  18. data/lib/aws/rails/action_mailbox/engine.rb +0 -21
  19. data/lib/aws/rails/action_mailbox/rspec/email.rb +0 -50
  20. data/lib/aws/rails/action_mailbox/rspec/subscription_confirmation.rb +0 -37
  21. data/lib/aws/rails/action_mailbox/s3_client.rb +0 -28
  22. data/lib/aws/rails/action_mailbox/sns_message_verifier.rb +0 -18
  23. data/lib/aws/rails/action_mailbox/sns_notification.rb +0 -99
  24. data/lib/aws/rails/middleware/ebs_sqs_active_job_middleware.rb +0 -118
  25. data/lib/aws/rails/ses_mailer.rb +0 -49
  26. data/lib/aws/rails/sesv2_mailer.rb +0 -60
  27. data/lib/aws/rails/sqs_active_job/configuration.rb +0 -184
  28. data/lib/aws/rails/sqs_active_job/deduplication.rb +0 -21
  29. data/lib/aws/rails/sqs_active_job/executor.rb +0 -77
  30. data/lib/aws/rails/sqs_active_job/job_runner.rb +0 -27
  31. data/lib/aws/rails/sqs_active_job/lambda_handler.rb +0 -63
  32. data/lib/aws/rails/sqs_active_job/poller.rb +0 -160
  33. data/lib/aws/rails/sqs_active_job.rb +0 -33
  34. data/lib/generators/aws_record/base.rb +0 -213
  35. data/lib/generators/aws_record/generated_attribute.rb +0 -138
  36. data/lib/generators/aws_record/model/USAGE +0 -24
  37. data/lib/generators/aws_record/model/model_generator.rb +0 -25
  38. data/lib/generators/aws_record/model/templates/model.erb +0 -48
  39. data/lib/generators/aws_record/model/templates/table_config.erb +0 -18
  40. data/lib/generators/aws_record/secondary_index.rb +0 -66
  41. data/lib/generators/dynamo_db/session_store_migration/USAGE +0 -13
  42. data/lib/generators/dynamo_db/session_store_migration/session_store_migration_generator.rb +0 -48
  43. data/lib/generators/dynamo_db/session_store_migration/templates/dynamo_db_session_store.yml +0 -70
  44. data/lib/generators/dynamo_db/session_store_migration/templates/session_store_migration.erb +0 -9
  45. data/lib/tasks/aws_record/migrate.rake +0 -14
  46. data/lib/tasks/dynamo_db/session_store.rake +0 -10
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aws
4
- module Rails
5
- module SqsActiveJob
6
- # @api private
7
- class JobRunner
8
- attr_reader :id, :class_name
9
-
10
- def initialize(message)
11
- @job_data = Aws::Json.load(message.data.body)
12
- @class_name = @job_data['job_class'].constantize
13
- @id = @job_data['job_id']
14
- end
15
-
16
- def run
17
- ActiveJob::Base.execute @job_data
18
- end
19
-
20
- def exception_executions?
21
- @job_data['exception_executions'] &&
22
- !@job_data['exception_executions'].empty?
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'aws-sdk-sqs'
4
-
5
- module Aws
6
- module Rails
7
- # A lambda event handler to run jobs from an SQS queue trigger
8
- # Trigger the lambda from your SQS queue
9
- # Configure the entrypoint to: +config/environment.Aws::Rails::SqsActiveJob.lambda_job_handler+
10
- # This will load your Rails environment, and then use this method as the handler.
11
- module SqsActiveJob
12
- def self.lambda_job_handler(event:, context:)
13
- return 'no records to process' unless event['Records']
14
-
15
- event['Records'].each do |record|
16
- sqs_msg = to_sqs_msg(record)
17
- job = Aws::Rails::SqsActiveJob::JobRunner.new(sqs_msg)
18
- puts("Running job: #{job.id}[#{job.class_name}]")
19
- job.run
20
- sqs_msg.delete
21
- end
22
- "Processed #{event['Records'].length} jobs."
23
- end
24
-
25
- def self.to_sqs_msg(record)
26
- msg = Aws::SQS::Types::Message.new(
27
- body: record['body'],
28
- md5_of_body: record['md5OfBody'],
29
- message_attributes: to_message_attributes(record),
30
- message_id: record['messageId'],
31
- receipt_handle: record['receiptHandle']
32
- )
33
- Aws::SQS::Message.new(
34
- queue_url: to_queue_url(record),
35
- receipt_handle: msg.receipt_handle,
36
- data: msg,
37
- client: Aws::Rails::SqsActiveJob.config.client
38
- )
39
- end
40
-
41
- def self.to_message_attributes(record)
42
- record['messageAttributes'].transform_values do |value|
43
- {
44
- string_value: value['stringValue'],
45
- binary_value: value['binaryValue'],
46
- string_list_values: ['stringListValues'],
47
- binary_list_values: value['binaryListValues'],
48
- data_type: value['dataType']
49
- }
50
- end
51
- end
52
-
53
- def self.to_queue_url(record)
54
- source_arn = record['eventSourceARN']
55
- raise ArgumentError, "Invalid queue arn: #{source_arn}" unless Aws::ARNParser.arn?(source_arn)
56
-
57
- arn = Aws::ARNParser.parse(source_arn)
58
- sfx = Aws::Partitions::EndpointProvider.dns_suffix_for(arn.region)
59
- "https://sqs.#{arn.region}.#{sfx}/#{arn.account_id}/#{arn.resource}"
60
- end
61
- end
62
- end
63
- end
@@ -1,160 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'aws-sdk-sqs'
4
- require 'optparse'
5
- require 'concurrent'
6
-
7
- module Aws
8
- module Rails
9
- module SqsActiveJob
10
- class Interrupt < StandardError; end
11
-
12
- # CLI runner for polling for SQS ActiveJobs
13
- # Use `aws_sqs_active_job --help` for detailed usage
14
- class Poller
15
- DEFAULT_OPTS = {
16
- threads: 2 * Concurrent.processor_count,
17
- max_messages: 10,
18
- shutdown_timeout: 15,
19
- backpressure: 10,
20
- retry_standard_errors: true
21
- }.freeze
22
-
23
- def initialize(args = ARGV)
24
- @options = parse_args(args)
25
- # Set_environment must be run before we boot_rails
26
- set_environment
27
- end
28
-
29
- def set_environment
30
- @environment = @options[:environment] || ENV['APP_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
31
- end
32
-
33
- def run
34
- # exit 0
35
- boot_rails
36
-
37
- # cannot load config (from file or initializers) until after
38
- # rails has been booted.
39
- @options = DEFAULT_OPTS
40
- .merge(Aws::Rails::SqsActiveJob.config.to_h)
41
- .merge(@options.to_h)
42
- validate_config
43
- # ensure we have a logger configured
44
- @logger = @options[:logger] || ActiveSupport::Logger.new($stdout)
45
- @logger.info("Starting Poller with options=#{@options}")
46
-
47
- Signal.trap('INT') { raise Interrupt }
48
- Signal.trap('TERM') { raise Interrupt }
49
- @executor = Executor.new(
50
- max_threads: @options[:threads],
51
- logger: @logger,
52
- max_queue: @options[:backpressure],
53
- retry_standard_errors: @options[:retry_standard_errors]
54
- )
55
-
56
- poll
57
- rescue Interrupt
58
- @logger.info 'Process Interrupted or killed - attempting to shutdown cleanly.'
59
- shutdown
60
- exit
61
- end
62
-
63
- private
64
-
65
- def shutdown
66
- @executor.shutdown(@options[:shutdown_timeout])
67
- end
68
-
69
- def poll
70
- queue_url = Aws::Rails::SqsActiveJob.config.queue_url_for(@options[:queue])
71
- @logger.info "Polling on: #{@options[:queue]} => #{queue_url}"
72
- client = Aws::Rails::SqsActiveJob.config.client
73
- @poller = Aws::SQS::QueuePoller.new(queue_url, client: client)
74
- poller_options = {
75
- skip_delete: true,
76
- max_number_of_messages: @options[:max_messages],
77
- visibility_timeout: @options[:visibility_timeout]
78
- }
79
- # Limit max_number_of_messages for FIFO queues to 1
80
- # this ensures jobs with the same message_group_id are processed
81
- # in order
82
- # Jobs with different message_group_id will be processed in
83
- # parallel and may be out of order.
84
- poller_options[:max_number_of_messages] = 1 if Aws::Rails::SqsActiveJob.fifo?(queue_url)
85
-
86
- single_message = poller_options[:max_number_of_messages] == 1
87
-
88
- @poller.poll(poller_options) do |msgs|
89
- msgs = [msgs] if single_message
90
- @logger.info "Processing batch of #{msgs.length} messages"
91
- msgs.each do |msg|
92
- @executor.execute(Aws::SQS::Message.new(
93
- queue_url: queue_url,
94
- receipt_handle: msg.receipt_handle,
95
- data: msg,
96
- client: client
97
- ))
98
- end
99
- end
100
- end
101
-
102
- def boot_rails
103
- ENV['RACK_ENV'] = ENV['RAILS_ENV'] = @environment
104
- require 'rails'
105
- require File.expand_path('config/environment.rb')
106
- end
107
-
108
- # rubocop:disable Metrics
109
- def parse_args(argv)
110
- out = {}
111
- parser = ::OptionParser.new do |opts|
112
- opts.on('-q', '--queue STRING', '[Required] Queue to poll') { |a| out[:queue] = a }
113
- opts.on('-e', '--environment STRING',
114
- 'Rails environment (defaults to development). You can also use the APP_ENV or RAILS_ENV environment variables to specify the environment.') do |a|
115
- out[:environment] = a
116
- end
117
- opts.on('-t', '--threads INTEGER', Integer,
118
- 'The maximum number of worker threads to create. Defaults to 2x the number of processors available on this system.') do |a|
119
- out[:threads] = a
120
- end
121
- opts.on('-b', '--backpressure INTEGER', Integer,
122
- 'The maximum number of messages to have waiting in the Executor queue. This should be a low, but non zero number. Messages in the Executor queue cannot be picked up by other processes and will slow down shutdown.') do |a|
123
- out[:backpressure] = a
124
- end
125
- opts.on('-m', '--max_messages INTEGER', Integer,
126
- 'Max number of messages to receive in a batch from SQS.') do |a|
127
- out[:max_messages] = a
128
- end
129
- opts.on('-v', '--visibility_timeout INTEGER', Integer,
130
- 'The visibility timeout is the number of seconds that a message will not be processable by any other consumers. You should set this value to be longer than your expected job runtime to prevent other processes from picking up an running job. See the SQS Visibility Timeout Documentation at https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html.') do |a|
131
- out[:visibility_timeout] = a
132
- end
133
- opts.on('-s', '--shutdown_timeout INTEGER', Integer,
134
- 'The amount of time to wait for a clean shutdown. Jobs that are unable to complete in this time will not be deleted from the SQS queue and will be retryable after the visibility timeout.') do |a|
135
- out[:shutdown_timeout] = a
136
- end
137
- opts.on('--[no-]retry_standard_errors [FLAG]', TrueClass,
138
- 'When set, retry all StandardErrors (leaving failed messages on the SQS Queue). These retries are ON TOP of standard Rails ActiveJob retries set by retry_on in the ActiveJob.') do |a|
139
- out[:retry_standard_errors] = a.nil? ? true : a
140
- end
141
- end
142
-
143
- parser.banner = 'aws_sqs_active_job [options]'
144
- parser.on_tail '-h', '--help', 'Show help' do
145
- puts parser
146
- exit 1
147
- end
148
-
149
- parser.parse(argv)
150
- out
151
- end
152
- # rubocop:enable Metrics
153
-
154
- def validate_config
155
- raise ArgumentError, 'You must specify the name of the queue to process jobs from' unless @options[:queue]
156
- end
157
- end
158
- end
159
- end
160
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../active_job/queue_adapters/sqs_adapter'
4
- require_relative '../../active_job/queue_adapters/sqs_adapter/params'
5
- require_relative '../../active_job/queue_adapters/sqs_async_adapter'
6
- require_relative 'sqs_active_job/configuration'
7
- require_relative 'sqs_active_job/deduplication'
8
- require_relative 'sqs_active_job/executor'
9
- require_relative 'sqs_active_job/job_runner'
10
- require_relative 'sqs_active_job/lambda_handler'
11
-
12
- module Aws
13
- module Rails
14
- # == AWS SQS ActiveJob.
15
- #
16
- # SQS-based queuing backend for Active Job.
17
- module SqsActiveJob
18
- # @return [Configuration] the (singleton) Configuration
19
- def self.config
20
- @config ||= Configuration.new
21
- end
22
-
23
- # @yield Configuration
24
- def self.configure
25
- yield(config)
26
- end
27
-
28
- def self.fifo?(queue_url)
29
- queue_url.ends_with? '.fifo'
30
- end
31
- end
32
- end
33
- end
@@ -1,213 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
- require_relative 'generated_attribute'
5
- require_relative 'secondary_index'
6
-
7
- module AwsRecord
8
- module Generators
9
- class Base < Rails::Generators::NamedBase
10
- argument :attributes, type: :array, default: [], banner: 'field[:type][:opts]...',
11
- desc: 'Describes the fields in the model'
12
- check_class_collision
13
-
14
- class_option :disable_mutation_tracking, type: :boolean, desc: 'Disables dirty tracking'
15
- class_option :timestamps, type: :boolean, desc: 'Adds created, updated timestamps to the model'
16
- class_option :table_config, type: :hash, default: {}, banner: 'primary:R-W [SecondaryIndex1:R-W]...',
17
- desc: 'Declares the r/w units for the model as well as any secondary indexes', required: true
18
- class_option :gsi, type: :array, default: [],
19
- banner: 'name:hkey{field_name}[,rkey{field_name},proj_type{ALL|KEYS_ONLY|INCLUDE}]...', desc: 'Allows for the declaration of secondary indexes'
20
- class_option :table_name, type: :string, banner: 'model_table_name'
21
- class_option :password_digest, type: :boolean, desc: 'Whether to add a password_digest field to the model'
22
-
23
- class_option :required, type: :string, banner: 'field1...',
24
- desc: 'A list of attributes that are required for an instance of the model'
25
- class_option :length_validations, type: :hash, default: {}, banner: 'field1:MIN-MAX...',
26
- desc: 'Validations on the length of attributes in a model'
27
-
28
- attr_accessor :primary_read_units, :primary_write_units, :gsi_rw_units, :gsis, :required_attrs,
29
- :length_validations
30
-
31
- private
32
-
33
- def initialize(args, *options)
34
- options[0] << '--skip-table-config' if options[1][:behavior] == :revoke
35
- @parse_errors = []
36
-
37
- super
38
- ensure_unique_fields
39
- ensure_hkey
40
- parse_gsis!
41
- parse_table_config!
42
- parse_validations!
43
-
44
- return if @parse_errors.empty?
45
-
46
- warn 'The following errors were encountered while trying to parse the given attributes'
47
- $stderr.puts
48
- warn @parse_errors
49
- $stderr.puts
50
-
51
- abort('Please fix the errors before proceeding.')
52
- end
53
-
54
- def parse_attributes!
55
- self.attributes = (attributes || []).map do |attr|
56
- GeneratedAttribute.parse(attr)
57
- rescue ArgumentError => e
58
- @parse_errors << e
59
- next
60
- end
61
- self.attributes = attributes.compact
62
-
63
- if options['password_digest']
64
- attributes << GeneratedAttribute.new('password_digest', :string_attr, digest: true)
65
- end
66
-
67
- return unless options['timestamps']
68
-
69
- attributes << GeneratedAttribute.parse('created:datetime:default_value{Time.now}')
70
- attributes << GeneratedAttribute.parse('updated:datetime:default_value{Time.now}')
71
- end
72
-
73
- def ensure_unique_fields
74
- used_names = Set.new
75
- duplicate_fields = []
76
-
77
- attributes.each do |attr|
78
- duplicate_fields << [:attribute, attr.name] if used_names.include? attr.name
79
- used_names.add attr.name
80
-
81
- next unless attr.options.key? :database_attribute_name
82
-
83
- raw_db_attr_name = attr.options[:database_attribute_name].delete('"') # db attribute names are wrapped with " to make template generation easier
84
-
85
- duplicate_fields << [:database_attribute_name, raw_db_attr_name] if used_names.include? raw_db_attr_name
86
-
87
- used_names.add raw_db_attr_name
88
- end
89
-
90
- return if duplicate_fields.empty?
91
-
92
- duplicate_fields.each do |invalid_attr|
93
- @parse_errors << ArgumentError.new("Found duplicated field name: #{invalid_attr[1]}, in attribute#{invalid_attr[0]}")
94
- end
95
- end
96
-
97
- def ensure_hkey
98
- uuid_member = nil
99
- hkey_member = nil
100
- rkey_member = nil
101
-
102
- attributes.each do |attr|
103
- if attr.options.key? :hash_key
104
- if hkey_member
105
- @parse_errors << ArgumentError.new("Redefinition of hash_key attr: #{attr.name}, original declaration of hash_key on: #{hkey_member.name}")
106
- next
107
- end
108
-
109
- hkey_member = attr
110
- elsif attr.options.key? :range_key
111
- if rkey_member
112
- @parse_errors << ArgumentError.new("Redefinition of range_key attr: #{attr.name}, original declaration of range_key on: #{hkey_member.name}")
113
- next
114
- end
115
-
116
- rkey_member = attr
117
- end
118
-
119
- uuid_member = attr if attr.name.include? 'uuid'
120
- end
121
-
122
- return if hkey_member
123
-
124
- if uuid_member
125
- uuid_member.options[:hash_key] = true
126
- else
127
- attributes.unshift GeneratedAttribute.parse('uuid:hkey')
128
- end
129
- end
130
-
131
- def mutation_tracking_disabled?
132
- options['disable_mutation_tracking']
133
- end
134
-
135
- def has_validations?
136
- !@required_attrs.empty? || !@length_validations.empty?
137
- end
138
-
139
- def parse_table_config!
140
- return unless options['table_config']
141
-
142
- @primary_read_units, @primary_write_units = parse_rw_units('primary')
143
-
144
- @gsi_rw_units = @gsis.to_h do |idx|
145
- [idx.name, parse_rw_units(idx.name)]
146
- end
147
-
148
- options['table_config'].each_key do |config|
149
- next if config == 'primary'
150
-
151
- gsi = @gsis.select { |idx| idx.name == config }
152
-
153
- @parse_errors << ArgumentError.new("Could not find a gsi declaration for #{config}") if gsi.empty?
154
- end
155
- end
156
-
157
- def parse_rw_units(name)
158
- if options['table_config'].key? name
159
- rw_units = options['table_config'][name]
160
- rw_units.gsub(/[,.-]/, ':').split(':').reject(&:empty?)
161
- else
162
- @parse_errors << ArgumentError.new("Please provide a table_config definition for #{name}")
163
- end
164
- end
165
-
166
- def parse_gsis!
167
- @gsis = (options['gsi'] || []).map do |raw_idx|
168
- idx = SecondaryIndex.parse(raw_idx)
169
-
170
- attributes = self.attributes.select { |attr| attr.name == idx.hash_key }
171
- if attributes.empty?
172
- @parse_errors << ArgumentError.new("Could not find attribute #{idx.hash_key} for gsi #{idx.name} hkey")
173
- next
174
- end
175
-
176
- if idx.range_key
177
- attributes = self.attributes.select { |attr| attr.name == idx.range_key }
178
- if attributes.empty?
179
- @parse_errors << ArgumentError.new("Could not find attribute #{idx.range_key} for gsi #{idx.name} rkey")
180
- next
181
- end
182
- end
183
-
184
- idx
185
- rescue ArgumentError => e
186
- @parse_errors << e
187
- next
188
- end
189
-
190
- @gsis = @gsis.compact
191
- end
192
-
193
- def parse_validations!
194
- @required_attrs = options['required'] ? options['required'].split(',') : []
195
- @required_attrs.each do |val_attr|
196
- @parse_errors << ArgumentError.new("No such field #{val_attr} in required validations") if attributes.none? do |attr|
197
- attr.name == val_attr
198
- end
199
- end
200
-
201
- @length_validations = options['length_validations'].map do |val_attr, bounds|
202
- @parse_errors << ArgumentError.new("No such field #{val_attr} in required validations") if attributes.none? do |attr|
203
- attr.name == val_attr
204
- end
205
-
206
- bounds = bounds.gsub(/[,.-]/, ':').split(':').reject(&:empty?)
207
- [val_attr, "#{bounds[0]}..#{bounds[1]}"]
208
- end
209
- @length_validations = @length_validations.to_h
210
- end
211
- end
212
- end
213
- end
@@ -1,138 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AwsRecord
4
- module Generators
5
- class GeneratedAttribute
6
- OPTS = %w[hkey rkey persist_nil db_attr_name ddb_type default_value].freeze
7
- INVALID_HKEY_TYPES = %i[map_attr list_attr numeric_set_attr string_set_attr].freeze
8
- attr_reader :name, :type
9
- attr_accessor :options
10
-
11
- def field_type
12
- case @type
13
- when :integer_attr then :number_field
14
- when :date_attr then :date_select
15
- when :datetime_attr then :datetime_select
16
- when :boolean_attr then :check_box
17
- else :text_field
18
- end
19
- end
20
-
21
- class << self
22
- def parse(field_definition)
23
- name, type, opts = field_definition.split(':')
24
- type ||= 'string'
25
- if OPTS.any? { |opt| type.include? opt }
26
- opts = type
27
- type = 'string'
28
- end
29
-
30
- opts = opts.split(',') if opts
31
- type, opts = parse_type_and_options(name, type, opts)
32
- validate_opt_combs(name, type, opts)
33
-
34
- new(name, type, opts)
35
- end
36
-
37
- private
38
-
39
- def validate_opt_combs(name, type, opts)
40
- return unless opts
41
-
42
- is_hkey = opts.key?(:hash_key)
43
- is_rkey = opts.key?(:range_key)
44
-
45
- if is_hkey && is_rkey
46
- raise ArgumentError,
47
- "Field #{name} cannot be a range key and hash key simultaneously"
48
- end
49
- return unless is_hkey && INVALID_HKEY_TYPES.include?(type)
50
-
51
- raise ArgumentError,
52
- "Field #{name} cannot be a hash key and be of type #{type}"
53
- end
54
-
55
- def parse_type_and_options(name, type, opts)
56
- opts ||= []
57
- [parse_type(name, type), opts.to_h { |opt| parse_option(name, opt) }]
58
- end
59
-
60
- def parse_option(name, opt)
61
- case opt
62
-
63
- when 'hkey'
64
- [:hash_key, true]
65
- when 'rkey'
66
- [:range_key, true]
67
- when 'persist_nil'
68
- [:persist_nil, true]
69
- when /db_attr_name\{(\w+)\}/
70
- [:database_attribute_name, "\"#{::Regexp.last_match(1)}\""]
71
- when /ddb_type\{(S|N|B|BOOL|SS|NS|BS|M|L)\}/i
72
- [:dynamodb_type, "\"#{::Regexp.last_match(1).upcase}\""]
73
- when /default_value\{(.+)\}/
74
- [:default_value, ::Regexp.last_match(1)]
75
- else
76
- raise ArgumentError, "You provided an invalid option for #{name}: #{opt}"
77
- end
78
- end
79
-
80
- def parse_type(name, type)
81
- case type.downcase
82
-
83
- when 'bool', 'boolean'
84
- :boolean_attr
85
- when 'date'
86
- :date_attr
87
- when 'datetime'
88
- :datetime_attr
89
- when 'float'
90
- :float_attr
91
- when 'int', 'integer'
92
- :integer_attr
93
- when 'list'
94
- :list_attr
95
- when 'map'
96
- :map_attr
97
- when 'num_set', 'numeric_set', 'nset'
98
- :numeric_set_attr
99
- when 'string_set', 's_set', 'sset'
100
- :string_set_attr
101
- when 'string'
102
- :string_attr
103
- else
104
- raise ArgumentError, "Invalid type for #{name}: #{type}"
105
- end
106
- end
107
- end
108
-
109
- def initialize(name, type = :string_attr, options = {})
110
- @name = name
111
- @type = type
112
- @options = options
113
- @digest = options.delete(:digest)
114
- end
115
-
116
- # Methods used by rails scaffolding
117
- def password_digest?
118
- @digest
119
- end
120
-
121
- def polymorphic?
122
- false
123
- end
124
-
125
- def column_name
126
- if @name == 'password_digest'
127
- 'password'
128
- else
129
- @name
130
- end
131
- end
132
-
133
- def human_name
134
- name.humanize
135
- end
136
- end
137
- end
138
- end
@@ -1,24 +0,0 @@
1
- Description:
2
- rails generator for aws-record models
3
-
4
- Pass the name of the model (preferably in singular form), and an optional list of attributes
5
-
6
- Attributes are declarations of the fields that you wish to store within a model. You can pass
7
- a type and list of options for each attribtue in the form: `name:type:options` if you do not provide
8
- a type, it is assumed that the attribute is of type `string_attr`
9
-
10
- Each model should have an hkey, if one is not present a `uuid:hkey` will be created for you.
11
-
12
- Timestamps are not added by default but you can add them using the `--timestamps` flag
13
- More information can be found at: https://github.com/awslabs/aws-record-generator/blob/master/README.md
14
-
15
- You don't have to think up every attribute up front, but it helps to
16
- sketch out a few so you can start working with the resource immediately.
17
-
18
- Example:
19
- rails generate aws_record:model Forum forum_uuid:hkey post_id:rkey post_title post_body tags:sset:default_value{Set.new} created_at:datetime:d_attr_name{PostCreatedAtTime} moderation:boolean:default_value{false}
20
-
21
- This will create:
22
- app/models/forum.rb
23
- db/table_config/forum_config.rb
24
- lib/tasks/table_config_migrate_task.rake # This is created once the first time the generator is run
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../base'
4
-
5
- module AwsRecord
6
- module Generators
7
- class ModelGenerator < Base
8
- def initialize(args, *options)
9
- self.class.source_root File.expand_path('templates', __dir__)
10
- super
11
- end
12
-
13
- def create_model
14
- template 'model.erb', File.join('app/models', class_path, "#{file_name}.rb")
15
- end
16
-
17
- def create_table_config
18
- return unless options['table_config']
19
-
20
- template 'table_config.erb',
21
- File.join('db/table_config', class_path, "#{file_name}_config.rb")
22
- end
23
- end
24
- end
25
- end