live-activity 0.3.2
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/.document +5 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +2 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +20 -0
- data/README.md +153 -0
- data/Rakefile +18 -0
- data/lib/generators/live_stream/activity/activity_generator.rb +17 -0
- data/lib/generators/live_stream/activity/templates/activity.rb +5 -0
- data/lib/generators/live_stream/migration/migration_generator.rb +17 -0
- data/lib/generators/live_stream/migration/templates/migration.rb +33 -0
- data/lib/generators/live_stream.rb +14 -0
- data/lib/live_activity/activity.rb +183 -0
- data/lib/live_activity/actor.rb +53 -0
- data/lib/live_activity/definition.rb +48 -0
- data/lib/live_activity/definition_dsl.rb +48 -0
- data/lib/live_activity/errors.rb +44 -0
- data/lib/live_activity/version.rb +3 -0
- data/lib/live_activity.rb +9 -0
- data/live-activity.gemspec +26 -0
- data/test/migrations/001_create_activities.rb +33 -0
- data/test/migrations/002_create_articles.rb +11 -0
- data/test/migrations/003_create_users.rb +8 -0
- data/test/migrations/004_add_nonstandard_to_activities.rb +7 -0
- data/test/migrations/005_create_volumes.rb +9 -0
- data/test/test_helper.rb +77 -0
- data/test/unit/activity_test.rb +85 -0
- data/test/unit/actor_test.rb +58 -0
- data/test/unit/definition_dsl_test.rb +29 -0
- data/test/unit/definition_test.rb +51 -0
- metadata +128 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fe8df6a8d020963d1afb51c4f68a711008cf404a
|
4
|
+
data.tar.gz: 6c9215b22a933a080d89f809e6278acda4d47da5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 85250962c209b1a30435eb3feedc56b449db92f559b514aec2d000038ed31e95475a5520ef924f59f5351592d42910b8b872d0cf70223cf469e25e799d719403
|
7
|
+
data.tar.gz: b3a405bce7b9146729f35be6c59c78a7c66c6b5b8fe9719517aafb45b4eb3b6b19646e7c82e3295f089f6c167474da9aa8096efa992920ecbe36551edfc32dbc
|
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Andreas Saebjoernsen
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# LiveActivity
|
2
|
+
|
3
|
+
LiveActivity is a simple Ruby activity stream gem for use with the ActiveRecord ODM framework.
|
4
|
+
|
5
|
+
This gem is inspired by Streama by Christopher Pappas.
|
6
|
+
|
7
|
+
[](http://travis-ci.org/digitalplaywright/live-activity) [](https://gemnasium.com/digitalplaywright/live-activity) [](https://codeclimate.com/github/digitalplaywright/live-activity)
|
8
|
+
|
9
|
+
|
10
|
+
## Install
|
11
|
+
|
12
|
+
gem install live_activity
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
### Create migration for activities and migrate the database (in your Rails project):
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
rails g public_activity:migration
|
20
|
+
rake db:migrate
|
21
|
+
```
|
22
|
+
|
23
|
+
A join table must also be created for all receivers. E.g if users are receivers:
|
24
|
+
|
25
|
+
``` ruby
|
26
|
+
create_table :activities_users, :id => false do |t|
|
27
|
+
t.references :activity, :user
|
28
|
+
end
|
29
|
+
|
30
|
+
add_index :activities_users, [:activity_id, :user_id ]
|
31
|
+
```
|
32
|
+
|
33
|
+
### Define Activities
|
34
|
+
|
35
|
+
Create an Activity model and define the activities and the fields you would like to cache within the activity.
|
36
|
+
|
37
|
+
An activity consists of an actor, a verb, an act_object, and a target.
|
38
|
+
|
39
|
+
``` ruby
|
40
|
+
class Activity < ActiveRecord::Base
|
41
|
+
include LiveActivity::Activity
|
42
|
+
|
43
|
+
has_and_belongs_to_many :users
|
44
|
+
|
45
|
+
activity :new_enquiry do
|
46
|
+
actor :User
|
47
|
+
act_object :Article
|
48
|
+
act_target :Volume
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
The activity verb is implied from the activity name, in the above example the verb is :new_enquiry
|
54
|
+
|
55
|
+
The act_object may be the entity performing the activity, or the entity on which the activity was performed.
|
56
|
+
e.g John(actor) shared a video(act_object)
|
57
|
+
|
58
|
+
The target is the act_object that the verb is enacted on.
|
59
|
+
e.g. Geraldine(actor) posted a photo(act_object) to her album(target)
|
60
|
+
|
61
|
+
This is based on the Activity Streams 1.0 specification (http://activitystrea.ms)
|
62
|
+
|
63
|
+
### Setup Actors
|
64
|
+
|
65
|
+
Include the Actor module in a class and override the default followers method.
|
66
|
+
|
67
|
+
``` ruby
|
68
|
+
class User < ActiveRecord::Base
|
69
|
+
include LiveActivity::Actor
|
70
|
+
|
71
|
+
has_and_belongs_to_many :activities
|
72
|
+
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
### Publishing Activity
|
79
|
+
|
80
|
+
In your controller or background worker:
|
81
|
+
|
82
|
+
``` ruby
|
83
|
+
current_user.publish_activity(:new_enquiry, :act_object => @enquiry, :target => @listing)
|
84
|
+
```
|
85
|
+
|
86
|
+
This will publish the activity to the mongoid act_objects returned by the #followers method in the Actor.
|
87
|
+
|
88
|
+
To send your activity to different receievers, pass in an additional :receivers parameter.
|
89
|
+
|
90
|
+
``` ruby
|
91
|
+
current_user.publish_activity(:new_enquiry, :act_object => @enquiry, :target => @listing, :receivers => :friends) # calls friends method
|
92
|
+
```
|
93
|
+
|
94
|
+
``` ruby
|
95
|
+
current_user.publish_activity(:new_enquiry, :act_object => @enquiry, :target => @listing, :receivers => current_user.find(:all, :conditions => {:group_id => mygroup}))
|
96
|
+
```
|
97
|
+
|
98
|
+
## Retrieving Activity
|
99
|
+
|
100
|
+
To retrieve all activity for an actor
|
101
|
+
|
102
|
+
``` ruby
|
103
|
+
current_user.activity_stream
|
104
|
+
```
|
105
|
+
|
106
|
+
To retrieve and filter to a particular activity type
|
107
|
+
|
108
|
+
``` ruby
|
109
|
+
current_user.activity_stream(:verb => 'new_enquiry')
|
110
|
+
```
|
111
|
+
|
112
|
+
#### Options
|
113
|
+
|
114
|
+
Additional options can be required:
|
115
|
+
|
116
|
+
``` ruby
|
117
|
+
class Activity < ActiveRecord::Base
|
118
|
+
include LiveActivity::Activity
|
119
|
+
|
120
|
+
has_and_belongs_to_many :users
|
121
|
+
|
122
|
+
activity :new_enquiry do
|
123
|
+
actor :User
|
124
|
+
act_object :Article
|
125
|
+
act_target :Volume
|
126
|
+
option :country
|
127
|
+
option :city
|
128
|
+
end
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
The option fields are stored using the ActiveRecord 'store' feature.
|
133
|
+
|
134
|
+
|
135
|
+
#### Bond type
|
136
|
+
|
137
|
+
A verb can have one bond type. This bond type can be used to classify and quickly retrieve
|
138
|
+
activity feed items that belong to a particular aggregate feed, like e.g the global feed.
|
139
|
+
|
140
|
+
``` ruby
|
141
|
+
class Activity < ActiveRecord::Base
|
142
|
+
include LiveActivity::Activity
|
143
|
+
|
144
|
+
has_and_belongs_to_many :users
|
145
|
+
|
146
|
+
activity :new_enquiry do
|
147
|
+
actor :User
|
148
|
+
act_object :Article
|
149
|
+
act_target :Volume
|
150
|
+
bond_type :global
|
151
|
+
end
|
152
|
+
end
|
153
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake'
|
3
|
+
require 'yard'
|
4
|
+
require 'yard/rake/yardoc_task'
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
desc 'Generate documentation for the live_stream plugin.'
|
10
|
+
YARD::Rake::YardocTask.new do |doc|
|
11
|
+
doc.files = ['lib/**/*.rb']
|
12
|
+
end
|
13
|
+
|
14
|
+
Rake::TestTask.new do |t|
|
15
|
+
t.libs << "test"
|
16
|
+
t.test_files = FileList['test/test*.rb', 'test/unit/*_test.rb']
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'generators/live_stream'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module LiveActivity
|
5
|
+
module Generators
|
6
|
+
# Activity generator that creates activity model file from template
|
7
|
+
class ActivityGenerator < ActiveRecord::Generators::Base
|
8
|
+
extend Base
|
9
|
+
|
10
|
+
argument :name, :type => :string, :default => 'activity'
|
11
|
+
# Create model in project's folder
|
12
|
+
def generate_files
|
13
|
+
copy_file 'activity.rb', "app/models/#{name}.rb"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'generators/live_stream'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module LiveStream
|
5
|
+
module Generators
|
6
|
+
# Migration generator that creates migration file from template
|
7
|
+
class MigrationGenerator < ActiveRecord::Generators::Base
|
8
|
+
extend Base
|
9
|
+
|
10
|
+
argument :name, :type => :string, :default => 'create_activities'
|
11
|
+
# Create migration in project's folder
|
12
|
+
def generate_files
|
13
|
+
migration_template 'migration.rb', "db/migrate/#{name}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Migration responsible for creating a table with activities
|
2
|
+
class CreateActivities < ActiveRecord::Migration
|
3
|
+
# Create table
|
4
|
+
def self.up
|
5
|
+
create_table :activities do |t|
|
6
|
+
t.belongs_to :actor, :polymorphic => true
|
7
|
+
t.belongs_to :act_object, :polymorphic => true
|
8
|
+
t.belongs_to :act_target, :polymorphic => true
|
9
|
+
|
10
|
+
t.string :verb
|
11
|
+
t.string :description
|
12
|
+
t.string :options
|
13
|
+
t.string :bond_type
|
14
|
+
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
|
18
|
+
create_table :activities_users, :id => false do |t|
|
19
|
+
t.references :activity, :user
|
20
|
+
end
|
21
|
+
|
22
|
+
add_index :activities_users, [:activity_id, :user_id ]
|
23
|
+
|
24
|
+
add_index :activities, [:verb]
|
25
|
+
add_index :activities, [:actor_id, :actor_type]
|
26
|
+
add_index :activities, [:act_object_id, :act_object_type]
|
27
|
+
add_index :activities, [:act_target_id, :act_target_type]
|
28
|
+
end
|
29
|
+
# Drop table
|
30
|
+
def self.down
|
31
|
+
drop_table :activities
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rails/generators/named_base'
|
2
|
+
|
3
|
+
module LiveActivity
|
4
|
+
# A generator module with Activity table schema.
|
5
|
+
module Generators
|
6
|
+
# A base module
|
7
|
+
module Base
|
8
|
+
# Get path for migration template
|
9
|
+
def source_root
|
10
|
+
@_live_activity_source_root ||= File.expand_path(File.join('../live_activity', generator_name, 'templates'), __FILE__)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
module LiveActivity
|
2
|
+
module Activity
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
|
7
|
+
store :options
|
8
|
+
|
9
|
+
belongs_to :actor, :polymorphic => true
|
10
|
+
belongs_to :act_object, :polymorphic => true
|
11
|
+
belongs_to :act_target, :polymorphic => true
|
12
|
+
|
13
|
+
validates_presence_of :actor_id, :actor_type, :verb
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
# Defines a new Activity2 type and registers a definition
|
19
|
+
#
|
20
|
+
# @param [ String ] name The name of the activity
|
21
|
+
#
|
22
|
+
# @example Define a new activity
|
23
|
+
# activity(:enquiry) do
|
24
|
+
# actor :user, :cache => [:full_name]
|
25
|
+
# act_object :enquiry, :cache => [:subject]
|
26
|
+
# act_target :listing, :cache => [:title]
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @return [Definition] Returns the registered definition
|
30
|
+
def activity(name, &block)
|
31
|
+
definition = LiveActivity::DefinitionDSL.new(name)
|
32
|
+
definition.instance_eval(&block)
|
33
|
+
LiveActivity::Definition.register(definition)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Publishes an activity using an activity name and data
|
37
|
+
#
|
38
|
+
# @param [ String ] verb The verb of the activity
|
39
|
+
# @param [ Hash ] data The data to initialize the activity with.
|
40
|
+
#
|
41
|
+
# @return [LiveActivity::Activity2] An Activity instance with data
|
42
|
+
def publish(verb, data)
|
43
|
+
new.publish({:verb => verb}.merge(data))
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
# Publishes the activity to the receivers
|
51
|
+
#
|
52
|
+
# @param [ Hash ] options The options to publish with.
|
53
|
+
#
|
54
|
+
def publish(data = {})
|
55
|
+
assign_properties(data)
|
56
|
+
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def refresh_data
|
62
|
+
save(:validate => false)
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def assign_properties(data = {})
|
68
|
+
|
69
|
+
self.verb = data.delete(:verb)
|
70
|
+
|
71
|
+
cur_receivers = data.delete(:receivers)
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
[:actor, :act_object, :act_target].each do |type|
|
76
|
+
|
77
|
+
cur_object = data[type]
|
78
|
+
|
79
|
+
unless cur_object
|
80
|
+
if definition.send(type.to_sym)
|
81
|
+
raise verb.to_json
|
82
|
+
#raise LiveActivity::InvalidData.new(type)
|
83
|
+
else
|
84
|
+
next
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class_sym = cur_object.class.name.to_sym
|
90
|
+
|
91
|
+
raise LiveActivity::InvalidData.new(class_sym) unless definition.send(type) == class_sym
|
92
|
+
|
93
|
+
case type
|
94
|
+
when :actor
|
95
|
+
self.actor = cur_object
|
96
|
+
when :act_object
|
97
|
+
self.act_object = cur_object
|
98
|
+
when :act_target
|
99
|
+
self.act_target = cur_object
|
100
|
+
else
|
101
|
+
raise "unknown type"
|
102
|
+
end
|
103
|
+
|
104
|
+
data.delete(type)
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
[:grouped_actor].each do |group|
|
109
|
+
|
110
|
+
|
111
|
+
grp_object = data[group]
|
112
|
+
|
113
|
+
if grp_object == nil
|
114
|
+
if definition.send(group.to_sym)
|
115
|
+
raise verb.to_json
|
116
|
+
#raise LiveActivity::InvalidData.new(group)
|
117
|
+
else
|
118
|
+
next
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
grp_object.each do |cur_obj|
|
124
|
+
raise LiveActivity::InvalidData.new(class_sym) unless definition.send(group) == cur_obj.class.name.to_sym
|
125
|
+
|
126
|
+
self.grouped_actors << cur_obj
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
data.delete(group)
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
cur_bond_type = definition.send(:bond_type)
|
135
|
+
|
136
|
+
if cur_bond_type
|
137
|
+
write_attribute( :bond_type, cur_bond_type.to_s )
|
138
|
+
end
|
139
|
+
|
140
|
+
def_options = definition.send(:options)
|
141
|
+
def_options.each do |cur_option|
|
142
|
+
cur_object = data[cur_option]
|
143
|
+
|
144
|
+
if cur_object
|
145
|
+
|
146
|
+
if cur_option == :description
|
147
|
+
self.description = cur_object
|
148
|
+
else
|
149
|
+
options[cur_option] = cur_object
|
150
|
+
end
|
151
|
+
data.delete(cur_option)
|
152
|
+
|
153
|
+
else
|
154
|
+
#all options defined must be used
|
155
|
+
raise Streama::InvalidData.new(cur_object[0])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
if data.size > 0
|
160
|
+
raise "unexpected arguments: " + data.to_json
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
self.save
|
166
|
+
|
167
|
+
|
168
|
+
if cur_receivers
|
169
|
+
cur_receivers.each do |sp|
|
170
|
+
send(sp.class.to_s.tableize) << sp
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
def definition
|
178
|
+
@definition ||= LiveActivity::Definition.find(verb)
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module LiveActivity
|
2
|
+
|
3
|
+
module Actor
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
cattr_accessor :activity_klass
|
8
|
+
|
9
|
+
has_many :created_activities, :class_name => "Activity", :as => :actor
|
10
|
+
has_many :act_object_activities, :class_name => "Activity", :as => :act_object
|
11
|
+
has_many :act_target_activities, :class_name => "Activity", :as => :act_target
|
12
|
+
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
def activity_class(klass)
|
19
|
+
self.activity_klass = klass.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Publishes the activity to the receivers
|
26
|
+
#
|
27
|
+
# @param [ Hash ] options The options to publish with.
|
28
|
+
#
|
29
|
+
# @example publish an activity with a act_object and act_target
|
30
|
+
# current_user.publish_activity(:enquiry, :act_object => @enquiry, :act_target => @listing)
|
31
|
+
#
|
32
|
+
def publish_activity(name, options={})
|
33
|
+
options[:receivers] = self.send(options[:receivers]) if options[:receivers].is_a?(Symbol)
|
34
|
+
activity = activity_class.publish(name, {:actor => self}.merge(options))
|
35
|
+
end
|
36
|
+
|
37
|
+
def activity_class
|
38
|
+
@activity_klass ||= activity_klass ? activity_klass.classify.constantize : ::Activity
|
39
|
+
end
|
40
|
+
|
41
|
+
def activity_stream(options = {})
|
42
|
+
|
43
|
+
if options.empty?
|
44
|
+
activities
|
45
|
+
else
|
46
|
+
activities.where(options)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module LiveActivity
|
2
|
+
|
3
|
+
class Definition
|
4
|
+
|
5
|
+
attr_reader :name, :actor, :act_object, :act_target, :grouped_actor, :bond_type, :options, :receivers
|
6
|
+
|
7
|
+
# @param dsl [LiveActivity::DefinitionDSL] A DSL act_object
|
8
|
+
def initialize(definition)
|
9
|
+
@name = definition[:name]
|
10
|
+
@actor = definition[:actor] || nil
|
11
|
+
@act_object = definition[:act_object] || nil
|
12
|
+
@act_target = definition[:act_target] || nil
|
13
|
+
@grouped_actor = definition[:grouped_actor] || nil
|
14
|
+
@bond_type = definition[:bond_type] || nil
|
15
|
+
@options = definition[:options] || []
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Registers a new definition
|
20
|
+
#
|
21
|
+
# @param definition [Definition] The definition to register
|
22
|
+
# @return [Definition] Returns the registered definition
|
23
|
+
def self.register(definition)
|
24
|
+
return false unless definition.is_a? DefinitionDSL
|
25
|
+
definition = new(definition)
|
26
|
+
self.registered << definition
|
27
|
+
return definition || false
|
28
|
+
end
|
29
|
+
|
30
|
+
# List of registered definitions
|
31
|
+
# @return [Array<LiveActivity::Definition>]
|
32
|
+
def self.registered
|
33
|
+
@definitions ||= []
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find(name)
|
37
|
+
unless definition = registered.find{|definition| definition.name == name.to_sym}
|
38
|
+
raise LiveActivity::InvalidActivity, "Could not find a definition for `#{name}`"
|
39
|
+
else
|
40
|
+
definition
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module LiveActivity
|
4
|
+
|
5
|
+
class DefinitionDSL
|
6
|
+
|
7
|
+
attr_reader :attributes
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@attributes = {
|
11
|
+
:name => name.to_sym,
|
12
|
+
:actor => nil,
|
13
|
+
:act_object => nil,
|
14
|
+
:act_target => nil,
|
15
|
+
:grouped_actor => nil,
|
16
|
+
:reverses => nil,
|
17
|
+
:bond_type => nil,
|
18
|
+
:options => nil
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_option(option)
|
23
|
+
@attributes[:options] ||= []
|
24
|
+
|
25
|
+
@attributes[:options] << option
|
26
|
+
end
|
27
|
+
|
28
|
+
def option(text)
|
29
|
+
add_option( text )
|
30
|
+
end
|
31
|
+
|
32
|
+
delegate :[], :to => :@attributes
|
33
|
+
|
34
|
+
def self.data_methods(*args)
|
35
|
+
args.each do |method|
|
36
|
+
define_method method do |*args|
|
37
|
+
|
38
|
+
@attributes[method] = args[0]
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
data_methods :actor, :act_object, :act_target, :grouped_actor, :bond_type
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module LiveActivity
|
2
|
+
|
3
|
+
class LiveActivityError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class InvalidActivity < LiveActivityError
|
7
|
+
end
|
8
|
+
|
9
|
+
# This error is raised when an act_object isn't defined
|
10
|
+
# as an actor, act_object or act_target
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
#
|
14
|
+
# <tt>InvalidField.new('field_name')</tt>
|
15
|
+
class InvalidData < LiveActivityError
|
16
|
+
attr_reader :message
|
17
|
+
|
18
|
+
def initialize message
|
19
|
+
@message = "Invalid Data: #{message}"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
# This error is raised when trying to store a field that doesn't exist
|
25
|
+
#
|
26
|
+
# Example:
|
27
|
+
#
|
28
|
+
# <tt>InvalidField.new('field_name')</tt>
|
29
|
+
class InvalidField < LiveActivityError
|
30
|
+
attr_reader :message
|
31
|
+
|
32
|
+
def initialize message
|
33
|
+
@message = "Invalid Field: #{message}"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class ActivityNotSaved < LiveActivityError
|
39
|
+
end
|
40
|
+
|
41
|
+
class NoFollowersDefined < LiveActivityError
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_support/core_ext/module/delegation.rb'
|
4
|
+
require "live_activity/version"
|
5
|
+
require "live_activity/actor"
|
6
|
+
require "live_activity/activity"
|
7
|
+
require "live_activity/definition"
|
8
|
+
require "live_activity/definition_dsl"
|
9
|
+
require "live_activity/errors"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "live_activity/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "live-activity"
|
7
|
+
s.version = LiveActivity::VERSION
|
8
|
+
s.authors = ["Andreas Saebjoernsen"]
|
9
|
+
s.email = ["andreas.saebjoernsen@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Activity Streams for rails}
|
12
|
+
s.description = %q{LiveActivity is a simple activity stream gem for use with the Mongoid ODM framework}
|
13
|
+
|
14
|
+
s.rubyforge_project = "live-activity"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.required_ruby_version = '>= 1.9.2'
|
22
|
+
|
23
|
+
s.add_dependency 'activerecord', '>= 3'
|
24
|
+
s.add_dependency 'activesupport', '>= 3'
|
25
|
+
s.add_dependency 'actionpack', '>= 3'
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Migration responsible for creating a table with activities
|
2
|
+
class CreateActivities < ActiveRecord::Migration
|
3
|
+
# Create table
|
4
|
+
def self.up
|
5
|
+
create_table :activities do |t|
|
6
|
+
t.belongs_to :actor, :polymorphic => true
|
7
|
+
t.belongs_to :act_object, :polymorphic => true
|
8
|
+
t.belongs_to :act_target, :polymorphic => true
|
9
|
+
|
10
|
+
t.string :verb
|
11
|
+
t.string :description
|
12
|
+
t.string :options
|
13
|
+
t.string :bond_type
|
14
|
+
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
|
18
|
+
create_table :activities_users, :id => false do |t|
|
19
|
+
t.references :activity, :user
|
20
|
+
end
|
21
|
+
|
22
|
+
add_index :activities_users, [:activity_id, :user_id ]
|
23
|
+
|
24
|
+
add_index :activities, [:verb]
|
25
|
+
add_index :activities, [:actor_id, :actor_type]
|
26
|
+
add_index :activities, [:act_object_id, :act_object_type]
|
27
|
+
add_index :activities, [:act_target_id, :act_target_type]
|
28
|
+
end
|
29
|
+
# Drop table
|
30
|
+
def self.down
|
31
|
+
drop_table :activities
|
32
|
+
end
|
33
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
Bundler.setup(:default, :test)
|
4
|
+
|
5
|
+
$:.unshift File.expand_path('../../lib/', __FILE__)
|
6
|
+
require 'active_support/testing/setup_and_teardown'
|
7
|
+
require 'live_activity'
|
8
|
+
require 'minitest/autorun'
|
9
|
+
|
10
|
+
#LiveStream.config # touch config to load ORM, needed in some separate tests
|
11
|
+
|
12
|
+
require 'active_record'
|
13
|
+
require 'active_record/connection_adapters/sqlite3_adapter'
|
14
|
+
|
15
|
+
|
16
|
+
class ActiveSupport::TestCase
|
17
|
+
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
18
|
+
#
|
19
|
+
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
20
|
+
# -- they do not yet inherit this setting
|
21
|
+
#fixtures :all
|
22
|
+
|
23
|
+
# Add more helper methods to be used by all tests here...
|
24
|
+
end
|
25
|
+
|
26
|
+
class Activity < ActiveRecord::Base
|
27
|
+
include LiveActivity::Activity
|
28
|
+
|
29
|
+
has_and_belongs_to_many :users
|
30
|
+
|
31
|
+
activity :new_enquiry do
|
32
|
+
actor :User
|
33
|
+
act_object :Article
|
34
|
+
act_target :Volume
|
35
|
+
#option :description
|
36
|
+
end
|
37
|
+
|
38
|
+
activity :test_description do
|
39
|
+
actor :User
|
40
|
+
act_object :Article
|
41
|
+
act_target :Volume
|
42
|
+
option :description
|
43
|
+
end
|
44
|
+
|
45
|
+
activity :test_option do
|
46
|
+
actor :User
|
47
|
+
act_object :Article
|
48
|
+
act_target :Volume
|
49
|
+
option :country
|
50
|
+
end
|
51
|
+
|
52
|
+
activity :test_bond_type do
|
53
|
+
actor :User
|
54
|
+
act_object :Article
|
55
|
+
act_target :Volume
|
56
|
+
bond_type :global
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
class User < ActiveRecord::Base
|
62
|
+
include LiveActivity::Actor
|
63
|
+
|
64
|
+
has_and_belongs_to_many :activities
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
class Article < ActiveRecord::Base
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
class Volume < ActiveRecord::Base
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
77
|
+
ActiveRecord::Migrator.migrate(File.expand_path('../migrations', __FILE__))
|
@@ -0,0 +1,85 @@
|
|
1
|
+
class ActivityTest < ActiveSupport::TestCase
|
2
|
+
|
3
|
+
def test_truth
|
4
|
+
assert true
|
5
|
+
end
|
6
|
+
|
7
|
+
def test_register_definition
|
8
|
+
|
9
|
+
@definition = Activity.activity(:test_activity) do
|
10
|
+
actor :user, :cache => [:full_name]
|
11
|
+
act_object :listing, :cache => [:title, :full_address]
|
12
|
+
act_target :listing, :cache => [:title]
|
13
|
+
end
|
14
|
+
|
15
|
+
assert @definition.is_a?(LiveActivity::Definition)
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_push_activity_to_receivers
|
20
|
+
_user = User.create()
|
21
|
+
_user_2 = User.create()
|
22
|
+
_article = Article.create()
|
23
|
+
_volume = Volume.create()
|
24
|
+
|
25
|
+
_activity = Activity.publish(:new_enquiry, :actor => _user, :act_object => _article, :act_target => _volume,
|
26
|
+
:receivers => [_user_2])
|
27
|
+
assert _activity.users.size == 1
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_publish_new_activity
|
32
|
+
_user = User.create()
|
33
|
+
_article = Article.create()
|
34
|
+
_volume = Volume.create()
|
35
|
+
|
36
|
+
_activity = Activity.publish(:new_enquiry, :actor => _user, :act_object => _article, :act_target => _volume)
|
37
|
+
|
38
|
+
assert _activity.persisted?
|
39
|
+
#_activity.should be_an_instance_of Activity
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_description
|
44
|
+
_user = User.create()
|
45
|
+
_article = Article.create()
|
46
|
+
_volume = Volume.create()
|
47
|
+
|
48
|
+
_description = "this is a test"
|
49
|
+
_activity = Activity.publish(:test_description, :actor => _user, :act_object => _article, :act_target => _volume,
|
50
|
+
:description => _description )
|
51
|
+
|
52
|
+
assert _activity.description == _description
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_options
|
57
|
+
_user = User.create()
|
58
|
+
_article = Article.create()
|
59
|
+
_volume = Volume.create()
|
60
|
+
|
61
|
+
_country = "denmark"
|
62
|
+
_activity = Activity.publish(:test_option, :actor => _user, :act_object => _article, :act_target => _volume,
|
63
|
+
:country => _country )
|
64
|
+
|
65
|
+
assert _activity.options[:country] == _country
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_bond_type
|
70
|
+
_user = User.create()
|
71
|
+
_article = Article.create()
|
72
|
+
_volume = Volume.create()
|
73
|
+
|
74
|
+
_activity = Activity.publish(:test_bond_type, :actor => _user, :act_object => _article, :act_target => _volume)
|
75
|
+
|
76
|
+
assert _activity.bond_type == 'global'
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class ActorTest < ActiveSupport::TestCase
|
2
|
+
|
3
|
+
|
4
|
+
def test_publish_activity
|
5
|
+
|
6
|
+
_user = User.create()
|
7
|
+
_article = Article.create()
|
8
|
+
_volume = Volume.create()
|
9
|
+
|
10
|
+
activity = _user.publish_activity(:new_enquiry, :act_object => _article, :act_target => _volume)
|
11
|
+
|
12
|
+
assert activity.persisted?
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_pushes_to_a_defined_stream
|
17
|
+
_user = User.create()
|
18
|
+
_user_2 = User.create()
|
19
|
+
_article = Article.create()
|
20
|
+
_volume = Volume.create()
|
21
|
+
|
22
|
+
_activity = _user.publish_activity(:new_enquiry, :act_object => _article, :act_target => _volume,
|
23
|
+
:receivers => [_user_2])
|
24
|
+
assert _activity.users.size == 1
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_retrieves_the_stream_for_an_actor
|
29
|
+
_user = User.create()
|
30
|
+
_article = Article.create()
|
31
|
+
_volume = Volume.create()
|
32
|
+
|
33
|
+
_user.publish_activity(:new_enquiry, :act_object => _article, :act_target => _volume, :receivers => [_user])
|
34
|
+
_user.publish_activity(:new_enquiry, :act_object => _article, :act_target => _volume, :receivers => [_user])
|
35
|
+
|
36
|
+
assert _user.activity_stream.size == 2
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def test_retrieves_the_stream_for_a_particular_activity_type
|
42
|
+
_user = User.create()
|
43
|
+
_article = Article.create()
|
44
|
+
_volume = Volume.create()
|
45
|
+
|
46
|
+
_user.publish_activity(:new_enquiry, :act_object => _article, :act_target => _volume, :receivers => [_user])
|
47
|
+
_user.publish_activity(:new_enquiry, :act_object => _article, :act_target => _volume, :receivers => [_user])
|
48
|
+
_user.publish_activity(:test_bond_type, :act_object => _article, :act_target => _volume, :receivers => [_user])
|
49
|
+
|
50
|
+
assert _user.activity_stream(:verb => 'new_enquiry').size == 2
|
51
|
+
assert _user.activity_stream(:bond_type => 'global').size == 1
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class DefinitionDslTest < ActiveSupport::TestCase
|
2
|
+
|
3
|
+
def definition_dsl
|
4
|
+
LiveActivity::DefinitionDSL.new(:new_enquiry)
|
5
|
+
end
|
6
|
+
|
7
|
+
def test_initializes_with_name
|
8
|
+
assert definition_dsl.attributes[:name] == :new_enquiry
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_adds_an_actor_to_the_definition
|
12
|
+
dsl = definition_dsl
|
13
|
+
dsl.actor(:User)
|
14
|
+
assert dsl.attributes[:actor] == :User
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_adds_an_act_object_to_the_definition
|
18
|
+
dsl = definition_dsl
|
19
|
+
dsl.act_object(:Article)
|
20
|
+
assert dsl.attributes[:act_object] == :Article
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_adds_a_act_target_to_the_definition
|
24
|
+
dsl = definition_dsl
|
25
|
+
dsl.act_target(:Volume)
|
26
|
+
assert dsl.attributes[:act_target] == :Volume
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class DefinitionTest < ActiveSupport::TestCase
|
2
|
+
|
3
|
+
def definition_dsl
|
4
|
+
dsl = LiveActivity::DefinitionDSL.new(:new_enquiry)
|
5
|
+
dsl.actor(:User)
|
6
|
+
dsl.act_object(:Article)
|
7
|
+
dsl.act_target(:Volume)
|
8
|
+
dsl
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_initialization
|
12
|
+
_definition_dsl = definition_dsl
|
13
|
+
_definition = LiveActivity::Definition.new(_definition_dsl)
|
14
|
+
|
15
|
+
assert _definition.actor == :User
|
16
|
+
assert _definition.act_object == :Article
|
17
|
+
assert _definition.act_target == :Volume
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_register_definition_and_return_new_definition
|
22
|
+
|
23
|
+
assert LiveActivity::Definition.register(definition_dsl).is_a?(LiveActivity::Definition)
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_register_invalid_definition
|
28
|
+
|
29
|
+
assert LiveActivity::Definition.register(false) == false
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_return_registered_definitions
|
34
|
+
|
35
|
+
LiveActivity::Definition.register(definition_dsl)
|
36
|
+
assert LiveActivity::Definition.registered.size > 0
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_return_definition_by_name
|
41
|
+
assert LiveActivity::Definition.find(:new_enquiry).name == :new_enquiry
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_raise_exception_if_invalid_activity
|
46
|
+
|
47
|
+
assert_raises(LiveActivity::InvalidActivity){ LiveActivity::Definition.find(:unknown_activity) }
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: live-activity
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andreas Saebjoernsen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: actionpack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3'
|
55
|
+
description: LiveActivity is a simple activity stream gem for use with the Mongoid
|
56
|
+
ODM framework
|
57
|
+
email:
|
58
|
+
- andreas.saebjoernsen@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- .document
|
64
|
+
- .gitignore
|
65
|
+
- .rspec
|
66
|
+
- .travis.yml
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- lib/generators/live_stream.rb
|
72
|
+
- lib/generators/live_stream/activity/activity_generator.rb
|
73
|
+
- lib/generators/live_stream/activity/templates/activity.rb
|
74
|
+
- lib/generators/live_stream/migration/migration_generator.rb
|
75
|
+
- lib/generators/live_stream/migration/templates/migration.rb
|
76
|
+
- lib/live_activity.rb
|
77
|
+
- lib/live_activity/activity.rb
|
78
|
+
- lib/live_activity/actor.rb
|
79
|
+
- lib/live_activity/definition.rb
|
80
|
+
- lib/live_activity/definition_dsl.rb
|
81
|
+
- lib/live_activity/errors.rb
|
82
|
+
- lib/live_activity/version.rb
|
83
|
+
- live-activity.gemspec
|
84
|
+
- test/migrations/001_create_activities.rb
|
85
|
+
- test/migrations/002_create_articles.rb
|
86
|
+
- test/migrations/003_create_users.rb
|
87
|
+
- test/migrations/004_add_nonstandard_to_activities.rb
|
88
|
+
- test/migrations/005_create_volumes.rb
|
89
|
+
- test/test_helper.rb
|
90
|
+
- test/unit/activity_test.rb
|
91
|
+
- test/unit/actor_test.rb
|
92
|
+
- test/unit/definition_dsl_test.rb
|
93
|
+
- test/unit/definition_test.rb
|
94
|
+
homepage: ''
|
95
|
+
licenses: []
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: 1.9.2
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project: live-activity
|
113
|
+
rubygems_version: 2.0.4
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: Activity Streams for rails
|
117
|
+
test_files:
|
118
|
+
- test/migrations/001_create_activities.rb
|
119
|
+
- test/migrations/002_create_articles.rb
|
120
|
+
- test/migrations/003_create_users.rb
|
121
|
+
- test/migrations/004_add_nonstandard_to_activities.rb
|
122
|
+
- test/migrations/005_create_volumes.rb
|
123
|
+
- test/test_helper.rb
|
124
|
+
- test/unit/activity_test.rb
|
125
|
+
- test/unit/actor_test.rb
|
126
|
+
- test/unit/definition_dsl_test.rb
|
127
|
+
- test/unit/definition_test.rb
|
128
|
+
has_rdoc:
|