dynamoid 3.8.0 → 3.10.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -3
  3. data/README.md +111 -60
  4. data/SECURITY.md +17 -0
  5. data/dynamoid.gemspec +65 -0
  6. data/lib/dynamoid/adapter.rb +20 -13
  7. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +2 -2
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/execute_statement.rb +62 -0
  9. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/filter_expression_convertor.rb +78 -0
  10. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +28 -2
  11. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +3 -0
  12. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/projection_expression_convertor.rb +38 -0
  13. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +46 -61
  14. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +33 -27
  15. data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +116 -70
  16. data/lib/dynamoid/associations/belongs_to.rb +6 -6
  17. data/lib/dynamoid/associations.rb +1 -1
  18. data/lib/dynamoid/components.rb +2 -3
  19. data/lib/dynamoid/config/options.rb +12 -12
  20. data/lib/dynamoid/config.rb +1 -0
  21. data/lib/dynamoid/criteria/chain.rb +101 -138
  22. data/lib/dynamoid/criteria/key_fields_detector.rb +6 -7
  23. data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +2 -2
  24. data/lib/dynamoid/criteria/where_conditions.rb +29 -0
  25. data/lib/dynamoid/dirty.rb +57 -57
  26. data/lib/dynamoid/document.rb +39 -3
  27. data/lib/dynamoid/dumping.rb +2 -2
  28. data/lib/dynamoid/errors.rb +2 -0
  29. data/lib/dynamoid/fields/declare.rb +6 -6
  30. data/lib/dynamoid/fields.rb +9 -27
  31. data/lib/dynamoid/finders.rb +26 -30
  32. data/lib/dynamoid/indexes.rb +7 -10
  33. data/lib/dynamoid/loadable.rb +2 -2
  34. data/lib/dynamoid/log/formatter.rb +19 -4
  35. data/lib/dynamoid/persistence/import.rb +4 -1
  36. data/lib/dynamoid/persistence/inc.rb +66 -0
  37. data/lib/dynamoid/persistence/save.rb +55 -12
  38. data/lib/dynamoid/persistence/update_fields.rb +2 -2
  39. data/lib/dynamoid/persistence/update_validations.rb +2 -2
  40. data/lib/dynamoid/persistence.rb +128 -48
  41. data/lib/dynamoid/type_casting.rb +15 -14
  42. data/lib/dynamoid/undumping.rb +1 -1
  43. data/lib/dynamoid/version.rb +1 -1
  44. metadata +27 -49
  45. data/lib/dynamoid/criteria/ignored_conditions_detector.rb +0 -41
  46. data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +0 -40
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'aws_sdk_v3/query'
4
4
  require_relative 'aws_sdk_v3/scan'
5
+ require_relative 'aws_sdk_v3/execute_statement'
5
6
  require_relative 'aws_sdk_v3/create_table'
6
7
  require_relative 'aws_sdk_v3/batch_get_item'
7
8
  require_relative 'aws_sdk_v3/item_updater'
@@ -13,7 +14,7 @@ module Dynamoid
13
14
  module AdapterPlugin
14
15
  # The AwsSdkV3 adapter provides support for the aws-sdk version 2 for ruby.
15
16
 
16
- # Note: Don't use keyword arguments in public methods as far as method
17
+ # NOTE: Don't use keyword arguments in public methods as far as method
17
18
  # calls on adapter are delegated to the plugin.
18
19
  #
19
20
  # There are breaking changes in Ruby related to delegating keyword
@@ -23,31 +24,6 @@ module Dynamoid
23
24
 
24
25
  class AwsSdkV3
25
26
  EQ = 'EQ'
26
- RANGE_MAP = {
27
- range_greater_than: 'GT',
28
- range_less_than: 'LT',
29
- range_gte: 'GE',
30
- range_lte: 'LE',
31
- range_begins_with: 'BEGINS_WITH',
32
- range_between: 'BETWEEN',
33
- range_eq: 'EQ'
34
- }.freeze
35
-
36
- FIELD_MAP = {
37
- eq: 'EQ',
38
- ne: 'NE',
39
- gt: 'GT',
40
- lt: 'LT',
41
- gte: 'GE',
42
- lte: 'LE',
43
- begins_with: 'BEGINS_WITH',
44
- between: 'BETWEEN',
45
- in: 'IN',
46
- contains: 'CONTAINS',
47
- not_contains: 'NOT_CONTAINS',
48
- null: 'NULL',
49
- not_null: 'NOT_NULL',
50
- }.freeze
51
27
  HASH_KEY = 'HASH'
