dynamoid 3.13.0 → 3.14.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -4
  3. data/README.md +60 -1584
  4. data/lib/dynamoid/associations/association.rb +10 -2
  5. data/lib/dynamoid/associations/belongs_to.rb +3 -1
  6. data/lib/dynamoid/associations/has_and_belongs_to_many.rb +0 -1
  7. data/lib/dynamoid/associations/has_many.rb +0 -1
  8. data/lib/dynamoid/associations/has_one.rb +1 -2
  9. data/lib/dynamoid/associations/many_association.rb +1 -0
  10. data/lib/dynamoid/associations.rb +64 -48
  11. data/lib/dynamoid/components.rb +1 -0
  12. data/lib/dynamoid/criteria/chain.rb +43 -30
  13. data/lib/dynamoid/dirty.rb +13 -3
  14. data/lib/dynamoid/document.rb +29 -21
  15. data/lib/dynamoid/fields.rb +55 -41
  16. data/lib/dynamoid/finders.rb +1 -1
  17. data/lib/dynamoid/indexes.rb +29 -21
  18. data/lib/dynamoid/persistence/inc.rb +15 -7
  19. data/lib/dynamoid/persistence/save.rb +21 -14
  20. data/lib/dynamoid/persistence.rb +88 -54
  21. data/lib/dynamoid/transactions/mutation/base.rb +76 -0
  22. data/lib/dynamoid/transactions/mutation/builders/delete_request_builder.rb +44 -0
  23. data/lib/dynamoid/transactions/mutation/builders/update_request_builder.rb +139 -0
  24. data/lib/dynamoid/transactions/mutation/create.rb +52 -0
  25. data/lib/dynamoid/transactions/mutation/delete_with_instance.rb +80 -0
  26. data/lib/dynamoid/transactions/mutation/delete_with_primary_key.rb +62 -0
  27. data/lib/dynamoid/transactions/mutation/destroy.rb +96 -0
  28. data/lib/dynamoid/transactions/mutation/import.rb +84 -0
  29. data/lib/dynamoid/transactions/mutation/inc.rb +101 -0
  30. data/lib/dynamoid/transactions/mutation/increment.rb +63 -0
  31. data/lib/dynamoid/transactions/mutation/save.rb +194 -0
  32. data/lib/dynamoid/transactions/mutation/touch.rb +99 -0
  33. data/lib/dynamoid/transactions/mutation/update_attributes.rb +49 -0
  34. data/lib/dynamoid/transactions/mutation/update_fields.rb +185 -0
  35. data/lib/dynamoid/transactions/mutation/upsert.rb +94 -0
  36. data/lib/dynamoid/transactions/mutation.rb +935 -0
  37. data/lib/dynamoid/transactions/retrieval/find.rb +140 -0
  38. data/lib/dynamoid/transactions/retrieval.rb +150 -0
  39. data/lib/dynamoid/transactions.rb +63 -0
  40. data/lib/dynamoid/version.rb +1 -1
  41. data/lib/dynamoid.rb +1 -2
  42. metadata +23 -17
  43. data/lib/dynamoid/transaction_read/find.rb +0 -137
  44. data/lib/dynamoid/transaction_read.rb +0 -146
  45. data/lib/dynamoid/transaction_write/base.rb +0 -59
  46. data/lib/dynamoid/transaction_write/create.rb +0 -49
  47. data/lib/dynamoid/transaction_write/delete_with_instance.rb +0 -65
  48. data/lib/dynamoid/transaction_write/delete_with_primary_key.rb +0 -64
  49. data/lib/dynamoid/transaction_write/destroy.rb +0 -84
  50. data/lib/dynamoid/transaction_write/item_updater.rb +0 -60
  51. data/lib/dynamoid/transaction_write/save.rb +0 -177
  52. data/lib/dynamoid/transaction_write/update_attributes.rb +0 -46
  53. data/lib/dynamoid/transaction_write/update_fields.rb +0 -247
  54. data/lib/dynamoid/transaction_write/upsert.rb +0 -113
  55. data/lib/dynamoid/transaction_write.rb +0 -673
