activity_notification 1.7.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.travis.yml +16 -2
  4. data/CHANGELOG.md +22 -2
  5. data/Gemfile +7 -0
  6. data/Procfile +2 -0
  7. data/README.md +366 -32
  8. data/Rakefile +19 -10
  9. data/activity_notification.gemspec +5 -3
  10. data/app/channels/activity_notification/notification_channel.rb +37 -0
  11. data/app/channels/activity_notification/notification_with_devise_channel.rb +51 -0
  12. data/app/controllers/activity_notification/notifications_controller.rb +1 -1
  13. data/app/controllers/activity_notification/subscriptions_controller.rb +1 -1
  14. data/app/jobs/activity_notification/notify_all_job.rb +16 -0
  15. data/app/jobs/activity_notification/notify_job.rb +17 -0
  16. data/app/jobs/activity_notification/notify_to_job.rb +16 -0
  17. data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +1 -1
  18. data/app/views/activity_notification/notifications/default/index.html.erb +55 -2
  19. data/bin/_dynamodblocal +4 -0
  20. data/{scripts → bin}/bundle_update.sh +1 -0
  21. data/bin/deploy_on_heroku.sh +14 -0
  22. data/bin/install_dynamodblocal.sh +5 -0
  23. data/bin/start_dynamodblocal.sh +47 -0
  24. data/bin/stop_dynamodblocal.sh +34 -0
  25. data/gemfiles/Gemfile.rails-4.2 +1 -0
  26. data/gemfiles/Gemfile.rails-5.0 +2 -0
  27. data/gemfiles/Gemfile.rails-5.1 +1 -0
  28. data/gemfiles/Gemfile.rails-5.2 +1 -0
  29. data/gemfiles/Gemfile.rails-6.0.rc +21 -0
  30. data/lib/activity_notification.rb +1 -0
  31. data/lib/activity_notification/apis/notification_api.rb +289 -136
  32. data/lib/activity_notification/apis/subscription_api.rb +80 -53
  33. data/lib/activity_notification/common.rb +3 -3
  34. data/lib/activity_notification/config.rb +89 -33
  35. data/lib/activity_notification/controllers/common_controller.rb +19 -7
  36. data/lib/activity_notification/helpers/errors.rb +4 -0
  37. data/lib/activity_notification/helpers/view_helpers.rb +1 -1
  38. data/lib/activity_notification/models/concerns/notifiable.rb +61 -53
  39. data/lib/activity_notification/models/concerns/subscriber.rb +7 -6
  40. data/lib/activity_notification/models/concerns/target.rb +73 -28
  41. data/lib/activity_notification/optional_targets/base.rb +2 -2
  42. data/lib/activity_notification/orm/active_record/notification.rb +4 -23
  43. data/lib/activity_notification/orm/dynamoid.rb +495 -0
  44. data/lib/activity_notification/orm/dynamoid/extension.rb +184 -0
  45. data/lib/activity_notification/orm/dynamoid/notification.rb +189 -0
  46. data/lib/activity_notification/orm/dynamoid/subscription.rb +82 -0
  47. data/lib/activity_notification/orm/mongoid.rb +4 -1
  48. data/lib/activity_notification/orm/mongoid/notification.rb +8 -25
  49. data/lib/activity_notification/orm/mongoid/subscription.rb +1 -1
  50. data/lib/activity_notification/roles/acts_as_notifiable.rb +33 -5
  51. data/lib/activity_notification/roles/acts_as_target.rb +62 -9
  52. data/lib/activity_notification/version.rb +1 -1
  53. data/lib/generators/templates/activity_notification.rb +30 -7
  54. data/lib/tasks/activity_notification_tasks.rake +14 -4
  55. data/spec/channels/notification_channel_shared_examples.rb +59 -0
  56. data/spec/channels/notification_channel_spec.rb +50 -0
  57. data/spec/channels/notification_with_devise_channel_spec.rb +99 -0
  58. data/spec/concerns/apis/notification_api_spec.rb +2 -2
  59. data/spec/concerns/apis/subscription_api_spec.rb +2 -2
  60. data/spec/concerns/models/notifiable_spec.rb +72 -7
  61. data/spec/concerns/models/subscriber_spec.rb +53 -49
  62. data/spec/concerns/models/target_spec.rb +135 -13
  63. data/spec/config_spec.rb +41 -1
  64. data/spec/controllers/notifications_controller_shared_examples.rb +7 -3
  65. data/spec/controllers/subscriptions_controller_shared_examples.rb +7 -3
  66. data/spec/helpers/view_helpers_spec.rb +12 -10
  67. data/spec/models/dummy/dummy_group_spec.rb +4 -0
  68. data/spec/models/dummy/dummy_notifiable_spec.rb +4 -0
  69. data/spec/models/dummy/dummy_notifier_spec.rb +4 -0
  70. data/spec/models/dummy/dummy_subscriber_spec.rb +3 -0
  71. data/spec/models/dummy/dummy_target_spec.rb +4 -0
  72. data/spec/models/notification_spec.rb +164 -45
  73. data/spec/models/subscription_spec.rb +69 -14
  74. data/spec/orm/dynamoid_spec.rb +115 -0
  75. data/spec/rails_app/app/assets/javascripts/application.js +2 -1
  76. data/spec/rails_app/app/assets/javascripts/cable.js +12 -0
  77. data/spec/rails_app/app/controllers/comments_controller.rb +3 -4
  78. data/spec/rails_app/app/models/admin.rb +6 -4
  79. data/spec/rails_app/app/models/article.rb +2 -2
  80. data/spec/rails_app/app/models/comment.rb +17 -5
  81. data/spec/rails_app/app/models/user.rb +5 -3
  82. data/spec/rails_app/app/views/activity_notification/notifications/users/overridden/custom/_test.html.erb +1 -0
  83. data/spec/rails_app/config/application.rb +6 -1
  84. data/spec/rails_app/config/cable.yml +8 -0
  85. data/spec/rails_app/config/dynamoid.rb +5 -0
  86. data/spec/rails_app/config/environment.rb +4 -1
  87. data/spec/rails_app/config/environments/production.rb +1 -1
  88. data/spec/rails_app/config/initializers/activity_notification.rb +30 -7
  89. data/spec/rails_app/config/locales/activity_notification.en.yml +2 -0
  90. data/spec/rails_app/db/seeds.rb +21 -5
  91. data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +12 -4
  92. data/spec/roles/acts_as_notifiable_spec.rb +2 -2
  93. data/spec/roles/acts_as_target_spec.rb +1 -1
  94. data/spec/spec_helper.rb +15 -8
  95. metadata +67 -20
  96. data/spec/rails_app/app/models/.keep +0 -0
  97. data/spec/rails_app/app/views/activity_notification/notifications/users/overriden/custom/_test.html.erb +0 -1