52
28
  RANGE_KEY = 'RANGE'
53
29
  STRING_TYPE = 'S'
@@ -69,26 +45,72 @@ module Dynamoid
69
45
 
70
46
  CONNECTION_CONFIG_OPTIONS = %i[endpoint region http_continue_timeout http_idle_timeout http_open_timeout http_read_timeout].freeze
71
47
 
72
- attr_reader :table_cache
48
+ # See https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html
49
+ # rubocop:disable Metrics/CollectionLiteralLength
50
+ RESERVED_WORDS = Set.new(
51
+ %i[
52
+ ABORT ABSOLUTE ACTION ADD AFTER AGENT AGGREGATE ALL ALLOCATE ALTER ANALYZE
53
+ AND ANY ARCHIVE ARE ARRAY AS ASC ASCII ASENSITIVE ASSERTION ASYMMETRIC AT
54
+ ATOMIC ATTACH ATTRIBUTE AUTH AUTHORIZATION AUTHORIZE AUTO AVG BACK BACKUP
55
+ BASE BATCH BEFORE BEGIN BETWEEN BIGINT BINARY BIT BLOB BLOCK BOOLEAN BOTH
56
+ BREADTH BUCKET BULK BY BYTE CALL CALLED CALLING CAPACITY CASCADE CASCADED
57
+ CASE CAST CATALOG CHAR CHARACTER CHECK CLASS CLOB CLOSE CLUSTER CLUSTERED
58
+ CLUSTERING CLUSTERS COALESCE COLLATE COLLATION COLLECTION COLUMN COLUMNS
59
+ COMBINE COMMENT COMMIT COMPACT COMPILE COMPRESS CONDITION CONFLICT CONNECT
60
+ CONNECTION CONSISTENCY CONSISTENT CONSTRAINT CONSTRAINTS CONSTRUCTOR
61
+ CONSUMED CONTINUE CONVERT COPY CORRESPONDING COUNT COUNTER CREATE CROSS
62
+ CUBE CURRENT CURSOR CYCLE DATA DATABASE DATE DATETIME DAY DEALLOCATE DEC
63
+ DECIMAL DECLARE DEFAULT DEFERRABLE DEFERRED DEFINE DEFINED DEFINITION
64
+ DELETE DELIMITED DEPTH DEREF DESC DESCRIBE DESCRIPTOR DETACH DETERMINISTIC
65
+ DIAGNOSTICS DIRECTORIES DISABLE DISCONNECT DISTINCT DISTRIBUTE DO DOMAIN
66
+ DOUBLE DROP DUMP DURATION DYNAMIC EACH ELEMENT ELSE ELSEIF EMPTY ENABLE
67
+ END EQUAL EQUALS ERROR ESCAPE ESCAPED EVAL EVALUATE EXCEEDED EXCEPT
68
+ EXCEPTION EXCEPTIONS EXCLUSIVE EXEC EXECUTE EXISTS EXIT EXPLAIN EXPLODE
69
+ EXPORT EXPRESSION EXTENDED EXTERNAL EXTRACT FAIL FALSE FAMILY FETCH FIELDS
70
+ FILE FILTER FILTERING FINAL FINISH FIRST FIXED FLATTERN FLOAT FOR FORCE
71
+ FOREIGN FORMAT FORWARD FOUND FREE FROM FULL FUNCTION FUNCTIONS GENERAL
72
+ GENERATE GET GLOB GLOBAL GO GOTO GRANT GREATER GROUP GROUPING HANDLER HASH
73
+ HAVE HAVING HEAP HIDDEN HOLD HOUR IDENTIFIED IDENTITY IF IGNORE IMMEDIATE
74
+ IMPORT IN INCLUDING INCLUSIVE INCREMENT INCREMENTAL INDEX INDEXED INDEXES
75
+ INDICATOR INFINITE INITIALLY INLINE INNER INNTER INOUT INPUT INSENSITIVE
76
+ INSERT INSTEAD INT INTEGER INTERSECT INTERVAL INTO INVALIDATE IS ISOLATION
77
+ ITEM ITEMS ITERATE JOIN KEY KEYS LAG LANGUAGE LARGE LAST LATERAL LEAD
78
+ LEADING LEAVE LEFT LENGTH LESS LEVEL LIKE LIMIT LIMITED LINES LIST LOAD
79
+ LOCAL LOCALTIME LOCALTIMESTAMP LOCATION LOCATOR LOCK LOCKS LOG LOGED LONG
80
+ LOOP LOWER MAP MATCH MATERIALIZED MAX MAXLEN MEMBER MERGE METHOD METRICS
81
+ MIN MINUS MINUTE MISSING MOD MODE MODIFIES MODIFY MODULE MONTH MULTI
82
+ MULTISET NAME NAMES NATIONAL NATURAL NCHAR NCLOB NEW NEXT NO NONE NOT NULL
83
+ NULLIF NUMBER NUMERIC OBJECT OF OFFLINE OFFSET OLD ON ONLINE ONLY OPAQUE
84
+ OPEN OPERATOR OPTION OR ORDER ORDINALITY OTHER OTHERS OUT OUTER OUTPUT
85
+ OVER OVERLAPS OVERRIDE OWNER PAD PARALLEL PARAMETER PARAMETERS PARTIAL
86
+ PARTITION PARTITIONED PARTITIONS PATH PERCENT PERCENTILE PERMISSION
87
+ PERMISSIONS PIPE PIPELINED PLAN POOL POSITION PRECISION PREPARE PRESERVE
88
+ PRIMARY PRIOR PRIVATE PRIVILEGES PROCEDURE PROCESSED PROJECT PROJECTION
89
+ PROPERTY PROVISIONING PUBLIC PUT QUERY QUIT QUORUM RAISE RANDOM RANGE RANK
90
+ RAW READ READS REAL REBUILD RECORD RECURSIVE REDUCE REF REFERENCE
91
+ REFERENCES REFERENCING REGEXP REGION REINDEX RELATIVE RELEASE REMAINDER
92
+ RENAME REPEAT REPLACE REQUEST RESET RESIGNAL RESOURCE RESPONSE RESTORE
93
+ RESTRICT RESULT RETURN RETURNING RETURNS REVERSE REVOKE RIGHT ROLE ROLES
94
+ ROLLBACK ROLLUP ROUTINE ROW ROWS RULE RULES SAMPLE SATISFIES SAVE SAVEPOINT
95
+ SCAN SCHEMA SCOPE SCROLL SEARCH SECOND SECTION SEGMENT SEGMENTS SELECT SELF
96
+ SEMI SENSITIVE SEPARATE SEQUENCE SERIALIZABLE SESSION SET SETS SHARD SHARE
97
+ SHARED SHORT SHOW SIGNAL SIMILAR SIZE SKEWED SMALLINT SNAPSHOT SOME SOURCE
98
+ SPACE SPACES SPARSE SPECIFIC SPECIFICTYPE SPLIT SQL SQLCODE SQLERROR
99
+ SQLEXCEPTION SQLSTATE SQLWARNING START STATE STATIC STATUS STORAGE STORE
100
+ STORED STREAM STRING STRUCT STYLE SUB SUBMULTISET SUBPARTITION SUBSTRING
101
+ SUBTYPE SUM SUPER SYMMETRIC SYNONYM SYSTEM TABLE TABLESAMPLE TEMP TEMPORARY
102
+ TERMINATED TEXT THAN THEN THROUGHPUT TIME TIMESTAMP TIMEZONE TINYINT TO
103
+ TOKEN TOTAL TOUCH TRAILING TRANSACTION TRANSFORM TRANSLATE TRANSLATION
104
+ TREAT TRIGGER TRIM TRUE TRUNCATE TTL TUPLE TYPE UNDER UNDO UNION UNIQUE UNIT
105
+ UNKNOWN UNLOGGED UNNEST UNPROCESSED UNSIGNED UNTIL UPDATE UPPER URL USAGE
106
+ USE USER USERS USING UUID VACUUM VALUE VALUED VALUES VARCHAR VARIABLE
107
+ VARIANCE VARINT VARYING VIEW VIEWS VIRTUAL VOID WAIT WHEN WHENEVER WHERE
108
+ WHILE WINDOW WITH WITHIN WITHOUT WORK WRAPPED WRITE YEAR ZONE
109
+ ]
110
+ ).freeze
111
+ # rubocop:enable Metrics/CollectionLiteralLength
73
112
 