@@ -1,146 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dynamoid/transaction_read/find'
4
-
5
- module Dynamoid
6
- # The class +TransactionRead+ provides means to perform multiple reading
7
- # operations in transaction, that is atomically, so that either all of them
8
- # succeed, or all of them fail.
9
- #
10
- # The reading methods are supposed to be as close as possible to their
11
- # non-transactional counterparts:
12
- #
13
- # user_id = params[:user_id]
14
- # payment = params[:payment_id]
15
- #
16
- # models = Dynamoid::TransactionRead.execute do |t|
17
- # t.find User, user_id
18
- # t.find Payment, payment_id
19
- # end
20
- #
21
- # The only difference is that the methods are called on a transaction
22
- # instance and a model or a model class should be specified. So +User.find+
23
- # becomes +t.find(user_id)+ and +Payment.find(payment_id)+ becomes +t.find
24
- # Payment, payment_id+.
25
- #
26
- # A transaction can be used without a block. This way a transaction instance
27
- # should be instantiated and committed manually with +#commit+ method:
28
- #
29
- # t = Dynamoid::TransactionRead.new
30
- #
31
- # t.find user_id
32
- # t.find payment_id
33
- #
34
- # models = t.commit
35
- #
36
- #
37
- # ### DynamoDB's transactions
38
- #
39
- # The main difference between DynamoDB transactions and a common interface is
40
- # that DynamoDB's transactions are executed in batch. So in Dynamoid no
41
- # data actually loaded when some transactional method (e.g+ `#find+) is
42
- # called. All the changes are loaded at the end.
43
- #
44
- # A +TransactGetItems+ DynamoDB operation is used (see
45
- # [documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html)
46
- # for details).
47
- class TransactionRead
48
- def self.execute
49
- transaction = new
50
-
51
- begin
52
- yield transaction
53
- transaction.commit
54
- end
55
- end
56
-
57
- def initialize
58
- @actions = []
59
- end
60
-
61
- # Load all the models.
62
- #
63
- # transaction = Dynamoid::TransactionRead.new
64
- # # ...
65
- # transaction.commit
66
- def commit
67
- return [] if @actions.empty?
68
-
69
- # some actions may produce multiple requests
70
- action_request_groups = @actions.map(&:action_request).map do |action_request|
71
- action_request.is_a?(Array) ? action_request : [action_request]
72
- end
73
- action_requests = action_request_groups.flatten(1)
74
-
75
- return [] if action_requests.empty?
76
-
77
- response = Dynamoid.adapter.transact_read_items(action_requests)
78
-
79
- responses = response.responses.dup
80
- @actions.zip(action_request_groups).map do |action, action_requests|
81
- action_responses = responses.shift(action_requests.size)
82
- action.process_responses(action_responses)
83
- end.flatten
84
- end
85
-
86
- # Find one or many objects, specified by one id or an array of ids.
87
- #
88
- # By default it raises +RecordNotFound+ exception if at least one model
89
- # isn't found. This behavior can be changed with +raise_error+ option. If
90
- # specified +raise_error: false+ option then +find+ will not raise the
91
- # exception.
92
- #
93
- # When a document schema includes range key it should always be specified
94
- # in +find+ method call. In case it's missing +MissingRangeKey+ exception
95
- # will be raised.
96
- #
97
- # Please note that there are the following differences between
98
- # transactional and non-transactional +find+:
99
- # - transactional +find+ preserves order of models in result when given multiple ids
100
- # - transactional +find+ doesn't return results immediately, a single
101
- # collection with results of all the +find+ calls is returned instead
102
- # - +:consistent_read+ option isn't supported
103
- # - transactional +find+ is subject to limitations of the
104
- # [TransactGetItems](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html)
105
- # DynamoDB operation, e.g. the whole read transaction can load only up to 100 models.
106
- #
107
- # @param [Object|Array] ids a single primary key or an array of primary keys
108
- # @param [Hash] options optional parameters of the operation
109
- # @option options [Object] :range_key sort key of a model; required when a single partition key is given and a sort key is declared for a model
110
- # @option options [true|false] :raise_error whether to raise a +RecordNotFound+ exception; specify explicitly +raise_error: false+ to suppress the exception; default is +true+
111
- # @return [nil]
112
- #
113
- # @example Find by partition key
114
- # Dynamoid::TransactionRead.execute do |t|
115
- # t.find Document, 101
116
- # end
117
- #
118
- # @example Find by partition key and sort key
119
- # Dynamoid::TransactionRead.execute do |t|
120
- # t.find Document, 101, range_key: 'archived'
121
- # end
122
- #
123
- # @example Find several documents by partition key
124
- # Dynamoid::TransactionRead.execute do |t|
125
- # t.find Document, 101, 102, 103
126
- # t.find Document, [101, 102, 103]
127
- # end
128
- #
129
- # @example Find several documents by partition key and sort key
130
- # Dynamoid::TransactionRead.execute do |t|
131
- # t.find Document, [[101, 'archived'], [102, 'new'], [103, 'deleted']]
132
- # end
133
- def find(model_class, *ids, **options)
134
- action = Dynamoid::TransactionRead::Find.new(model_class, *ids, **options)
135
- register_action action
136
- end
137
-
138
- private
139
-
140
- def register_action(action)
141
- @actions << action
142
- action.on_registration
143
- action.observable_by_user_result
144
- end
145
- end
146
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dynamoid
4
- class TransactionWrite
5
- class Base
6
- # Callback called at "initialization" or "registration" an action
7
- # before changes are persisted. It's a proper place to validate
8
- # a model or run callbacks
9
- def on_registration
10
- raise 'Not implemented'
11
- end
12
-
13
- # Callback called after changes are persisted.
14
- # It's a proper place to mark changes in a model as applied.
15
- def on_commit
16
- raise 'Not implemented'
17
- end
18
-
19
- # Callback called when a transaction is rolled back.
20
- # It's a proper place to undo changes made in after_... callbacks.
21
- def on_rollback
22
- raise 'Not implemented'
23
- end
24
-
25
- # Whether some callback aborted or canceled an action
26
- def aborted?
27
- raise 'Not implemented'
28
- end
29
-
30
- # Whether there are changes to persist, e.g. updating a model with no
31
- # attribute changed is skipped.
32
- def skipped?
33
- raise 'Not implemented'
34
- end
35
-
36
- # Value returned to a user as an action result
37
- def observable_by_user_result
38
- raise 'Not implemented'
39
- end
40
-
41
- # Coresponding part of a final request body
42
- def action_request
43
- raise 'Not implemented'
44
- end
45
-
46
- # copied from aws_sdk_v3
47
- def sanitize_item(attributes)
48
- config_value = Dynamoid.config.store_attribute_with_nil_value
49
- store_attribute_with_nil_value = config_value.nil? ? false : !!config_value
50
-
51
- attributes.reject do |_, v|
52
- !store_attribute_with_nil_value && v.nil?
53
- end.transform_values do |v|
54
- v.is_a?(Hash) ? v.stringify_keys : v
55
- end
56
- end
57
- end
58
- end
59
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Dynamoid
6
- class TransactionWrite
7
- class Create < Base
8
- def initialize(model_class, attributes = {}, **options, &block)
9
- super()
10
-
11
- @model = model_class.new(attributes)
12
-
13
- if block
14
- yield(@model)
15
- end
16
-
17
- @save_action = Save.new(@model, **options)
18
- end
19
-
20
- def on_registration
21
- @save_action.on_registration
22
- end
23
-
24
- def on_commit
25
- @save_action.on_commit
26
- end
27
-
28
- def on_rollback
29
- @save_action.on_rollback
30
- end
31
-
32
- def aborted?
33
- @save_action.aborted?
34
- end
35
-
36
- def skipped?
37
- false
38
- end
39
-
40
- def observable_by_user_result
41
- @model
42
- end
43
-
44
- def action_request
45
- @save_action.action_request
46
- end
47
- end
48
- end
49
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Dynamoid
6
- class TransactionWrite
7
- class DeleteWithInstance < Base
8
- def initialize(model)
9
- super()
10
-
11
- @model = model
12
- @model_class = model.class
13
- end
14
-
15
- def on_registration
16
- validate_model!
17
- end
18
-
19
- def on_commit
20
- @model.destroyed = true
21
- end
22
-
23
- def on_rollback; end
24
-
25
- def aborted?
26
- false
27
- end
28
-
29
- def skipped?
30
- false
31
- end
32
-
33
- def observable_by_user_result
34
- @model
35
- end
36
-
37
- def action_request
38
- key = { @model_class.hash_key => dump_attribute(@model_class.hash_key, @model.hash_key) }
39
-
40
- if @model_class.range_key?
41
- key[@model_class.range_key] = dump_attribute(@model_class.range_key, @model.range_value)
42
- end
43
-
44
- {
45
- delete: {
46
- key: key,
47
- table_name: @model_class.table_name
48
- }
49
- }
50
- end
51
-
52
- private
53
-
54
- def validate_model!
55
- raise Dynamoid::Errors::MissingHashKey if @model.hash_key.nil?
56
- raise Dynamoid::Errors::MissingRangeKey if @model_class.range_key? && @model.range_value.nil?
57
- end
58
-
59
- def dump_attribute(name, value)
60
- options = @model_class.attributes[name]
61
- Dumping.dump_field(value, options)
62
- end
63
- end
64
- end
65
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Dynamoid
6
- class TransactionWrite
7
- class DeleteWithPrimaryKey < Base
8
- def initialize(model_class, hash_key, range_key)
9
- super()
10
-
11
- @model_class = model_class
12
- @hash_key = hash_key
13
- @range_key = range_key
14
- end
15
-
16
- def on_registration
17
- validate_primary_key!
18
- end
19
-
20
- def on_commit; end
21
-
22
- def on_rollback; end
23
-
24
- def aborted?
25
- false
26
- end
27
-
28
- def skipped?
29
- false
30
- end
31
-
32
- def observable_by_user_result
33
- nil
34
- end
35
-
36
- def action_request
37
- key = { @model_class.hash_key => dump_attribute(@model_class.hash_key, @hash_key) }
38
-
39
- if @model_class.range_key?
40
- key[@model_class.range_key] = dump_attribute(@model_class.range_key, @range_key)
41
- end
42
-
43
- {
44
- delete: {
45
- key: key,
46
- table_name: @model_class.table_name
47
- }
48
- }
49
- end
50
-
51
- private
52
-
53
- def validate_primary_key!
54
- raise Dynamoid::Errors::MissingHashKey if @hash_key.nil?
55
- raise Dynamoid::Errors::MissingRangeKey if @model_class.range_key? && @range_key.nil?
56
- end
57
-
58
- def dump_attribute(name, value)
59
- options = @model_class.attributes[name]
60
- Dumping.dump_field(value, options)
61
- end
62
- end
63
- end
64
- end
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Dynamoid
6
- class TransactionWrite
7
- class Destroy < Base
8
- def initialize(model, **options)
9
- super()
10
-
11
- @model = model
12
- @options = options
13
- @model_class = model.class
14
- @aborted = false
15
- end
16
-
17
- def on_registration
18
- @aborted = true
19
- @model.run_callbacks(:destroy) do
20
- validate_primary_key!
21
-
22
- @aborted = false
23
- true
24
- end
25
-
26
- if @aborted && @options[:raise_error]
27
- raise Dynamoid::Errors::RecordNotDestroyed, @model
28
- end
29
- end
30
-
31
- def on_commit
32
- return if @aborted
33
-
34
- @model.destroyed = true
35
- @model.run_callbacks(:commit)
36
- end
37
-
38
- def on_rollback
39
- @model.run_callbacks(:rollback)
40
- end
41
-
42
- def aborted?
43
- @aborted
44
- end
45
-
46
- def skipped?
47
- false
48
- end
49
-
50
- def observable_by_user_result
51
- return false if @aborted
52
-
53
- @model
54
- end
55
-
56
- def action_request
57
- key = { @model_class.hash_key => dump_attribute(@model_class.hash_key, @model.hash_key) }
58
-
59
- if @model_class.range_key?
60
- key[@model_class.range_key] = dump_attribute(@model_class.range_key, @model.range_value)
61
- end
62
-
63
- {
64
- delete: {
65
- key: key,
66
- table_name: @model_class.table_name
67
- }
68
- }
69
- end
70
-
71
- private
72
-
73
- def validate_primary_key!
74
- raise Dynamoid::Errors::MissingHashKey if @model.hash_key.nil?
75
- raise Dynamoid::Errors::MissingRangeKey if @model_class.range_key? && @model.range_value.nil?
76
- end
77
-
78
- def dump_attribute(name, value)
79
- options = @model_class.attributes[name]
80
- Dumping.dump_field(value, options)
81
- end
82
- end
83
- end
84
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dynamoid
4
- class TransactionWrite
5
- class ItemUpdater
6
- attr_reader :attributes_to_set, :attributes_to_add, :attributes_to_delete, :attributes_to_remove
7
-
8
- def initialize(model_class)
9
- @model_class = model_class
10
-
11
- @attributes_to_set = {}
12
- @attributes_to_add = {}
13
- @attributes_to_delete = {}
14
- @attributes_to_remove = []
15
- end
16
-
17
- def empty?
18
- [@attributes_to_set, @attributes_to_add, @attributes_to_delete, @attributes_to_remove].all?(&:empty?)
19
- end
20
-
21
- def set(attributes)
22
- validate_attribute_names!(attributes.keys)
23
- if Dynamoid.config.store_attribute_with_nil_value
24
- @attributes_to_set.merge!(attributes)
25
- else
26
- @attributes_to_set.merge!(attributes.reject { |_, v| v.nil? })
27
- @attributes_to_remove += attributes.select { |_, v| v.nil? }.keys
28
- end
29
- end
30
-
31
- # adds to array of fields for use in REMOVE update expression
32
- def remove(*names)
33
- validate_attribute_names!(names)
34
- @attributes_to_remove += names
35
- end
36
-
37
- # increments a number or adds to a set, starts at 0 or [] if it doesn't yet exist
38
- def add(attributes)
39
- validate_attribute_names!(attributes.keys)
40
- @attributes_to_add.merge!(attributes)
41
- end
42
-
43
- # deletes a value or values from a set
44
- def delete(attributes)
45
- validate_attribute_names!(attributes.keys)
46
- @attributes_to_delete.merge!(attributes)
47
- end
48
-
49
- private
50
-
51
- def validate_attribute_names!(names)
52
- names.each do |name|
53
- unless @model_class.attributes[name]
54
- raise Dynamoid::Errors::UnknownAttribute.new(@model_class, name)
55
- end
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,177 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Dynamoid
6
- class TransactionWrite
7
- class Save < Base
8
- def initialize(model, **options)
9
- super()
10
-
11
- @model = model
12
- @model_class = model.class
13
- @options = options
14
-
15
- @aborted = false
16
- @was_new_record = model.new_record?
17
- @valid = nil
18
- end
19
-
20
- def on_registration
21
- if @options[:validate] != false && !(@valid = @model.valid?)
22
- if @options[:raise_error]
23
- raise Dynamoid::Errors::DocumentNotValid, @model
24
- else
25
- @aborted = true
26
- return
27
- end
28
- end
29
-
30
- @aborted = true
31
- callback_name = @was_new_record ? :create : :update
32
-
33
- @model.run_callbacks(:save) do
34
- @model.run_callbacks(callback_name) do
35
- @model.run_callbacks(:validate) do
36
- validate_primary_key!
37
-
38
- @aborted = false
39
- true
40
- end
41
- end
42
- end
43
-
44
- if @aborted && @options[:raise_error]
45
- raise Dynamoid::Errors::RecordNotSaved, @model
46
- end
47
-
48
- if @was_new_record && @model.hash_key.nil?
49
- @model.hash_key = SecureRandom.uuid
50
- end
51
- end
52
-
53
- def on_commit
54
- return if @aborted
55
-
56
- @model.changes_applied
57
-
58
- if @was_new_record
59
- @model.new_record = false
60
- end
61
-
62
- @model.run_callbacks(:commit)
63
- end
64
-
65
- def on_rollback
66
- @model.run_callbacks(:rollback)
67
- end
68
-
69
- def aborted?
70
- @aborted
71
- end
72
-
73
- def skipped?
74
- @model.persisted? && !@model.changed?
75
- end
76
-
77
- def observable_by_user_result
78
- !@aborted
79
- end
80
-
81
- def action_request
82
- if @was_new_record
83
- action_request_to_create
84
- else
85
- action_request_to_update
86
- end
87
- end
88
-
89
- private
90
-
91
- def validate_primary_key!
92
- raise Dynamoid::Errors::MissingHashKey if !@was_new_record && @model.hash_key.nil?
93
- raise Dynamoid::Errors::MissingRangeKey if @model_class.range_key? && @model.range_value.nil?
94
- end
95
-
96
- def action_request_to_create
97
- touch_model_timestamps(skip_created_at: false)
98
-
99
- attributes_dumped = Dynamoid::Dumping.dump_attributes(@model.attributes, @model_class.attributes)
100
- attributes_dumped = sanitize_item(attributes_dumped)
101
-
102
- # require primary key not to exist yet
103
- condition = "attribute_not_exists(#{@model_class.hash_key})"
104
- if @model_class.range_key?
105
- condition += " AND attribute_not_exists(#{@model_class.range_key})"
106
- end
107
-
108
- {
109
- put: {
110
- item: attributes_dumped,
111
- table_name: @model_class.table_name,
112
- condition_expression: condition
113
- }
114
- }
115
- end
116
-
117
- def action_request_to_update
118
- touch_model_timestamps(skip_created_at: true)
119
-
120
- # changed attributes to persist
121
- changes = @model.attributes.slice(*@model.changed.map(&:to_sym))
122
- changes_dumped = Dynamoid::Dumping.dump_attributes(changes, @model_class.attributes)
123
-
124
- # primary key to look up an item to update
125
- key = { @model_class.hash_key => dump_attribute(@model_class.hash_key, @model.hash_key) }
126
- key[@model_class.range_key] = dump_attribute(@model_class.range_key, @model.range_value) if @model_class.range_key?
127
-
128
- # Build UpdateExpression and keep names and values placeholders mapping
129
- # in ExpressionAttributeNames and ExpressionAttributeValues.
130
- set_expression_statements = []
131
- remove_expression_statements = []
132
- expression_attribute_names = {}
133
- expression_attribute_values = {}
134
-
135
- changes_dumped.each_with_index do |(name, value), i|
136
- name_placeholder = "#_n#{i}"
137
- value_placeholder = ":_s#{i}"
138
-
139
- if value || Dynamoid.config.store_attribute_with_nil_value
140
- set_expression_statements << "#{name_placeholder} = #{value_placeholder}"
141
- expression_attribute_values[value_placeholder] = value
142
- else
143
- remove_expression_statements << name_placeholder
144
- end
145
- expression_attribute_names[name_placeholder] = name
146
- end
147
-
148
- update_expression = ''
149
- update_expression += "SET #{set_expression_statements.join(', ')}" if set_expression_statements.any?
150
- update_expression += " REMOVE #{remove_expression_statements.join(', ')}" if remove_expression_statements.any?
151
-
152
- {
153
- update: {
154
- key: key,
155
- table_name: @model_class.table_name,
156
- update_expression: update_expression,
157
- expression_attribute_names: expression_attribute_names,
158
- expression_attribute_values: expression_attribute_values
159
- }
160
- }
161
- end
162
-
163
- def touch_model_timestamps(skip_created_at:)
164
- return unless @model_class.timestamps_enabled?
165
-
166
- timestamp = DateTime.now.in_time_zone(Time.zone)
167
- @model.updated_at = timestamp unless @options[:touch] == false && !@was_new_record
168
- @model.created_at ||= timestamp unless skip_created_at
169
- end
170
-
171
- def dump_attribute(name, value)
172
- options = @model_class.attributes[name]
173
- Dumping.dump_field(value, options)
174
- end
175
- end
176
- end
177
- end