activity_notification 1.7.1 → 2.0.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 (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