74
- # Build an array of values for Condition
75
- # Is used in ScanFilter and QueryFilter
76
- # https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
77
- # @param [String] operator value of RANGE_MAP or FIELD_MAP hash, e.g. "EQ", "LT" etc
78
- # @param [Object] value scalar value or array/set
79
- def self.attribute_value_list(operator, value)
80
- # For BETWEEN and IN operators we should keep value as is (it should be already an array)
81
- # NULL and NOT_NULL require absence of attribute list
82
- # For all the other operators we wrap the value with array
83
- # https://docs.aws.amazon.com/en_us/amazondynamodb/latest/developerguide/LegacyConditionalParameters.Conditions.html
84
- if %w[BETWEEN IN].include?(operator)
85
- [value].flatten
86
- elsif %w[NULL NOT_NULL].include?(operator)
87
- nil
88
- else
89
- [value]
90
- end
91
- end
113
+ attr_reader :table_cache
92
114
 
93
115
  # Establish the connection to DynamoDB.
94
116
  #
@@ -393,7 +415,7 @@ module Dynamoid
393
415
  item = client.get_item(table_name: table_name,
394
416
  key: key_stanza(table, key, range_key),
395
417
  consistent_read: consistent_read)[:item]
396
- item ? result_item_to_hash(item) : nil
418
+ item ? item_to_hash(item) : nil
397
419
  end
