activity_hub 0.0.1
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.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +260 -0
- data/Rakefile +20 -0
- data/lib/generators/public_activity.rb +16 -0
- data/lib/generators/public_activity/migration/migration_generator.rb +19 -0
- data/lib/generators/public_activity/migration_upgrade/migration_upgrade_generator.rb +19 -0
- data/lib/generators/public_activity/migration_upgrade/templates/upgrade.rb +11 -0
- data/lib/public_activity.rb +70 -0
- data/lib/public_activity/actions/creation.rb +19 -0
- data/lib/public_activity/actions/destruction.rb +19 -0
- data/lib/public_activity/actions/update.rb +20 -0
- data/lib/public_activity/activity.rb +8 -0
- data/lib/public_activity/common.rb +363 -0
- data/lib/public_activity/config.rb +102 -0
- data/lib/public_activity/models/activist.rb +11 -0
- data/lib/public_activity/models/activity.rb +6 -0
- data/lib/public_activity/models/adapter.rb +7 -0
- data/lib/public_activity/models/trackable.rb +11 -0
- data/lib/public_activity/orm/active_record.rb +7 -0
- data/lib/public_activity/orm/active_record/activist.rb +35 -0
- data/lib/public_activity/orm/active_record/activity.rb +66 -0
- data/lib/public_activity/orm/active_record/adapter.rb +23 -0
- data/lib/public_activity/orm/active_record/trackable.rb +17 -0
- data/lib/public_activity/orm/mongo_mapper.rb +6 -0
- data/lib/public_activity/orm/mongo_mapper/activist.rb +36 -0
- data/lib/public_activity/orm/mongo_mapper/activity.rb +35 -0
- data/lib/public_activity/orm/mongo_mapper/adapter.rb +19 -0
- data/lib/public_activity/orm/mongo_mapper/trackable.rb +13 -0
- data/lib/public_activity/orm/mongoid.rb +6 -0
- data/lib/public_activity/orm/mongoid/activist.rb +36 -0
- data/lib/public_activity/orm/mongoid/activity.rb +34 -0
- data/lib/public_activity/orm/mongoid/adapter.rb +19 -0
- data/lib/public_activity/orm/mongoid/trackable.rb +13 -0
- data/lib/public_activity/renderable.rb +166 -0
- data/lib/public_activity/roles/deactivatable.rb +44 -0
- data/lib/public_activity/roles/tracked.rb +196 -0
- data/lib/public_activity/testing.rb +37 -0
- data/lib/public_activity/utility/store_controller.rb +32 -0
- data/lib/public_activity/utility/view_helpers.rb +30 -0
- data/lib/public_activity/version.rb +6 -0
- data/test/migrations/001_create_activities.rb +25 -0
- data/test/migrations/002_create_articles.rb +15 -0
- data/test/migrations/003_create_users.rb +12 -0
- data/test/migrations/004_add_nonstandard_to_activities.rb +11 -0
- data/test/migrations_base.rb +7 -0
- data/test/mongo_mapper.yml +4 -0
- data/test/mongoid.yml +6 -0
- data/test/test_activist.rb +58 -0
- data/test/test_activity.rb +89 -0
- data/test/test_common.rb +194 -0
- data/test/test_controller_integration.rb +42 -0
- data/test/test_generators.rb +31 -0
- data/test/test_helper.rb +144 -0
- data/test/test_testing.rb +37 -0
- data/test/test_tracking.rb +385 -0
- data/test/test_view_helpers.rb +38 -0
- data/test/views/custom/_layout.erb +1 -0
- data/test/views/custom/_test.erb +1 -0
- data/test/views/layouts/_activity.erb +1 -0
- data/test/views/public_activity/_test.erb +8 -0
- metadata +295 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PublicActivity
|
|
4
|
+
# Enables per-class disabling of PublicActivity functionality.
|
|
5
|
+
module Deactivatable
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
class_attribute :public_activity_enabled_for_model
|
|
10
|
+
set_public_activity_class_defaults
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Returns true if PublicActivity is enabled
|
|
14
|
+
# globally and for this class.
|
|
15
|
+
# @return [Boolean]
|
|
16
|
+
# @api private
|
|
17
|
+
# @since 0.5.0
|
|
18
|
+
# overrides the method from Common
|
|
19
|
+
def public_activity_enabled?
|
|
20
|
+
PublicActivity.enabled? && self.class.public_activity_enabled_for_model
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Provides global methods to disable or enable PublicActivity on a per-class
|
|
24
|
+
# basis.
|
|
25
|
+
module ClassMethods
|
|
26
|
+
# Switches public_activity off for this class
|
|
27
|
+
def public_activity_off
|
|
28
|
+
self.public_activity_enabled_for_model = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Switches public_activity on for this class
|
|
32
|
+
def public_activity_on
|
|
33
|
+
self.public_activity_enabled_for_model = true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @since 1.0.0
|
|
37
|
+
# @api private
|
|
38
|
+
def set_public_activity_class_defaults
|
|
39
|
+
super
|
|
40
|
+
self.public_activity_enabled_for_model = true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PublicActivity
|
|
4
|
+
# Main module extending classes we want to keep track of.
|
|
5
|
+
module Tracked
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
# A shortcut method for setting custom key, owner and parameters of {Activity}
|
|
8
|
+
# in one line. Accepts a hash with 3 keys:
|
|
9
|
+
# :key, :owner, :params. You can specify all of them or just the ones you want to overwrite.
|
|
10
|
+
#
|
|
11
|
+
# == Options
|
|
12
|
+
#
|
|
13
|
+
# [:key]
|
|
14
|
+
# See {Common#activity_key}
|
|
15
|
+
# [:owner]
|
|
16
|
+
# See {Common#activity_owner}
|
|
17
|
+
# [:params]
|
|
18
|
+
# See {Common#activity_params}
|
|
19
|
+
# [:recipient]
|
|
20
|
+
# Set the recipient for this activity. Useful for private notifications, which should only be visible to a certain user. See {Common#activity_recipient}.
|
|
21
|
+
# @example
|
|
22
|
+
#
|
|
23
|
+
# @article = Article.new
|
|
24
|
+
# @article.title = "New article"
|
|
25
|
+
# @article.activity :key => "my.custom.article.key", :owner => @article.author, :params => {:title => @article.title}
|
|
26
|
+
# @article.save
|
|
27
|
+
# @article.activities.last.key #=> "my.custom.article.key"
|
|
28
|
+
# @article.activities.last.parameters #=> {:title => "New article"}
|
|
29
|
+
#
|
|
30
|
+
# @param options [Hash] instance options to set on the tracked model
|
|
31
|
+
# @return [nil]
|
|
32
|
+
def activity(options = {})
|
|
33
|
+
rest = options.clone
|
|
34
|
+
self.activity_key = rest.delete(:key) if rest[:key]
|
|
35
|
+
self.activity_owner = rest.delete(:owner) if rest[:owner]
|
|
36
|
+
self.activity_params = rest.delete(:params) if rest[:params]
|
|
37
|
+
self.activity_recipient = rest.delete(:recipient) if rest[:recipient]
|
|
38
|
+
self.activity_custom_fields = rest if rest.count > 0
|
|
39
|
+
nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Module with basic +tracked+ method that enables tracking models.
|
|
43
|
+
module ClassMethods
|
|
44
|
+
# Adds required callbacks for creating and updating
|
|
45
|
+
# tracked models and adds +activities+ relation for listing
|
|
46
|
+
# associated activities.
|
|
47
|
+
#
|
|
48
|
+
# == Parameters:
|
|
49
|
+
# [:owner]
|
|
50
|
+
# Specify the owner of the {Activity} (person responsible for the action).
|
|
51
|
+
# It can be a Proc, Symbol or an ActiveRecord object:
|
|
52
|
+
# == Examples:
|
|
53
|
+
#
|
|
54
|
+
# tracked :owner => :author
|
|
55
|
+
# tracked :owner => proc {|o| o.author}
|
|
56
|
+
#
|
|
57
|
+
# Keep in mind that owner relation is polymorphic, so you can't just
|
|
58
|
+
# provide id number of the owner object.
|
|
59
|
+
# [:recipient]
|
|
60
|
+
# Specify the recipient of the {Activity}
|
|
61
|
+
# It can be a Proc, Symbol, or an ActiveRecord object
|
|
62
|
+
# == Examples:
|
|
63
|
+
#
|
|
64
|
+
# tracked :recipient => :author
|
|
65
|
+
# tracked :recipient => proc {|o| o.author}
|
|
66
|
+
#
|
|
67
|
+
# Keep in mind that recipient relation is polymorphic, so you can't just
|
|
68
|
+
# provide id number of the owner object.
|
|
69
|
+
# [:params]
|
|
70
|
+
# Accepts a Hash with custom parameters you want to pass to i18n.translate
|
|
71
|
+
# method. It is later used in {Renderable#text} method.
|
|
72
|
+
# == Example:
|
|
73
|
+
# class Article < ActiveRecord::Base
|
|
74
|
+
# include PublicActivity::Model
|
|
75
|
+
# tracked :params => {
|
|
76
|
+
# :title => :title,
|
|
77
|
+
# :author_name => "Michael",
|
|
78
|
+
# :category_name => proc {|controller, model_instance| model_instance.category.name},
|
|
79
|
+
# :summary => proc {|controller, model_instance| truncate(model.text, :length => 30)}
|
|
80
|
+
# }
|
|
81
|
+
# end
|
|
82
|
+
#
|
|
83
|
+
# Values in the :params hash can either be an *exact* *value*, a *Proc/Lambda* executed before saving the activity or a *Symbol*
|
|
84
|
+
# which is a an attribute or a method name executed on the tracked model's instance.
|
|
85
|
+
#
|
|
86
|
+
# Everything specified here has a lower priority than parameters
|
|
87
|
+
# specified directly in {#activity} method.
|
|
88
|
+
# So treat it as a place where you provide 'default' values or where you
|
|
89
|
+
# specify what data should be gathered for every activity.
|
|
90
|
+
# For more dynamic settings refer to {Activity} model documentation.
|
|
91
|
+
# [:skip_defaults]
|
|
92
|
+
# Disables recording of activities on create/update/destroy leaving that to programmer's choice. Check {PublicActivity::Common#create_activity}
|
|
93
|
+
# for a guide on how to manually record activities.
|
|
94
|
+
# [:only]
|
|
95
|
+
# Accepts a symbol or an array of symbols, of which any combination of the three is accepted:
|
|
96
|
+
# * _:create_
|
|
97
|
+
# * _:update_
|
|
98
|
+
# * _:destroy_
|
|
99
|
+
# Selecting one or more of these will make PublicActivity create activities
|
|
100
|
+
# automatically for the tracked model on selected actions.
|
|
101
|
+
#
|
|
102
|
+
# Resulting activities will have have keys assigned to, respectively:
|
|
103
|
+
# * _article.create_
|
|
104
|
+
# * _article.update_
|
|
105
|
+
# * _article.destroy_
|
|
106
|
+
# Since only three options are valid,
|
|
107
|
+
# see _:except_ option for a shorter version
|
|
108
|
+
# [:except]
|
|
109
|
+
# Accepts a symbol or an array of symbols with values like in _:only_, above.
|
|
110
|
+
# Values provided will be subtracted from all default actions:
|
|
111
|
+
# (create, update, destroy).
|
|
112
|
+
#
|
|
113
|
+
# So, passing _create_ would track and automatically create
|
|
114
|
+
# activities on _update_ and _destroy_ actions,
|
|
115
|
+
# but not on the _create_ action.
|
|
116
|
+
# [:on]
|
|
117
|
+
# Accepts a Hash with key being the *action* on which to execute *value* (proc)
|
|
118
|
+
# Currently supported only for CRUD actions which are enabled in _:only_
|
|
119
|
+
# or _:except_ options on this method.
|
|
120
|
+
#
|
|
121
|
+
# Key-value pairs in this option define callbacks that can decide
|
|
122
|
+
# whether to create an activity or not. Procs have two attributes for
|
|
123
|
+
# use: _model_ and _controller_. If the proc returns true, the activity
|
|
124
|
+
# will be created, if not, then activity will not be saved.
|
|
125
|
+
#
|
|
126
|
+
# == Example:
|
|
127
|
+
# # app/models/article.rb
|
|
128
|
+
# tracked :on => {:update => proc {|model, controller| model.published? }}
|
|
129
|
+
#
|
|
130
|
+
# In the example above, given a model Article with boolean column _published_.
|
|
131
|
+
# The activities with key _article.update_ will only be created
|
|
132
|
+
# if the published status is set to true on that article.
|
|
133
|
+
# @param opts [Hash] options
|
|
134
|
+
# @return [nil] options
|
|
135
|
+
def tracked(opts = {})
|
|
136
|
+
options = opts.clone
|
|
137
|
+
|
|
138
|
+
include_default_actions(options)
|
|
139
|
+
|
|
140
|
+
assign_globals options
|
|
141
|
+
assign_hooks options
|
|
142
|
+
assign_custom_fields options
|
|
143
|
+
|
|
144
|
+
nil
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def include_default_actions(options)
|
|
148
|
+
defaults = {
|
|
149
|
+
create: Creation,
|
|
150
|
+
destroy: Destruction,
|
|
151
|
+
update: Update
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if options[:skip_defaults] == true
|
|
155
|
+
return
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
modules = if options[:except]
|
|
159
|
+
defaults.except(*options[:except])
|
|
160
|
+
elsif options[:only]
|
|
161
|
+
defaults.slice(*options[:only])
|
|
162
|
+
else
|
|
163
|
+
defaults
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
modules.each do |key, value|
|
|
167
|
+
include value
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def available_options
|
|
172
|
+
[:skip_defaults, :only, :except, :on, :owner, :recipient, :params].freeze
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def assign_globals(options)
|
|
176
|
+
[:owner, :recipient, :params].each do |key|
|
|
177
|
+
if options[key]
|
|
178
|
+
self.send("activity_#{key}_global=".to_sym, options.delete(key))
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def assign_hooks(options)
|
|
184
|
+
if options[:on].is_a?(Hash)
|
|
185
|
+
self.activity_hooks = options[:on].select {|_, v| v.is_a? Proc}.symbolize_keys
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def assign_custom_fields(options)
|
|
190
|
+
options.except(*available_options).each do |k, v|
|
|
191
|
+
self.activity_custom_fields_global[k] = v
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file provides functionality for testing your code with public_activity
|
|
4
|
+
# activated or deactivated.
|
|
5
|
+
# This file should only be required in test/spec code!
|
|
6
|
+
#
|
|
7
|
+
# To enable PublicActivity testing capabilities do:
|
|
8
|
+
# require 'public_activity/testing'
|
|
9
|
+
module PublicActivity
|
|
10
|
+
# Execute the code block with PublicActiviy active
|
|
11
|
+
#
|
|
12
|
+
# Example usage:
|
|
13
|
+
# PublicActivity.with_tracking do
|
|
14
|
+
# # your test code here
|
|
15
|
+
# end
|
|
16
|
+
def self.with_tracking
|
|
17
|
+
current = PublicActivity.config.enabled
|
|
18
|
+
PublicActivity.config.enabled(true)
|
|
19
|
+
yield
|
|
20
|
+
ensure
|
|
21
|
+
PublicActivity.config.enabled(current)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Execute the code block with PublicActiviy deactive
|
|
25
|
+
#
|
|
26
|
+
# Example usage:
|
|
27
|
+
# PublicActivity.without_tracking do
|
|
28
|
+
# # your test code here
|
|
29
|
+
# end
|
|
30
|
+
def self.without_tracking
|
|
31
|
+
current = PublicActivity.enabled?
|
|
32
|
+
PublicActivity.config.enabled(false)
|
|
33
|
+
yield
|
|
34
|
+
ensure
|
|
35
|
+
PublicActivity.config.enabled(current)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PublicActivity
|
|
4
|
+
class << self
|
|
5
|
+
# Setter for remembering controller instance
|
|
6
|
+
def set_controller(controller)
|
|
7
|
+
Thread.current[:public_activity_controller] = controller
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Getter for accessing the controller instance
|
|
11
|
+
def get_controller
|
|
12
|
+
Thread.current[:public_activity_controller]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Module included in controllers to allow p_a access to controller instance
|
|
17
|
+
module StoreController
|
|
18
|
+
extend ActiveSupport::Concern
|
|
19
|
+
|
|
20
|
+
included do
|
|
21
|
+
around_action :store_controller_for_public_activity if respond_to?(:around_action)
|
|
22
|
+
around_filter :store_controller_for_public_activity unless respond_to?(:around_action)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def store_controller_for_public_activity
|
|
26
|
+
PublicActivity.set_controller(self)
|
|
27
|
+
yield
|
|
28
|
+
ensure
|
|
29
|
+
PublicActivity.set_controller(nil)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Provides a shortcut from views to the rendering method.
|
|
4
|
+
module PublicActivity
|
|
5
|
+
# Module extending ActionView::Base and adding `render_activity` helper.
|
|
6
|
+
module ViewHelpers
|
|
7
|
+
# View helper for rendering an activity, calls {PublicActivity::Activity#render} internally.
|
|
8
|
+
def render_activity activities, options = {}
|
|
9
|
+
if activities.is_a? PublicActivity::Activity
|
|
10
|
+
activities.render self, options
|
|
11
|
+
elsif activities.respond_to?(:map)
|
|
12
|
+
# depend on ORMs to fetch as needed
|
|
13
|
+
# maybe we can support Postgres streaming with this?
|
|
14
|
+
activities.map {|activity| activity.render self, options.dup }.join.html_safe
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
alias_method :render_activities, :render_activity
|
|
18
|
+
|
|
19
|
+
# Helper for setting content_for in activity partial, needed to
|
|
20
|
+
# flush remains in between partial renders.
|
|
21
|
+
def single_content_for(name, content = nil, &block)
|
|
22
|
+
@view_flow.set(name, ActiveSupport::SafeBuffer.new)
|
|
23
|
+
content_for(name, content, &block)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
ActiveSupport.on_load(:action_view) do
|
|
29
|
+
include PublicActivity::ViewHelpers
|
|
30
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Migration responsible for creating a table with activities
|
|
4
|
+
class CreateActivities < (ActiveRecord.version.release() < Gem::Version.new('5.2.0') ? ActiveRecord::Migration : ActiveRecord::Migration[5.2])
|
|
5
|
+
# Create table
|
|
6
|
+
def self.up
|
|
7
|
+
create_table :activities do |t|
|
|
8
|
+
t.belongs_to :trackable, :polymorphic => true
|
|
9
|
+
t.belongs_to :owner, :polymorphic => true
|
|
10
|
+
t.string :key
|
|
11
|
+
t.text :parameters
|
|
12
|
+
t.belongs_to :recipient, :polymorphic => true
|
|
13
|
+
|
|
14
|
+
t.timestamps
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
add_index :activities, [:trackable_id, :trackable_type]
|
|
18
|
+
add_index :activities, [:owner_id, :owner_type]
|
|
19
|
+
add_index :activities, [:recipient_id, :recipient_type]
|
|
20
|
+
end
|
|
21
|
+
# Drop table
|
|
22
|
+
def self.down
|
|
23
|
+
drop_table :activities
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'migrations_base.rb'
|
|
4
|
+
|
|
5
|
+
class CreateArticles < MigrationsBase
|
|
6
|
+
def self.up
|
|
7
|
+
puts "creating"
|
|
8
|
+
create_table :articles do |t|
|
|
9
|
+
t.string :name
|
|
10
|
+
t.boolean :published
|
|
11
|
+
t.belongs_to :user
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|