@@ -0,0 +1,184 @@
1
+ require 'dynamoid/adapter_plugin/aws_sdk_v3'
2
+
3
+ # Entend Dynamoid to support none, limit, exists?, update_all in Dynamoid::Criteria::Chain.
4
+ # ActivityNotification project will try to contribute these fundamental functions to Dynamoid upstream.
5
+ # @private
6
+ module Dynamoid # :nodoc: all
7
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria.rb
8
+ # @private
9
+ module Criteria
10
+ # @private
11
+ class None < Chain
12
+ def ==(other)
13
+ other.is_a?(None)
14
+ end
15
+
16
+ def records
17
+ []
18
+ end
19
+
20
+ def count
21
+ 0
22
+ end
23
+
24
+ def delete_all
25
+ end
26
+
27
+ def empty?
28
+ true
29
+ end
30
+ end
31
+
32
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria/chain.rb
33
+ # @private
34
+ class Chain
35
+ def none
36
+ None.new(self.source)
37
+ end
38
+
39
+ # Set query result limit as record_limit of Dynamoid
40
+ # @scope class
41
+ # @param [Integer] limit Query result limit as record_limit
42
+ # @return [Dynamoid::Criteria::Chain] Database query of filtered notifications or subscriptions
43
+ def limit(limit)
44
+ record_limit(limit)
45
+ end
46
+
47
+ # Return if records exist
48
+ # @scope class
49
+ # @return [Boolean] If records exist
50
+ def exists?
51
+ record_limit(1).count > 0
52
+ end
53
+
54
+ # Return size of records as count
55
+ # @scope class
56
+ # @return [Integer] Size of records
57
+ def size
58
+ count
59
+ end
60
+
61
+ #TODO Make this batch
62
+ def update_all(conditions = {})
63
+ each do |document|
64
+ document.update_attributes(conditions)
65
+ end
66
+ end
67
+ end
68
+
69
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria.rb
70
+ # @private
71
+ module ClassMethods
72
+ define_method(:none) do |*args, &blk|
73
+ chain = Dynamoid::Criteria::Chain.new(self)
74
+ chain.send(:none, *args, &blk)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ # Entend Dynamoid to support query and scan with 'null' and 'not_null' conditions
81
+ # @private
82
+ module Dynamoid # :nodoc: all
83
+ # @private
84
+ module Criteria
85
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria/chain.rb
86
+ # @private
87
+ module NullOperatorExtension
88
+ # @private
89
+ def field_hash(key)
90
+ name, operation = key.to_s.split('.')
91
+ val = type_cast_condition_parameter(name, query[key])
92
+
93
+ hash = case operation
94
+ when 'null'
95
+ { null: val }
96
+ when 'not_null'
97
+ { not_null: val }
98
+ else
99
+ return super(key)
100
+ end
101
+
102
+ { name.to_sym => hash }
103
+ end
104
+ end
105
+
106
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria/chain.rb
107
+ # @private
108
+ class Chain
109
+ prepend NullOperatorExtension
110
+ end
111
+ end
112
+
113
+ # @private
114
+ module AdapterPlugin
115
+ # @private
116
+ class AwsSdkV3
117
+
118
+ NULL_OPERATOR_FIELD_MAP = {
119
+ null: 'NULL',
120
+ not_null: 'NOT_NULL'
121
+ }.freeze
122
+
123
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb
124
+ # @private
125
+ class Query < ::Dynamoid::AdapterPlugin::Query
126
+ # @private
127
+ def query_filter
128
+ conditions.except(*AwsSdkV3::RANGE_MAP.keys).reduce({}) do |result, (attr, cond)|
129
+ if AwsSdkV3::NULL_OPERATOR_FIELD_MAP.has_key?(cond.keys[0])
130
+ condition = { comparison_operator: AwsSdkV3::NULL_OPERATOR_FIELD_MAP[cond.keys[0]] }
131
+ else
132
+ condition = {
133
+ comparison_operator: AwsSdkV3::FIELD_MAP[cond.keys[0]],
134
+ attribute_value_list: AwsSdkV3.attribute_value_list(AwsSdkV3::FIELD_MAP[cond.keys[0]], cond.values[0].freeze)
135
+ }
136
+ end
137
+ result[attr] = condition
138
+ result
139
+ end
140
+ end
141
+ end
142
+
143
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb
144
+ # @private
145
+ class Scan < ::Dynamoid::AdapterPlugin::Scan
146
+ # @private
147
+ def scan_filter
148
+ conditions.reduce({}) do |result, (attr, cond)|
149
+ if AwsSdkV3::NULL_OPERATOR_FIELD_MAP.has_key?(cond.keys[0])
150
+ condition = { comparison_operator: AwsSdkV3::NULL_OPERATOR_FIELD_MAP[cond.keys[0]] }
151
+ else
152
+ condition = {
153
+ comparison_operator: AwsSdkV3::FIELD_MAP[cond.keys[0]],
154
+ attribute_value_list: AwsSdkV3.attribute_value_list(AwsSdkV3::FIELD_MAP[cond.keys[0]], cond.values[0].freeze)
155
+ }
156
+ end
157
+ result[attr] = condition
158
+ result
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ module ActivityNotification
167
+ # Dynamoid extension module for ActivityNotification.
168
+ module DynamoidExtension
169
+ extend ActiveSupport::Concern
170
+
171
+ class_methods do
172
+ # Defines delete_all method as calling delete_table and create_table methods
173
+ def delete_all
174
+ delete_table
175
+ create_table(sync: true)
176
+ end
177
+ end
178
+
179
+ # Returns an instance of the specified +klass+ with the attributes of the current record.
180
+ def becomes(klass)
181
+ self
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,189 @@
1
+ require 'dynamoid'
2
+ require 'activity_notification/apis/notification_api'
3
+
4
+ module ActivityNotification
5
+ module ORM
6
+ module Dynamoid
7
+ # Notification model implementation generated by ActivityNotification.
8
+ class Notification
9
+ include ::Dynamoid::Document
10
+ include ActiveModel::AttributeAssignment
11
+ include GlobalID::Identification
12
+ include DynamoidExtension
13
+ include Common
14
+ include Renderable
15
+ include Association
16
+ include NotificationApi
17
+
18
+ table name: ActivityNotification.config.notification_table_name, key: :id
19
+
20
+ # Belongs to target instance of this notification as polymorphic association using composite key.
21
+ # @scope instance
22
+ # @return [Object] Target instance of this notification
23
+ belongs_to_composite_xdb_record :target, store_with_associated_records: true
24
+
25
+ # Belongs to notifiable instance of this notification as polymorphic association using composite key.
26
+ # @scope instance
27
+ # @return [Object] Notifiable instance of this notification
28
+ belongs_to_composite_xdb_record :notifiable, store_with_associated_records: true
29
+
30
+ # Belongs to group instance of this notification as polymorphic association using composite key.
31
+ # @scope instance
32
+ # @return [Object] Group instance of this notification
33
+ belongs_to_composite_xdb_record :group
34
+
35
+ field :key, :string
36
+ field :parameters, :raw, default: {}
37
+ field :opened_at, :datetime
38
+ field :group_owner_id, :string
39
+
40
+ # Belongs to group owner notification instance of this notification.
41
+ # Only group member instance has :group_owner value.
42
+ # Group owner instance has nil as :group_owner association.
43
+ # @scope instance
44
+ # @return [Notification] Group owner notification instance of this notification
45
+ belongs_to :group_owner, { class_name: "ActivityNotification::Notification", foreign_key: :group_owner_id }.merge(Rails::VERSION::MAJOR >= 5 ? { optional: true } : {})
46
+
47
+ # Customized method that belongs to group owner notification instance of this notification.
48
+ # @raise [Errors::RecordNotFound] Record not found error
49
+ # @return [Notification] Group owner notification instance of this notification
50
+ def group_owner
51
+ group_owner_id.nil? ? nil : Notification.find(group_owner_id)
52
+ end
53
+
54
+ # Has many group member notification instances of this notification.
55
+ # Only group owner instance has :group_members value.
56
+ # Group member instance has nil as :group_members association.
57
+ # @scope instance
58
+ # @return [Dynamoid::Criteria::Chain] Database query of the group member notification instances of this notification
59
+ # has_many :group_members, class_name: "ActivityNotification::Notification", foreign_key: :group_owner_id
60
+ def group_members
61
+ Notification.where(group_owner_id: id)
62
+ end
63
+
64
+ # Belongs to :otifier instance of this notification.
65
+ # @scope instance
66
+ # @return [Object] Notifier instance of this notification
67
+ belongs_to_composite_xdb_record :notifier, store_with_associated_records: true
68
+
69
+ # Mandatory global secondary index to query effectively
70
+ global_secondary_index hash_key: :target_key, range_key: :created_at, projected_attributes: :all
71
+ global_secondary_index hash_key: :group_owner_id, range_key: :created_at, projected_attributes: :all
72
+ # Optional global secondary index to sort by created_at
73
+ global_secondary_index hash_key: :notifier_key, range_key: :created_at, projected_attributes: :all
74
+ global_secondary_index hash_key: :notifiable_key, range_key: :created_at, projected_attributes: :all
75
+
76
+ validates :target, presence: true
77
+ validates :notifiable, presence: true
78
+ validates :key, presence: true
79
+
80
+ %i[ all_index! unopened_index opened_index
81
+ filtered_by_association filtered_by_target filtered_by_instance filtered_by_group
82
+ filtered_by_target_type filtered_by_type filtered_by_key filtered_by_options
83
+ latest_order earliest_order latest_order! earliest_order!
84
+ group_owners_only group_members_only unopened_only opened_only! opened_only
85
+ unopened_index_group_members_only opened_index_group_members_only
86
+ within_expiration_only(expiry_delay
87
+ group_members_of_owner_ids_only
88
+ reload
89
+ latest earliest latest! earliest!
90
+ uniq_keys
91
+ ].each do |method|
92
+ # Return a criteria chain in response to a method that will begin or end a chain.
93
+ # For more information, see Dynamoid::Criteria::Chain.
94
+ singleton_class.send(:define_method, method) do |*args, &block|
95
+ # Use scan_index_forward with true as default value to convert Dynamoid::Document into Dynamoid::Criteria::Chain
96
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/document.rb
97
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/components.rb
98
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria.rb
99
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria/chain.rb
100
+ scan_index_forward(true).send(method, *args, &block)
101
+ end
102
+ end
103
+
104
+ %i[ with_target with_notifiable with_group with_group_owner with_group_members with_notifier ].each do |method|
105
+ singleton_class.send(:define_method, method) do |*args, &block|
106
+ self
107
+ end
108
+ end
109
+
110
+ # Returns if the notification is group owner.
111
+ # Calls NotificationApi#group_owner? as super method.
112
+ # @return [Boolean] If the notification is group owner
113
+ def group_owner?
114
+ super
115
+ end
116
+
117
+ # Raise ActivityNotification::DeleteRestrictionError for notifications.
118
+ # @param [String] error_text Error text for raised exception
119
+ # @raise ActivityNotification::DeleteRestrictionError
120
+ # @return [void]
121
+ def self.raise_delete_restriction_error(error_text)
122
+ raise ActivityNotification::DeleteRestrictionError, error_text
123
+ end
124
+
125
+ # Returns prepared notification object to store
126
+ # @return [Object] prepared notification object to store
127
+ # def prepare_to_store
128
+ # end
129
+
130
+ protected
131
+
132
+ # Returns count of group members of the unopened notification.
133
+ # This method is designed to cache group by query result to avoid N+1 call.
134
+ # @api protected
135
+ # @todo Avoid N+1 call
136
+ #
137
+ # @return [Integer] Count of group members of the unopened notification
138
+ def unopened_group_member_count
139
+ group_members.unopened_only.count
140
+ end
141
+
142
+ # Returns count of group members of the opened notification.
143
+ # This method is designed to cache group by query result to avoid N+1 call.
144
+ # @api protected
145
+ # @todo Avoid N+1 call
146
+ #
147
+ # @param [Integer] limit Limit to query for opened notifications
148
+ # @return [Integer] Count of group members of the opened notification
149
+ def opened_group_member_count(limit = ActivityNotification.config.opened_index_limit)
150
+ limit == 0 and return 0
151
+ group_members.opened_only(limit).to_a.length
152
+ end
153
+
154
+ # Returns count of group member notifiers of the unopened notification not including group owner notifier.
155
+ # This method is designed to cache group by query result to avoid N+1 call.
156
+ # @api protected
157
+ # @todo Avoid N+1 call
158
+ #
159
+ # @return [Integer] Count of group member notifiers of the unopened notification
160
+ def unopened_group_member_notifier_count
161
+ group_members.unopened_only
162
+ .filtered_by_association_type("notifier", notifier)
163
+ .where("notifier_key.ne": notifier_key)
164
+ .to_a
165
+ .collect {|n| n.notifier_key }.compact.uniq
166
+ .length
167
+ end
168
+
169
+ # Returns count of group member notifiers of the opened notification not including group owner notifier.
170
+ # This method is designed to cache group by query result to avoid N+1 call.
171
+ # @api protected
172
+ # @todo Avoid N+1 call
173
+ #
174
+ # @param [Integer] limit Limit to query for opened notifications
175
+ # @return [Integer] Count of group member notifiers of the opened notification
176
+ def opened_group_member_notifier_count(limit = ActivityNotification.config.opened_index_limit)
177
+ limit == 0 and return 0
178
+ group_members.opened_only(limit)
179
+ .filtered_by_association_type("notifier", notifier)
180
+ .where("notifier_key.ne": notifier_key)
181
+ .to_a
182
+ .collect {|n| n.notifier_key }.compact.uniq
183
+ .length
184
+ end
185
+
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,82 @@
1
+ require 'dynamoid'
2
+ require 'activity_notification/apis/subscription_api'
3
+
4
+ module ActivityNotification
5
+ module ORM
6
+ module Dynamoid
7
+ # Subscription model implementation generated by ActivityNotification.
8
+ class Subscription
9
+ include ::Dynamoid::Document
10
+ include ActiveModel::AttributeAssignment
11
+ include DynamoidExtension
12
+ include Association
13
+ include SubscriptionApi
14
+
15
+ table name: ActivityNotification.config.subscription_table_name, key: :id
16
+
17
+ # Belongs to target instance of this subscription as polymorphic association using composite key.
18
+ # @scope instance
19
+ # @return [Object] Target instance of this subscription
20
+ belongs_to_composite_xdb_record :target
21
+
22
+ field :key, :string
23
+ field :subscribing, :boolean, default: ActivityNotification.config.subscribe_as_default
24
+ field :subscribing_to_email, :boolean, default: ActivityNotification.config.subscribe_as_default
25
+ field :subscribed_at, :datetime
26
+ field :unsubscribed_at, :datetime
27
+ field :subscribed_to_email_at, :datetime
28
+ field :unsubscribed_to_email_at, :datetime
29
+ field :optional_targets, :raw, default: {}
30
+
31
+ global_secondary_index hash_key: :target_key, range_key: :created_at, projected_attributes: :all
32
+
33
+ validates :target, presence: true
34
+ validates :key, presence: true
35
+ validates_inclusion_of :subscribing, in: [true, false]
36
+ validates_inclusion_of :subscribing_to_email, in: [true, false]
37
+ validate :subscribing_to_email_cannot_be_true_when_subscribing_is_false
38
+ validates :subscribed_at, presence: true, if: :subscribing
39
+ validates :unsubscribed_at, presence: true, unless: :subscribing
40
+ validates :subscribed_to_email_at, presence: true, if: :subscribing_to_email
41
+ validates :unsubscribed_to_email_at, presence: true, unless: :subscribing_to_email
42
+ validate :subscribing_to_optional_target_cannot_be_true_when_subscribing_is_false
43
+
44
+ %i[ filtered_by_association filtered_by_target
45
+ filtered_by_target_type filtered_by_key filtered_by_options
46
+ latest_order earliest_order latest_order! earliest_order!
47
+ latest_subscribed_order earliest_subscribed_order key_order
48
+ reload
49
+ uniq_keys
50
+ ].each do |method|
51
+ # Return a criteria chain in response to a method that will begin or end a chain.
52
+ # For more information, see Dynamoid::Criteria::Chain.
53
+ singleton_class.send(:define_method, method) do |*args, &block|
54
+ # Use scan_index_forward with true as default value to convert Dynamoid::Document into Dynamoid::Criteria::Chain
55
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/document.rb
56
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/components.rb
57
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria.rb
58
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/criteria/chain.rb
59
+ scan_index_forward(true).send(method, *args, &block)
60
+ end
61
+ end
62
+
63
+ %i[ with_target ].each do |method|
64
+ singleton_class.send(:define_method, method) do |*args, &block|
65
+ self
66
+ end
67
+ end
68
+
69
+ # Initialize without options to use Dynamoid.config.store_datetime_as_string
70
+ # https://github.com/Dynamoid/dynamoid/blob/master/lib/dynamoid/dumping.rb
71
+ @@date_time_dumper = ::Dynamoid::Dumping::DateTimeDumper.new({})
72
+
73
+ # Convert Time value to store in database as Hash value.
74
+ # @param [Time] time Time value to store in database as Hash value
75
+ # @return [Integer, String] Converted Time value
76
+ def self.convert_time_as_hash(time)
77
+ @@date_time_dumper.process(time)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end