398
420
 
399
421
  # Edits an existing item's attributes, or adds a new item to the table if it does not already exist. You can put, delete, or add attribute values
@@ -422,7 +444,7 @@ module Dynamoid
422
444
  attribute_updates: item_updater.attribute_updates,
423
445
  expected: expected_stanza(conditions),
424
446
  return_values: 'ALL_NEW')
425
- result_item_to_hash(result[:attributes])
447
+ item_to_hash(result[:attributes])
426
448
  rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
427
449
  raise Dynamoid::Errors::ConditionalCheckFailedException, e
428
450
  end
@@ -469,38 +491,45 @@ module Dynamoid
469
491
  # only really useful for range queries, since it can only find by one hash key at once. Only provide
470
492
  # one range key to the hash.
471
493
  #
494
+ # Dynamoid.adapter.query('users', { id: [[:eq, '1']], age: [[:between, [10, 30]]] }, { batch_size: 1000 })
495
+ #
472
496
  # @param [String] table_name the name of the table
473
- # @param [Hash] options the options to query the table with
474
- # @option options [String] :hash_value the value of the hash key to find
475
- # @option options [Number, Number] :range_between find the range key within this range
476
- # @option options [Number] :range_greater_than find range keys greater than this
477
- # @option options [Number] :range_less_than find range keys less than this
478
- # @option options [Number] :range_gte find range keys greater than or equal to this
479
- # @option options [Number] :range_lte find range keys less than or equal to this
497
+ # @param [Array[Array]] key_conditions conditions for the primary key attributes
498
+ # @param [Array[Array]] non_key_conditions (optional) conditions for non-primary key attributes
499
+ # @param [Hash] options (optional) the options to query the table with
500
+ # @option options [Boolean] :consistent_read You can set the ConsistentRead parameter to true and obtain a strongly consistent result
501
+ # @option options [Boolean] :scan_index_forward Specifies the order for index traversal: If true (default), the traversal is performed in ascending order; if false, the traversal is performed in descending order.
502
+ # @option options [Symbop] :select The attributes to be returned in the result (one of ALL_ATTRIBUTES, ALL_PROJECTED_ATTRIBUTES, ...)
503
+ # @option options [Symbol] :index_name The name of an index to query. This index can be any local secondary index or global secondary index on the table.
504
+ # @option options [Hash] :exclusive_start_key The primary key of the first item that this operation will evaluate.
505
+ # @option options [Integer] :batch_size The number of items to lazily load one by one
506
+ # @option options [Integer] :record_limit The maximum number of items to return (not necessarily the number of evaluated items)
507
+ # @option options [Integer] :scan_limit The maximum number of items to evaluate (not necessarily the number of matching items)
508
+ # @option options [Array[Symbol]] :project The attributes to retrieve from the table
480
509
  #
