wfl_simple_activity 0.1.25 → 0.1.26

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/public_activity.rb +70 -0
  3. data/lib/public_activity/.DS_Store +0 -0
  4. data/lib/public_activity/actions/creation.rb +19 -0
  5. data/lib/public_activity/actions/destruction.rb +19 -0
  6. data/lib/public_activity/actions/update.rb +20 -0
  7. data/lib/public_activity/activity.rb +8 -0
  8. data/lib/public_activity/common.rb +363 -0
  9. data/lib/public_activity/config.rb +102 -0
  10. data/lib/public_activity/models/activist.rb +11 -0
  11. data/lib/public_activity/models/activity.rb +6 -0
  12. data/lib/public_activity/models/adapter.rb +7 -0
  13. data/lib/public_activity/models/trackable.rb +11 -0
  14. data/lib/public_activity/orm/.DS_Store +0 -0
  15. data/lib/public_activity/orm/active_record.rb +7 -0
  16. data/lib/public_activity/orm/active_record/activist.rb +35 -0
  17. data/lib/public_activity/orm/active_record/activity.rb +66 -0
  18. data/lib/public_activity/orm/active_record/adapter.rb +23 -0
  19. data/lib/public_activity/orm/active_record/trackable.rb +17 -0
  20. data/lib/public_activity/orm/mongo_mapper.rb +6 -0
  21. data/lib/public_activity/orm/mongo_mapper/activist.rb +36 -0
  22. data/lib/public_activity/orm/mongo_mapper/activity.rb +35 -0
  23. data/lib/public_activity/orm/mongo_mapper/adapter.rb +19 -0
  24. data/lib/public_activity/orm/mongo_mapper/trackable.rb +13 -0
  25. data/lib/public_activity/orm/mongoid.rb +6 -0
  26. data/lib/public_activity/orm/mongoid/activist.rb +36 -0
  27. data/lib/public_activity/orm/mongoid/activity.rb +34 -0
  28. data/lib/public_activity/orm/mongoid/adapter.rb +19 -0
  29. data/lib/public_activity/orm/mongoid/trackable.rb +13 -0
  30. data/lib/public_activity/renderable.rb +166 -0
  31. data/lib/public_activity/roles/deactivatable.rb +44 -0
  32. data/lib/public_activity/roles/tracked.rb +196 -0
  33. data/lib/public_activity/testing.rb +37 -0
  34. data/lib/public_activity/utility/store_controller.rb +32 -0
  35. data/lib/public_activity/utility/view_helpers.rb +30 -0
  36. data/lib/public_activity/version.rb +6 -0
  37. data/lib/wfl_simple_activity.rb +0 -1
  38. data/lib/wfl_simple_activity/version.rb +1 -1
  39. metadata +36 -2
  40. data/lib/wfl_simple_activity/common_activity.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a272f8fb44df29e56b63bc2ea9ff9c510bc52c640db3fad187db8f0342a9acb4
4
- data.tar.gz: 9d95b48f3e7cd8e94473969b8c49c700ee90409a307d1eb11650032f7323fcba
3
+ metadata.gz: dc03e54672b586137ce5fe4e3ee06a37abcf52d7d816f8097c29c18043f48e3a
4
+ data.tar.gz: 259e52c170b84eaf70ee134a83506b14cb4b64cc9b1359db8fbaf7c3e977e430
5
5
  SHA512:
6
- metadata.gz: de5f2c9ee42e71ac51ac06314b3e78c302b3c1b47daa505d4d7767836b50a79a3262657c3df451bd6f2d96514a5c160cf51f675239ec7cfadd12b0ff26f70150
7
- data.tar.gz: 51fb44f0b85306dba1c503f737a471f596630c2fefb12268da9c6a02454147308a25f15578249b319ae0698018ada92a1a7ec3e266371d5d61cdc5d5ee56024b
6
+ metadata.gz: ce8e6aaf0ca27dc8f52c6292d214721e9c21271ca5a0d7f2b86d1615240494bda1766be26dd4c77c55e3dc4f2089be9abe39212e937a7a0056dad79212c43c3f
7
+ data.tar.gz: 050706120e5e770b58f9ab3fbd54304a0418ff3a3ed97eb051e64b4ce93128e4ea9995ee81007826dab17a9728631e7f35dfcde3a452bc93fb0408d7380b7365
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'action_view'
5
+ # +public_activity+ keeps track of changes made to models
6
+ # and allows you to display them to the users.
7
+ #
8
+ # Check {PublicActivity::Tracked::ClassMethods#tracked} for more details about customizing and specifying
9
+ # ownership to users.
10
+ module PublicActivity
11
+ extend ActiveSupport::Concern
12
+ extend ActiveSupport::Autoload
13
+
14
+ autoload :Activity, 'public_activity/models/activity'
15
+ autoload :Activist, 'public_activity/models/activist'
16
+ autoload :Adapter, 'public_activity/models/adapter'
17
+ autoload :Trackable, 'public_activity/models/trackable'
18
+ autoload :Common
19
+ autoload :Config
20
+ autoload :Creation, 'public_activity/actions/creation.rb'
21
+ autoload :Deactivatable,'public_activity/roles/deactivatable.rb'
22
+ autoload :Destruction, 'public_activity/actions/destruction.rb'
23
+ autoload :Renderable
24
+ autoload :Tracked, 'public_activity/roles/tracked.rb'
25
+ autoload :Update, 'public_activity/actions/update.rb'
26
+ autoload :VERSION
27
+
28
+ # Switches PublicActivity on or off.
29
+ # @param value [Boolean]
30
+ # @since 0.5.0
31
+ def self.enabled=(value)
32
+ config.enabled(value)
33
+ end
34
+
35
+ # Returns `true` if PublicActivity is on, `false` otherwise.
36
+ # Enabled by default.
37
+ # @return [Boolean]
38
+ # @since 0.5.0
39
+ def self.enabled?
40
+ config.enabled
41
+ end
42
+
43
+ # Returns PublicActivity's configuration object.
44
+ # @since 0.5.0
45
+ def self.config
46
+ @@config ||= PublicActivity::Config.instance
47
+ end
48
+
49
+ # Method used to choose which ORM to load
50
+ # when PublicActivity::Activity class is being autoloaded
51
+ def self.inherit_orm(model="Activity")
52
+ orm = PublicActivity.config.orm
53
+ require "public_activity/orm/#{orm.to_s}"
54
+ "PublicActivity::ORM::#{orm.to_s.classify}::#{model}".constantize
55
+ end
56
+
57
+ # Module to be included in ActiveRecord models. Adds required functionality.
58
+ module Model
59
+ extend ActiveSupport::Concern
60
+ included do
61
+ include Common
62
+ include Deactivatable
63
+ include Tracked
64
+ include Activist # optional associations by recipient|owner
65
+ end
66
+ end
67
+ end
68
+
69
+ require 'public_activity/utility/store_controller'
70
+ require 'public_activity/utility/view_helpers'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PublicActivity
4
+ # Handles creation of Activities upon destruction and update of tracked model.
5
+ module Creation
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ after_create :activity_on_create
10
+ end
11
+
12
+ private
13
+
14
+ # Creates activity upon creation of the tracked model
15
+ def activity_on_create
16
+ create_activity(:create)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PublicActivity
4
+ # Handles creation of Activities upon destruction of tracked model.
5
+ module Destruction
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_destroy :activity_on_destroy
10
+ end
11
+
12
+ private
13
+
14
+ # Records an activity upon destruction of the tracked model
15
+ def activity_on_destroy
16
+ create_activity(:destroy)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PublicActivity
4
+ # Handles creation of Activities upon destruction and update of tracked model.
5
+ module Update
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ after_update :activity_on_update
10
+ end
11
+
12
+ private
13
+
14
+ # Creates activity upon modification of the tracked model
15
+ def activity_on_update
16
+ # Either use #changed? method for Rails < 5.1 or #saved_changes? for recent versions
17
+ create_activity(:update) if respond_to?(:saved_changes?) ? saved_changes? : changed?
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PublicActivity
4
+ # Main model, stores all information about what happened,
5
+ # who caused it, when and anything else.
6
+ class Activity < inherit_orm("Activity")
7
+ end
8
+ end
@@ -0,0 +1,363 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PublicActivity
4
+ # Happens when creating custom activities without either action or a key.
5
+ class NoKeyProvided < Exception; end
6
+
7
+ # Used to smartly transform value from metadata to data.
8
+ # Accepts Symbols, which it will send against context.
9
+ # Accepts Procs, which it will execute with controller and context.
10
+ # @since 0.4.0
11
+ def self.resolve_value(context, thing)
12
+ case thing
13
+ when Symbol
14
+ context.__send__(thing)
15
+ when Proc
16
+ thing.call(PublicActivity.get_controller, context)
17
+ else
18
+ thing
19
+ end
20
+ end
21
+
22
+ # Common methods shared across the gem.
23
+ module Common
24
+ extend ActiveSupport::Concern
25
+
26
+ included do
27
+ include Trackable
28
+ class_attribute :activity_owner_global, :activity_recipient_global,
29
+ :activity_params_global, :activity_hooks, :activity_custom_fields_global
30
+ set_public_activity_class_defaults
31
+ end
32
+
33
+ # @!group Global options
34
+
35
+ # @!attribute activity_owner_global
36
+ # Global version of activity owner
37
+ # @see #activity_owner
38
+ # @return [Model]
39
+
40
+ # @!attribute activity_recipient_global
41
+ # Global version of activity recipient
42
+ # @see #activity_recipient
43
+ # @return [Model]
44
+
45
+ # @!attribute activity_params_global
46
+ # Global version of activity parameters
47
+ # @see #activity_params
48
+ # @return [Hash<Symbol, Object>]
49
+
50
+ # @!attribute activity_hooks
51
+ # @return [Hash<Symbol, Proc>]
52
+ # Hooks/functions that will be used to decide *if* the activity should get
53
+ # created.
54
+ #
55
+ # The supported keys are:
56
+ # * :create
57
+ # * :update
58
+ # * :destroy
59
+
60
+ # @!endgroup
61
+
62
+ # @!group Instance options
63
+
64
+ # Set or get parameters that will be passed to {Activity} when saving
65
+ #
66
+ # == Usage:
67
+ #
68
+ # @article.activity_params = {:article_title => @article.title}
69
+ # @article.save
70
+ #
71
+ # This way you can pass strings that should remain constant, even when model attributes
72
+ # change after creating this {Activity}.
73
+ # @return [Hash<Symbol, Object>]
74
+ attr_accessor :activity_params
75
+ @activity_params = {}
76
+ # Set or get owner object responsible for the {Activity}.
77
+ #
78
+ # == Usage:
79
+ #
80
+ # # where current_user is an object of logged in user
81
+ # @article.activity_owner = current_user
82
+ # # OR: take @article.author association
83
+ # @article.activity_owner = :author
84
+ # # OR: provide a Proc with custom code
85
+ # @article.activity_owner = proc {|controller, model| model.author }
86
+ # @article.save
87
+ # @article.activities.last.owner #=> Returns owner object
88
+ # @return [Model] Polymorphic model
89
+ # @see #activity_owner_global
90
+ attr_accessor :activity_owner
91
+ @activity_owner = nil
92
+
93
+ # Set or get recipient for activity.
94
+ #
95
+ # Association is polymorphic, thus allowing assignment of
96
+ # all types of models. This can be used for example in the case of sending
97
+ # private notifications for only a single user.
98
+ # @return (see #activity_owner)
99
+ attr_accessor :activity_recipient
100
+ @activity_recipient = nil
101
+ # Set or get custom i18n key passed to {Activity}, later used in {Renderable#text}
102
+ #
103
+ # == Usage:
104
+ #
105
+ # @article = Article.new
106
+ # @article.activity_key = "my.custom.article.key"
107
+ # @article.save
108
+ # @article.activities.last.key #=> "my.custom.article.key"
109
+ #
110
+ # @return [String]
111
+ attr_accessor :activity_key
112
+ @activity_key = nil
113
+
114
+ # Set or get custom fields for later processing
115
+ #
116
+ # @return [Hash]
117
+ attr_accessor :activity_custom_fields
118
+ @activity_custom_fields = {}
119
+
120
+ # @!visibility private
121
+ @@activity_hooks = {}
122
+
123
+ # @!endgroup
124
+
125
+ # Provides some global methods for every model class.
126
+ module ClassMethods
127
+ #
128
+ # @since 1.0.0
129
+ # @api private
130
+ def set_public_activity_class_defaults
131
+ self.activity_owner_global = nil
132
+ self.activity_recipient_global = nil
133
+ self.activity_params_global = {}
134
+ self.activity_hooks = {}
135
+ self.activity_custom_fields_global = {}
136
+ end
137
+
138
+ # Extracts a hook from the _:on_ option provided in
139
+ # {Tracked::ClassMethods#tracked}. Returns nil when no hook exists for
140
+ # given action
141
+ # {Common#get_hook}
142
+ #
143
+ # @see Tracked#get_hook
144
+ # @param key [String, Symbol] action to retrieve a hook for
145
+ # @return [Proc, nil] callable hook or nil
146
+ # @since 0.4.0
147
+ # @api private
148
+ def get_hook(key)
149
+ key = key.to_sym
150
+ if self.activity_hooks.has_key?(key) and self.activity_hooks[key].is_a? Proc
151
+ self.activity_hooks[key]
152
+ else
153
+ nil
154
+ end
155
+ end
156
+ end
157
+ #
158
+ # Returns true if PublicActivity is enabled
159
+ # globally and for this class.
160
+ # @return [Boolean]
161
+ # @api private
162
+ # @since 0.5.0
163
+ def public_activity_enabled?
164
+ PublicActivity.enabled?
165
+ end
166
+ #
167
+ # Shortcut for {ClassMethods#get_hook}
168
+ # @param (see ClassMethods#get_hook)
169
+ # @return (see ClassMethods#get_hook)
170
+ # @since (see ClassMethods#get_hook)
171
+ # @api (see ClassMethods#get_hook)
172
+ def get_hook(key)
173
+ self.class.get_hook(key)
174
+ end
175
+
176
+ # Calls hook safely.
177
+ # If a hook for given action exists, calls it with model (self) and
178
+ # controller (if available, see {StoreController})
179
+ # @param key (see #get_hook)
180
+ # @return [Boolean] if hook exists, it's decision, if there's no hook, true
181
+ # @since 0.4.0
182
+ # @api private
183
+ def call_hook_safe(key)
184
+ hook = self.get_hook(key)
185
+ if hook
186
+ # provides hook with model and controller
187
+ hook.call(self, PublicActivity.get_controller)
188
+ else
189
+ true
190
+ end
191
+ end
192
+
193
+ # Directly creates activity record in the database, based on supplied options.
194
+ #
195
+ # It's meant for creating custom activities while *preserving* *all*
196
+ # *configuration* defined before. If you fire up the simplest of options:
197
+ #
198
+ # current_user.create_activity(:avatar_changed)
199
+ #
200
+ # It will still gather data from any procs or symbols you passed as params
201
+ # to {Tracked::ClassMethods#tracked}. It will ask the hooks you defined
202
+ # whether to really save this activity.
203
+ #
204
+ # But you can also overwrite instance and global settings with your options:
205
+ #
206
+ # @article.activity :owner => proc {|controller| controller.current_user }
207
+ # @article.create_activity(:commented_on, :owner => @user)
208
+ #
209
+ # And it's smart! It won't execute your proc, since you've chosen to
210
+ # overwrite instance parameter _:owner_ with @user.
211
+ #
212
+ # [:key]
213
+ # The key will be generated from either:
214
+ # * the first parameter you pass that is not a hash (*action*)
215
+ # * the _:action_ option in the options hash (*action*)
216
+ # * the _:key_ option in the options hash (it has to be a full key,
217
+ # including model name)
218
+ # When you pass an *action* (first two options above), they will be
219
+ # added to parameterized model name:
220
+ #
221
+ # Given Article model and instance: @article,
222
+ #
223
+ # @article.create_activity :commented_on
224
+ # @article.activities.last.key # => "article.commented_on"
225
+ #
226
+ # For other parameters, see {Tracked#activity}, and "Instance options"
227
+ # accessors at {Tracked}, information on hooks is available at
228
+ # {Tracked::ClassMethods#tracked}.
229
+ # @see #prepare_settings
230
+ # @return [Model, nil] If created successfully, new activity
231
+ # @since 0.4.0
232
+ # @api public
233
+ # @overload create_activity(action, options = {})
234
+ # @param [Symbol,String] action Name of the action
235
+ # @param [Hash] options Options with quality higher than instance options
236
+ # set in {Tracked#activity}
237
+ # @option options [Activist] :owner Owner
238
+ # @option options [Activist] :recipient Recipient
239
+ # @option options [Hash] :params Parameters, see
240
+ # {PublicActivity.resolve_value}
241
+ # @overload create_activity(options = {})
242
+ # @param [Hash] options Options with quality higher than instance options
243
+ # set in {Tracked#activity}
244
+ # @option options [Symbol,String] :action Name of the action
245
+ # @option options [String] :key Full key
246
+ # @option options [Activist] :owner Owner
247
+ # @option options [Activist] :recipient Recipient
248
+ # @option options [Hash] :params Parameters, see
249
+ # {PublicActivity.resolve_value}
250
+ def create_activity(*args)
251
+ return unless self.public_activity_enabled?
252
+ options = prepare_settings(*args)
253
+
254
+ if call_hook_safe(options[:key].split('.').last)
255
+ reset_activity_instance_options
256
+ return PublicActivity::Adapter.create_activity(self, options)
257
+ end
258
+
259
+ nil
260
+ end
261
+
262
+ # Directly saves activity to database. Works the same as create_activity
263
+ # but throws validation error for each supported ORM.
264
+ #
265
+ # @see #create_activity
266
+ def create_activity!(*args)
267
+ return unless self.public_activity_enabled?
268
+ options = prepare_settings(*args)
269
+
270
+ if call_hook_safe(options[:key].split('.').last)
271
+ reset_activity_instance_options
272
+ return PublicActivity::Adapter.create_activity!(self, options)
273
+ end
274
+ end
275
+
276
+ # Prepares settings used during creation of Activity record.
277
+ # params passed directly to tracked model have priority over
278
+ # settings specified in tracked() method
279
+ #
280
+ # @see #create_activity
281
+ # @return [Hash] Settings with preserved options that were passed
282
+ # @api private
283
+ # @overload prepare_settings(action, options = {})
284
+ # @see #create_activity
285
+ # @overload prepare_settings(options = {})
286
+ # @see #create_activity
287
+ def prepare_settings(*args)
288
+ raw_options = args.extract_options!
289
+ action = [args.first, raw_options.delete(:action)].compact.first
290
+ key = prepare_key(action, raw_options)
291
+
292
+ raise NoKeyProvided, "No key provided for #{self.class.name}" unless key
293
+
294
+ prepare_custom_fields(raw_options.except(:params)).merge(
295
+ {
296
+ key: key,
297
+ owner: prepare_relation(:owner, raw_options),
298
+ recipient: prepare_relation(:recipient, raw_options),
299
+ parameters: prepare_parameters(raw_options),
300
+ }
301
+ )
302
+ end
303
+
304
+ # Prepares and resolves custom fields
305
+ # users can pass to `tracked` method
306
+ # @private
307
+ def prepare_custom_fields(options)
308
+ customs = self.class.activity_custom_fields_global.clone
309
+ customs.merge!(self.activity_custom_fields) if self.activity_custom_fields
310
+ customs.merge!(options)
311
+ customs.each do |k, v|
312
+ customs[k] = PublicActivity.resolve_value(self, v)
313
+ end
314
+ end
315
+
316
+ # Prepares i18n parameters that will
317
+ # be serialized into the Activity#parameters column
318
+ # @private
319
+ def prepare_parameters(options)
320
+ params = {}
321
+ params.merge!(self.class.activity_params_global)
322
+ params.merge!(self.activity_params) if self.activity_params
323
+ params.merge!([options.delete(:parameters), options.delete(:params), {}].compact.first)
324
+ params.each { |k, v| params[k] = PublicActivity.resolve_value(self, v) }
325
+ end
326
+
327
+ # Prepares relation to be saved
328
+ # to Activity. Can be :recipient or :owner
329
+ # @private
330
+ def prepare_relation(name, options)
331
+ PublicActivity.resolve_value(self,
332
+ (options.has_key?(name) ? options[name] : (
333
+ self.send("activity_#{name}") || self.class.send("activity_#{name}_global")
334
+ )
335
+ )
336
+ )
337
+ end
338
+
339
+ # Helper method to serialize class name into relevant key
340
+ # @return [String] the resulted key
341
+ # @param [Symbol] or [String] the name of the operation to be done on class
342
+ # @param [Hash] options to be used on key generation, defaults to {}
343
+ def prepare_key(action, options = {})
344
+ (
345
+ options[:key] ||
346
+ self.activity_key ||
347
+ ((self.class.name.underscore.gsub('/', '_') + "." + action.to_s) if action)
348
+ ).try(:to_s)
349
+ end
350
+
351
+ # Resets all instance options on the object
352
+ # triggered by a successful #create_activity, should not be
353
+ # called from any other place, or from application code.
354
+ # @private
355
+ def reset_activity_instance_options
356
+ @activity_params = {}
357
+ @activity_key = nil
358
+ @activity_owner = nil
359
+ @activity_recipient = nil
360
+ @activity_custom_fields = {}
361
+ end
362
+ end
363
+ end