evilmarty_activity_stream 1.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.
- data/.gitignore +20 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README +113 -0
- data/Rakefile +25 -0
- data/activity_stream.gemspec +24 -0
- data/generators/activity_stream/USAGE +1 -0
- data/generators/activity_stream/activity_stream_generator.rb +12 -0
- data/generators/activity_stream/templates/migrate/create_activities.rb +16 -0
- data/generators/activity_stream/templates/models/activity.rb +18 -0
- data/init.rb +1 -0
- data/lib/activity_observer.rb +23 -0
- data/lib/activity_stream.rb +223 -0
- data/lib/activity_stream/CHANGELOG.md +2 -0
- data/lib/activity_stream/version.rb +3 -0
- data/lib/version.rb +3 -0
- data/rails/init.rb +9 -0
- data/tasks/activity_stream_tasks.rake +4 -0
- data/test/activity_stream_test.rb +68 -0
- data/test/database.yml +22 -0
- data/test/fixtures/comment.rb +16 -0
- data/test/fixtures/comments.yml +17 -0
- data/test/fixtures/people.yml +9 -0
- data/test/fixtures/person.rb +10 -0
- data/test/fixtures/post.rb +11 -0
- data/test/fixtures/posts.yml +9 -0
- data/test/schema.rb +15 -0
- data/test/test_helper.rb +54 -0
- metadata +149 -0
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
test/debug.log
|
18
|
+
tmp
|
19
|
+
.rbenv-gemsets
|
20
|
+
.rbenv-version
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 erikecoologic
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# ActivityStream
|
2
|
+
|
3
|
+
Activity Stream will keep trace of your activity on the db.
|
4
|
+
|
5
|
+
This Gem is sutable for whom have installed [the plugin activity_stream by evilmarty](https://github.com/evilmarty/activity_stream) and want to use it with a Gem.
|
6
|
+
|
7
|
+
All tests are passing.
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'activity_stream'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install activity_stream
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
See below original readme.
|
27
|
+
|
28
|
+
## Contributing
|
29
|
+
|
30
|
+
Contributions are welcome, but be aware that we're not the original developers of the code and our own part was to move the existing code into a Gem.
|
31
|
+
|
32
|
+
1. Fork it
|
33
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
34
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
35
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
36
|
+
5. Create new Pull Request
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
ActivityStream
|
42
|
+
==============
|
43
|
+
|
44
|
+
A dead easy way to log activity streams.
|
45
|
+
|
46
|
+
Installation
|
47
|
+
============
|
48
|
+
|
49
|
+
script/plugin install http://github.com/evilmarty/activity_stream
|
50
|
+
|
51
|
+
Then run...
|
52
|
+
|
53
|
+
script/generate activity_stream
|
54
|
+
|
55
|
+
this will create the Activity model and place it in your app/models path as a migration file.
|
56
|
+
|
57
|
+
|
58
|
+
DON'T FORGET to add :activity_observer to your config.active_record.observers in environments.rb like so...
|
59
|
+
|
60
|
+
config.active_record.observers = :activity_observer
|
61
|
+
|
62
|
+
Usage
|
63
|
+
=====
|
64
|
+
|
65
|
+
For all the models you want to log an activity for do the following...
|
66
|
+
|
67
|
+
class Comment < ActiveRecord::Base
|
68
|
+
log_activities
|
69
|
+
end
|
70
|
+
|
71
|
+
this will log an activity for :create, :update and :destroy. To only log an activity for :create simply say so...
|
72
|
+
|
73
|
+
class Comment < ActiveRecord::Base
|
74
|
+
log_activities :create
|
75
|
+
end
|
76
|
+
|
77
|
+
You can also pass a Proc which can be used to check whether to log the activity or not, just return false
|
78
|
+
|
79
|
+
class Comment < ActiveRecord::Base
|
80
|
+
log_activities :create, :destroy
|
81
|
+
log_activities :update do |record|
|
82
|
+
record.status == 1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
and you can call it multiple times for different actions with different Procs
|
87
|
+
|
88
|
+
|
89
|
+
Now once your done with your logging, it's time to define your actors. Like so...
|
90
|
+
|
91
|
+
class User < ActiveRecord::Base
|
92
|
+
acts_as_actor
|
93
|
+
end
|
94
|
+
|
95
|
+
and now when you want to log activities simply do the following in your controllers or wherever you please
|
96
|
+
|
97
|
+
class CommentsController < ApplicationController
|
98
|
+
def create
|
99
|
+
current_user.log_activity('web') do
|
100
|
+
Comment.create params[:comment]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
that little argument for log_activity is the context of the activity but you can omit it should you feel so.
|
106
|
+
|
107
|
+
TODO
|
108
|
+
====
|
109
|
+
|
110
|
+
* write better doc
|
111
|
+
* add support for indirect objects maybe?
|
112
|
+
|
113
|
+
Copyright (c) 2009 Marty Zalega (evil.marty@gmail.com), released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
|
7
|
+
desc 'Default: run unit tests.'
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
desc 'Test the retrieve_resource plugin.'
|
11
|
+
Rake::TestTask.new(:test) do |t|
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = true
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Generate documentation for the retrieve_resource plugin.'
|
19
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
20
|
+
rdoc.rdoc_dir = 'rdoc'
|
21
|
+
rdoc.title = 'RetrieveResource'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('README')
|
24
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'activity_stream/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "evilmarty_activity_stream"
|
8
|
+
gem.version = ActivityStream::VERSION
|
9
|
+
gem.authors = ["ecoologic"]
|
10
|
+
gem.email = ["erik@netengine.com.au"]
|
11
|
+
gem.description = %q{A Gem for the plugin: https://github.com/evilmarty/activity_stream}
|
12
|
+
gem.summary = %q{This is a dependency we intend to maintain in order to upgrade our own projects from Rails 2.3.5 to 3.2 (or 4?)}
|
13
|
+
gem.homepage = "https://github.com/organizations/net-engine/activity_stream"
|
14
|
+
|
15
|
+
gem.add_development_dependency 'rake', ['0.8.7']
|
16
|
+
gem.add_development_dependency 'rails', ['2.3.16']
|
17
|
+
gem.add_development_dependency 'sqlite3'
|
18
|
+
|
19
|
+
|
20
|
+
gem.files = `git ls-files`.split($/)
|
21
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
22
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
23
|
+
gem.require_paths = ["lib"]
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Just run with no arguments
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class ActivityStreamGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
m.file 'models/activity.rb', 'app/models/activity.rb'
|
5
|
+
m.migration_template 'migrate/create_activities.rb', 'db/migrate'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def file_name
|
10
|
+
'create_activities'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateActivities < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :activities do |t|
|
4
|
+
t.string :verb, :null => false, :limit => 24
|
5
|
+
t.references :actor, :polymorphic => true
|
6
|
+
t.references :object, :polymorphic => true
|
7
|
+
t.references :indirect_object, :polymorphic => true
|
8
|
+
t.string :context, :limit => 32
|
9
|
+
t.datetime :timestamp, :null => false
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :activities
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Activity < ActiveRecord::Base
|
2
|
+
default_scope :order => 'timestamp DESC'
|
3
|
+
|
4
|
+
belongs_to :actor, :polymorphic => true
|
5
|
+
belongs_to :object, :polymorphic => true
|
6
|
+
belongs_to :indirect_object, :polymorphic => true
|
7
|
+
|
8
|
+
validates_presence_of :actor, :object, :verb
|
9
|
+
|
10
|
+
def before_create
|
11
|
+
self.timestamp ||= Time.now
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
default = ["objects.#{object_type.underscore}.#{verb}".intern, "verbs.#{verb}".intern, "#{actor_type.underscore} #{verb} #{object_type.intern}"]
|
16
|
+
I18n.t "actors.#{actor_type.underscore}.#{object_type.underscore}.#{verb}", :scope => 'activity_streams', :default => default, :actor => actor, :verb => verb, :object => object, :object_type => object_type
|
17
|
+
end
|
18
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rails/init.rb'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class ActivityObserver < ActiveRecord::Observer
|
2
|
+
class << self
|
3
|
+
# we don't want to include the activity model
|
4
|
+
def observed_class
|
5
|
+
nil
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def update(observed_method, object)
|
10
|
+
# check the object isn't an activity
|
11
|
+
return if object.is_a? Activity
|
12
|
+
context, block = Thread.current[:activity_stream_context], object.class.activity_triggers[observed_method]
|
13
|
+
# lets not log an activity if we don't have an actor or isn't an allowed callback
|
14
|
+
return unless !!context and (block.is_a?(Proc) ? block.call(object) != false : block == true)
|
15
|
+
|
16
|
+
verb = observed_method.to_s.gsub /^after_/, ''
|
17
|
+
|
18
|
+
attributes = context.attributes.merge :verb => verb, :object => object
|
19
|
+
attributes[:indirect_object] ||= object.instance_variable_get('@_indirect_object')
|
20
|
+
|
21
|
+
Activity.create(attributes)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require "activity_stream/version"
|
2
|
+
|
3
|
+
module ActivityStream
|
4
|
+
class Context
|
5
|
+
attr_reader :attributes
|
6
|
+
|
7
|
+
def initialize(attributes = {})
|
8
|
+
@attributes = attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(&block)
|
12
|
+
raise ArgumentError unless block_given?
|
13
|
+
current_context = Thread.current[:activity_stream_context]
|
14
|
+
Thread.current[:activity_stream_context] = self
|
15
|
+
|
16
|
+
yield
|
17
|
+
|
18
|
+
Thread.current[:activity_stream_context] = current_context
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
attributes[:context].to_s
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module ActiveRecord
|
27
|
+
def self.included(base)
|
28
|
+
base.extend ClassMethods
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def activity_triggers
|
33
|
+
read_inheritable_attribute(:activity_triggers) || {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def log_activities(*args, &block)
|
37
|
+
args = [:create, :update, :destroy] if args.length == 0
|
38
|
+
|
39
|
+
activity_triggers = self.activity_triggers
|
40
|
+
callback = block_given?? block : true
|
41
|
+
args.each { |verb| activity_triggers["after_#{verb}".intern] = callback }
|
42
|
+
write_inheritable_attribute :activity_triggers, activity_triggers
|
43
|
+
|
44
|
+
unless defined? @_activity_observed
|
45
|
+
has_many :activities, :as => :object do
|
46
|
+
def all(options = {})
|
47
|
+
klass = proxy_owner.klass
|
48
|
+
Scope.new scope_for_reflection(:find => {:conditions => ['object_type = ? OR indirect_object_type = ?', klass.name, klass.name]}), :find => options
|
49
|
+
end
|
50
|
+
|
51
|
+
def indirectly(options = {})
|
52
|
+
klass = proxy_owner.klass
|
53
|
+
Scope.new scope_for_reflection(:find => {:conditions => {:indirect_object_type => klass.name}}), :find => options
|
54
|
+
end
|
55
|
+
|
56
|
+
def directly(options = {})
|
57
|
+
klass = proxy_owner.klass
|
58
|
+
Scope.new scope_for_reflection(:find => {:conditions => {:object_type => klass.name}}), :find => options
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def scope_for_reflection(options)
|
63
|
+
Scope.new proxy_reflection.klass, options
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
add_observer ActivityObserver.instance
|
68
|
+
# to ensure we don't add the observer multiple times
|
69
|
+
@_activity_observed = true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def skip_log_activity(*args)
|
74
|
+
args = args.map(&:to_sym)
|
75
|
+
write_inheritable_attribute :activity_triggers, activity_triggers.reject { |k, v| args.include?("after_#{k}".intern) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def acts_as_actor
|
79
|
+
class_eval do
|
80
|
+
def log_activity(options = {}, &block)
|
81
|
+
raise ArgumentError unless block_given?
|
82
|
+
|
83
|
+
context = ActivityStream::Context.new options.merge(:actor => self)
|
84
|
+
context.call(&block)
|
85
|
+
end
|
86
|
+
|
87
|
+
def log_activity_indirectly_for(record, options = {}, &block)
|
88
|
+
log_activity options.merge(:indirect_object => record), &block
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
has_many :activities, :as => :actor
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
module AssociationProxy
|
98
|
+
def self.included(base)
|
99
|
+
base.class_eval do
|
100
|
+
private
|
101
|
+
def find_indirect_object
|
102
|
+
# we don't want activity to be our indirect object
|
103
|
+
return nil if @owner.class == Activity
|
104
|
+
|
105
|
+
# tried to use memoize but too many errors, bah!
|
106
|
+
@indirect_object ||= if @owner.class.respond_to?(:activity_triggers)
|
107
|
+
@owner
|
108
|
+
elsif ivar = @owner.instance_variable_get('@_indirect_object')
|
109
|
+
ivar
|
110
|
+
else
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def tag_with_indirect_object(record)
|
116
|
+
record.instance_variable_set '@_indirect_object', find_indirect_object if find_indirect_object
|
117
|
+
end
|
118
|
+
|
119
|
+
def set_belongs_to_association_for_with_indirect_object(record)
|
120
|
+
tag_with_indirect_object record
|
121
|
+
set_belongs_to_association_for_without_indirect_object record
|
122
|
+
end
|
123
|
+
alias_method_chain :set_belongs_to_association_for, :indirect_object
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
module AssociationCollection
|
129
|
+
def self.included(base)
|
130
|
+
base.class_eval do
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
module BelongsToAssociation
|
137
|
+
def self.included(base)
|
138
|
+
base.class_eval do
|
139
|
+
def replace_with_indirect_object(record)
|
140
|
+
tag_with_indirect_object record
|
141
|
+
replace_without_indirect_object record
|
142
|
+
end
|
143
|
+
alias_method_chain :replace, :indirect_object
|
144
|
+
|
145
|
+
def find_target_with_indirect_object
|
146
|
+
record = find_target_without_indirect_object
|
147
|
+
tag_with_indirect_object record
|
148
|
+
record
|
149
|
+
end
|
150
|
+
alias_method_chain :find_target, :indirect_object
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
module HasOneAssociation
|
156
|
+
def self.included(base)
|
157
|
+
base.class_eval do
|
158
|
+
def replace_with_indirect_object(*args)
|
159
|
+
tag_with_indirect_object args.first
|
160
|
+
replace_without_indirect_object *args
|
161
|
+
end
|
162
|
+
alias_method_chain :replace, :indirect_object
|
163
|
+
|
164
|
+
def new_record_with_indirect_object(replace_existing, &block)
|
165
|
+
new_record_without_indirect_object replace_existing do |reflection|
|
166
|
+
record = block.call reflection
|
167
|
+
# if we are going to replace_existing, this'll get done in our
|
168
|
+
# replace_with_parental_control above - no point in doing it twice
|
169
|
+
tag_with_indirect_object record unless replace_existing
|
170
|
+
record
|
171
|
+
end
|
172
|
+
end
|
173
|
+
alias_method_chain :new_record, :indirect_object
|
174
|
+
|
175
|
+
def find_target_with_indirect_object
|
176
|
+
record = find_target_without_indirect_object
|
177
|
+
tag_with_indirect_object record
|
178
|
+
record
|
179
|
+
end
|
180
|
+
alias_method_chain :find_target, :indirect_object
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
module HasManyAssociation
|
186
|
+
def self.included(base)
|
187
|
+
base.class_eval do
|
188
|
+
def add_record_to_target_with_callbacks_with_indirect_object(record, &block)
|
189
|
+
tag_with_indirect_object record
|
190
|
+
add_record_to_target_with_callbacks_without_indirect_object record, &block
|
191
|
+
end
|
192
|
+
alias_method_chain :add_record_to_target_with_callbacks, :indirect_object
|
193
|
+
|
194
|
+
def find_target_with_indirect_object
|
195
|
+
records = find_target_without_indirect_object
|
196
|
+
records.each { |record| tag_with_indirect_object(record) }
|
197
|
+
records
|
198
|
+
end
|
199
|
+
alias_method_chain :find_target, :indirect_object
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
module BelongsToPolymorphicAssociation
|
206
|
+
def self.included(base)
|
207
|
+
base.class_eval do
|
208
|
+
def replace_with_indirect_object(record)
|
209
|
+
tag_with_indirect_object record
|
210
|
+
replace_without_indirect_object record
|
211
|
+
end
|
212
|
+
alias_method_chain :replace, :indirect_object
|
213
|
+
|
214
|
+
def find_target_with_indirect_object
|
215
|
+
record = find_target_without_indirect_object
|
216
|
+
tag_with_indirect_object record
|
217
|
+
record
|
218
|
+
end
|
219
|
+
alias_method_chain :find_target, :indirect_object
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
data/lib/version.rb
ADDED
data/rails/init.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'activity_stream'
|
2
|
+
require 'activity_observer'
|
3
|
+
|
4
|
+
ActiveRecord::Base.class_eval { include ActivityStream::ActiveRecord }
|
5
|
+
ActiveRecord::Associations::AssociationProxy.class_eval { include ActivityStream::AssociationProxy }
|
6
|
+
ActiveRecord::Associations::BelongsToAssociation.class_eval { include ActivityStream::BelongsToAssociation }
|
7
|
+
ActiveRecord::Associations::HasOneAssociation.class_eval { include ActivityStream::HasOneAssociation }
|
8
|
+
ActiveRecord::Associations::HasManyAssociation.class_eval { include ActivityStream::HasManyAssociation }
|
9
|
+
ActiveRecord::Associations::BelongsToPolymorphicAssociation.class_eval { include ActivityStream::BelongsToPolymorphicAssociation }
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
2
|
+
|
3
|
+
class ActivityStreamTest < ActiveSupport::TestCase
|
4
|
+
load_schema
|
5
|
+
load_fixtures
|
6
|
+
load_activity_model
|
7
|
+
|
8
|
+
def test_model_actor_setup
|
9
|
+
assert @person = Person.first
|
10
|
+
assert_respond_to @person, :log_activity
|
11
|
+
assert_respond_to @person, :activities
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_model_activity_setup
|
15
|
+
assert @comment = Comment.first
|
16
|
+
assert_respond_to Comment, :log_activities
|
17
|
+
assert_respond_to Comment, :activity_triggers
|
18
|
+
assert_instance_of Hash, Comment.activity_triggers
|
19
|
+
assert_equal true, Comment.activity_triggers[:after_create]
|
20
|
+
assert_instance_of Proc, Comment.activity_triggers[:after_update]
|
21
|
+
assert_instance_of Proc, Comment.activity_triggers[:after_destroy]
|
22
|
+
assert_equal 1, Comment.count_observers
|
23
|
+
assert_respond_to @comment, :activities
|
24
|
+
assert_respond_to @comment.activities, :indirectly
|
25
|
+
assert_respond_to @comment.activities, :directly
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_activity_observer
|
29
|
+
assert_respond_to ActivityObserver, :instance
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_log_activity
|
33
|
+
assert @person = Person.first
|
34
|
+
Activity.delete_all
|
35
|
+
@person.log_activity do
|
36
|
+
@comment = @person.comments.build(:message => "I'm going to leave an activity")
|
37
|
+
assert @comment.save
|
38
|
+
end
|
39
|
+
assert @activity = Activity.first
|
40
|
+
assert_equal @person, @activity.actor
|
41
|
+
assert_equal @comment, @activity.object
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_indirect_object
|
45
|
+
Activity.delete_all
|
46
|
+
assert @person = Person.last
|
47
|
+
assert @post = Post.first
|
48
|
+
assert @comment = @post.comments.build(:message => 'testing indirect object')
|
49
|
+
|
50
|
+
@person.log_activity do
|
51
|
+
assert @comment.save
|
52
|
+
end
|
53
|
+
assert_equal @post, Activity.first.indirect_object
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_explicit_indirect_object
|
57
|
+
Activity.delete_all
|
58
|
+
assert @person = Person.last
|
59
|
+
assert @post = Post.first
|
60
|
+
assert @other_post = Post.last
|
61
|
+
assert_not_equal @post, @other_post
|
62
|
+
|
63
|
+
@person.log_activity_indirectly_for(@other_post) do
|
64
|
+
assert @post.comments.create :message => 'testing explicit indirect'
|
65
|
+
end
|
66
|
+
assert_equal @other_post, Activity.first.indirect_object
|
67
|
+
end
|
68
|
+
end
|
data/test/database.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
sqlite3:
|
2
|
+
database: ":memory:"
|
3
|
+
adapter: sqlite3
|
4
|
+
timeout: 500
|
5
|
+
|
6
|
+
sqlite2:
|
7
|
+
database: ":memory:"
|
8
|
+
adapter: sqlite2
|
9
|
+
|
10
|
+
mysql:
|
11
|
+
adapter: mysql
|
12
|
+
username: root
|
13
|
+
password:
|
14
|
+
encoding: utf8
|
15
|
+
database: activity_stream_unittest
|
16
|
+
|
17
|
+
postgres:
|
18
|
+
adapter: postgresql
|
19
|
+
username: root
|
20
|
+
password:
|
21
|
+
database: activity_stream_unittest
|
22
|
+
min_messages: warning
|
@@ -0,0 +1,17 @@
|
|
1
|
+
witty_comment:
|
2
|
+
id: 1
|
3
|
+
person_id: 1
|
4
|
+
post_id: 1
|
5
|
+
message: "Birdman is better!"
|
6
|
+
|
7
|
+
plea_comment:
|
8
|
+
id: 2
|
9
|
+
person_id: 1
|
10
|
+
post_id: 1
|
11
|
+
message: "I beg of you wont someone please think of the children"
|
12
|
+
|
13
|
+
robbery:
|
14
|
+
id: 3
|
15
|
+
person_id: 2
|
16
|
+
post_id: 2
|
17
|
+
message: "Nobody this is a robbery!"
|
data/test/schema.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
create_table :people, :force => true do |t|
|
3
|
+
t.string :firstname
|
4
|
+
t.string :lastname
|
5
|
+
t.timestamps
|
6
|
+
end
|
7
|
+
create_table :posts, :force => true do |t|
|
8
|
+
t.string :message
|
9
|
+
t.references :person
|
10
|
+
end
|
11
|
+
create_table :comments, :force => true do |t|
|
12
|
+
t.string :message
|
13
|
+
t.references :person, :post
|
14
|
+
end
|
15
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
2
|
+
ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
require 'yaml'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'active_record'
|
8
|
+
require 'active_record/version'
|
9
|
+
require 'active_record/fixtures'
|
10
|
+
|
11
|
+
require File.join(File.dirname(__FILE__), '..', 'init.rb')
|
12
|
+
|
13
|
+
def load_schema
|
14
|
+
config = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'database.yml')))
|
15
|
+
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "/debug.log"))
|
16
|
+
|
17
|
+
db_adapter = ENV['DB']
|
18
|
+
|
19
|
+
# no db passed, try one of these fine config-free DBs before bombing.
|
20
|
+
db_adapter ||=
|
21
|
+
begin
|
22
|
+
require 'rubygems'
|
23
|
+
require 'sqlite'
|
24
|
+
'sqlite'
|
25
|
+
rescue MissingSourceFile
|
26
|
+
begin
|
27
|
+
require 'sqlite3'
|
28
|
+
'sqlite3'
|
29
|
+
rescue MissingSourceFile
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if db_adapter.nil?
|
34
|
+
raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
|
35
|
+
end
|
36
|
+
|
37
|
+
ActiveRecord::Base.establish_connection(config[db_adapter])
|
38
|
+
load(File.join(File.dirname(__FILE__), "schema.rb"))
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_fixtures
|
42
|
+
filepath = File.join(File.dirname(__FILE__), 'fixtures')
|
43
|
+
ActiveSupport::Dependencies.load_paths.unshift filepath
|
44
|
+
Fixtures.create_fixtures(filepath, ActiveRecord::Base.connection.tables)
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_activity_model
|
48
|
+
template_path = File.join(File.dirname(__FILE__), '..', 'generators', 'activity_stream', 'templates')
|
49
|
+
|
50
|
+
load(File.join(template_path, 'migrate', 'create_activities.rb'))
|
51
|
+
CreateActivities.up
|
52
|
+
|
53
|
+
load(File.join(template_path, 'models', 'activity.rb'))
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evilmarty_activity_stream
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- ecoologic
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2013-02-02 00:00:00 +10:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rake
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - "="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 49
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 8
|
33
|
+
- 7
|
34
|
+
version: 0.8.7
|
35
|
+
type: :development
|
36
|
+
requirement: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rails
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - "="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 35
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 3
|
49
|
+
- 16
|
50
|
+
version: 2.3.16
|
51
|
+
type: :development
|
52
|
+
requirement: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: sqlite3
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
type: :development
|
66
|
+
requirement: *id003
|
67
|
+
description: "A Gem for the plugin: https://github.com/evilmarty/activity_stream"
|
68
|
+
email:
|
69
|
+
- erik@netengine.com.au
|
70
|
+
executables: []
|
71
|
+
|
72
|
+
extensions: []
|
73
|
+
|
74
|
+
extra_rdoc_files: []
|
75
|
+
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README
|
81
|
+
- Rakefile
|
82
|
+
- activity_stream.gemspec
|
83
|
+
- generators/activity_stream/USAGE
|
84
|
+
- generators/activity_stream/activity_stream_generator.rb
|
85
|
+
- generators/activity_stream/templates/migrate/create_activities.rb
|
86
|
+
- generators/activity_stream/templates/models/activity.rb
|
87
|
+
- init.rb
|
88
|
+
- lib/activity_observer.rb
|
89
|
+
- lib/activity_stream.rb
|
90
|
+
- lib/activity_stream/CHANGELOG.md
|
91
|
+
- lib/activity_stream/version.rb
|
92
|
+
- lib/version.rb
|
93
|
+
- rails/init.rb
|
94
|
+
- tasks/activity_stream_tasks.rake
|
95
|
+
- test/activity_stream_test.rb
|
96
|
+
- test/database.yml
|
97
|
+
- test/fixtures/comment.rb
|
98
|
+
- test/fixtures/comments.yml
|
99
|
+
- test/fixtures/people.yml
|
100
|
+
- test/fixtures/person.rb
|
101
|
+
- test/fixtures/post.rb
|
102
|
+
- test/fixtures/posts.yml
|
103
|
+
- test/schema.rb
|
104
|
+
- test/test_helper.rb
|
105
|
+
has_rdoc: true
|
106
|
+
homepage: https://github.com/organizations/net-engine/activity_stream
|
107
|
+
licenses: []
|
108
|
+
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
hash: 3
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
version: "0"
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
hash: 3
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
version: "0"
|
132
|
+
requirements: []
|
133
|
+
|
134
|
+
rubyforge_project:
|
135
|
+
rubygems_version: 1.6.2
|
136
|
+
signing_key:
|
137
|
+
specification_version: 3
|
138
|
+
summary: This is a dependency we intend to maintain in order to upgrade our own projects from Rails 2.3.5 to 3.2 (or 4?)
|
139
|
+
test_files:
|
140
|
+
- test/activity_stream_test.rb
|
141
|
+
- test/database.yml
|
142
|
+
- test/fixtures/comment.rb
|
143
|
+
- test/fixtures/comments.yml
|
144
|
+
- test/fixtures/people.yml
|
145
|
+
- test/fixtures/person.rb
|
146
|
+
- test/fixtures/post.rb
|
147
|
+
- test/fixtures/posts.yml
|
148
|
+
- test/schema.rb
|
149
|
+
- test/test_helper.rb
|