481
510
  # @return [Enumerable] matching items
482
511
  #
483
512
  # @since 1.0.0
484
513
  #
485
514
  # @todo Provide support for various other options http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#query-instance_method
486
- def query(table_name, options = {})
515
+ def query(table_name, key_conditions, non_key_conditions = {}, options = {})
487
516
  Enumerator.new do |yielder|
488
517
  table = describe_table(table_name)
489
518
 
490
- Query.new(client, table, options).call.each do |page|
519
+ Query.new(client, table, key_conditions, non_key_conditions, options).call.each do |page|
491
520
  yielder.yield(
492
- page.items.map { |row| result_item_to_hash(row) },
521
+ page.items.map { |item| item_to_hash(item) },
493
522
  last_evaluated_key: page.last_evaluated_key
494
523
  )
495
524
  end
496
525
  end
497
526
  end
498
527
 
499
- def query_count(table_name, options = {})
528
+ def query_count(table_name, key_conditions, non_key_conditions, options)
500
529
  table = describe_table(table_name)
501
530
  options[:select] = 'COUNT'
502
531
 
503
- Query.new(client, table, options).call
532
+ Query.new(client, table, key_conditions, non_key_conditions, options).call
504
533
  .map(&:count)
505
534
  .reduce(:+)
506
535
  end
@@ -522,7 +551,7 @@ module Dynamoid
522
551
 
523
552
  Scan.new(client, table, conditions, options).call.each do |page|
524
553
  yielder.yield(
525
- page.items.map { |row| result_item_to_hash(row) },
554
+ page.items.map { |item| item_to_hash(item) },
526
555
  last_evaluated_key: page.last_evaluated_key
527
556
  )
528
557
  end
@@ -557,7 +586,29 @@ module Dynamoid
557
586
  end
558
587
 
559
588
  def count(table_name)
560
- describe_table(table_name, true).item_count
589
+ describe_table(table_name, reload: true).item_count
590
+ end
591
+
592
+ # Run PartiQL query.
593
+ #
594
+ # Dynamoid.adapter.execute("SELECT * FROM users WHERE id = ?", ["758"])
595
+ #
596
+ # @param [String] statement PartiQL statement
597
+ # @param [Array] parameters a list of bind parameters
598
+ # @param [Hash] options
599
+ # @option [Boolean] consistent_read
600
+ # @return [[] | Array[Hash] | Enumerator::Lazy[Hash]] items when used a SELECT statement and empty Array otherwise
601
+ #
602
+ def execute(statement, parameters = [], options = {})
603
+ items = ExecuteStatement.new(client, statement, parameters, options).call
604
+
605
+ if items.is_a?(Array)
606
+ items
607
+ else
608
+ items.lazy.flat_map { |array| array }
609
+ end
610
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
611
+ []
561
612
  end
562
613
 
563
614
  protected
@@ -582,10 +633,7 @@ module Dynamoid
582
633
  conditions.delete(:unless_exists).try(:each) do |col|
583
634
  expected[col.to_s][:exists] = false
584
635
  end
585
- conditions.delete(:if_exists).try(:each) do |col, val|
586
- expected[col.to_s][:exists] = true
587
- expected[col.to_s][:value] = val
588
- end
636
+
589
637
  conditions.delete(:if).try(:each) do |col, val|
590
638
  expected[col.to_s][:value] = val
591
639
  end
@@ -596,7 +644,7 @@ module Dynamoid
596
644
  #
597
645
  # New, semi-arbitrary API to get data on the table
598
646
  #
599
- def describe_table(table_name, reload = false)
647
+ def describe_table(table_name, reload: false)
600
648
  (!reload && table_cache[table_name]) || begin
601
649
  table_cache[table_name] = Table.new(client.describe_table(table_name: table_name).data)
602
650
  end
@@ -605,10 +653,8 @@ module Dynamoid
605
653
  #
606
654
  # Converts a hash returned by get_item, scan, etc. into a key-value hash
607
655
  #
608
- def result_item_to_hash(item)
609
- {}.tap do |r|
610
- item.each { |k, v| r[k.to_sym] = v }
611
- end
656
+ def item_to_hash(hash)
657
+ hash.symbolize_keys
612
658
  end
613
659
 
614
660
  def sanitize_item(attributes)
@@ -39,14 +39,14 @@ module Dynamoid
39
39
  #
40
40
  # @since 0.2.0
41
41
  def target_association
42
- has_many_key_name = options[:inverse_of] || source.class.to_s.underscore.pluralize.to_sym
43
- has_one_key_name = options[:inverse_of] || source.class.to_s.underscore.to_sym
44
- unless target_class.associations[has_many_key_name].nil?
45
- return has_many_key_name if target_class.associations[has_many_key_name][:type] == :has_many
42
+ name = options[:inverse_of] || source.class.to_s.underscore.pluralize.to_sym
43
+ if target_class.associations.dig(name, :type) == :has_many
44
+ return name
46
45
  end
47
46
 
48
- unless target_class.associations[has_one_key_name].nil?
49
- return has_one_key_name if target_class.associations[has_one_key_name][:type] == :has_one
47
+ name = options[:inverse_of] || source.class.to_s.underscore.to_sym
48
+ if target_class.associations.dig(name, :type) == :has_one
49
+ return name # rubocop:disable Style/RedundantReturn
50
50
  end
51
51
  end
52
52
  end
@@ -265,7 +265,7 @@ module Dynamoid
265
265
  @associations[:"#{name}_ids"] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
266
266
  end
267
267
 
268
- define_method("#{name}=".to_sym) do |objects|
268
+ define_method(:"#{name}=") do |objects|
269
269
  @associations[:"#{name}_ids"] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
270
270
  @associations[:"#{name}_ids"].setter(objects)
271
271
  end
@@ -11,10 +11,9 @@ module Dynamoid
11
11
  extend ActiveModel::Translation
12
12
  extend ActiveModel::Callbacks
13
13
 
14
- define_model_callbacks :create, :save, :destroy, :initialize, :update
14
+ define_model_callbacks :create, :save, :destroy, :update
15
+ define_model_callbacks :initialize, :find, :touch, only: :after
15
16
 
16
- before_create :set_created_at
17
- before_save :set_updated_at
18
17
  before_save :set_expires_field
19
18
  after_initialize :set_inheritance_field
20
19
  end
@@ -33,21 +33,21 @@ module Dynamoid
33
33
  defaults[name] = settings[name] = options[:default]
34
34
 
35
35
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
36
- def #{name}
37
- settings[#{name.inspect}]
38
- end
36
+ def #{name} # def endpoint
37
+ settings[#{name.inspect}] # settings["endpoint"]
38
+ end # end
39
39
 
40
- def #{name}=(value)
41
- settings[#{name.inspect}] = value
42
- end
40
+ def #{name}=(value) # def endpoint=(value)
41
+ settings[#{name.inspect}] = value # settings["endpoint"] = value
42
+ end # end
43
43
 
44
- def #{name}?
45
- #{name}
46
- end
44
+ def #{name}? # def endpoint?
45
+ #{name} # endpoint
46
+ end # end
47
47
 
48
- def reset_#{name}
49
- settings[#{name.inspect}] = defaults[#{name.inspect}]
50
- end
48
+ def reset_#{name} # def reset_endpoint
49
+ settings[#{name.inspect}] = defaults[#{name.inspect}] # settings["endpoint"] = defaults["endpoint"]
50
+ end # end
51
51
  RUBY
52
52
  end
53
53
 
@@ -59,6 +59,7 @@ module Dynamoid
59
59
  option :http_idle_timeout, default: nil # - default: 5
60
60
  option :http_open_timeout, default: nil # - default: 15
61
61
  option :http_read_timeout, default: nil # - default: 60
62
+ option :create_table_on_save, default: true
62
63
 
63
64
  # The default logger for Dynamoid: either the Rails logger or just stdout.
64
65
  #