streama 0.3.2 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.travis.yml +2 -0
- data/Gemfile +2 -8
- data/Gemfile.lock +36 -32
- data/README.md +134 -0
- data/Rakefile +3 -43
- data/lib/streama.rb +7 -7
- data/lib/streama/activity.rb +51 -55
- data/lib/streama/actor.rb +18 -22
- data/lib/streama/definition.rb +2 -2
- data/lib/streama/definition_dsl.rb +8 -3
- data/lib/streama/version.rb +3 -0
- data/spec/app/models/activity.rb +21 -0
- data/spec/{support/models/listing.rb → app/models/album.rb} +1 -1
- data/spec/{support/models/enquiry.rb → app/models/photo.rb} +2 -2
- data/spec/{support → app}/models/user.rb +0 -0
- data/spec/lib/activity_spec.rb +41 -21
- data/spec/lib/actor_spec.rb +20 -29
- data/spec/lib/definition_dsl_spec.rb +7 -1
- data/spec/lib/definition_spec.rb +6 -6
- data/spec/spec_helper.rb +30 -10
- data/streama.gemspec +18 -68
- metadata +75 -87
- data/README.rdoc +0 -114
- data/VERSION +0 -1
- data/spec/support/models/activity.rb +0 -10
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -1,10 +1,4 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
gem
|
4
|
-
|
5
|
-
|
6
|
-
group :development do
|
7
|
-
gem "rspec", "~> 2.3.0"
|
8
|
-
gem "bundler", "~> 1.0.0"
|
9
|
-
gem "jeweler", "~> 1.6.1"
|
10
|
-
end
|
3
|
+
# Specify your gem's dependencies in streama.gemspec
|
4
|
+
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,43 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
streama (0.3.3)
|
5
|
+
|
1
6
|
GEM
|
2
7
|
remote: http://rubygems.org/
|
3
8
|
specs:
|
4
|
-
activemodel (3.
|
5
|
-
activesupport (= 3.
|
6
|
-
builder (~>
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
mongoid (2.0.2)
|
21
|
-
activemodel (~> 3.0)
|
9
|
+
activemodel (3.2.1)
|
10
|
+
activesupport (= 3.2.1)
|
11
|
+
builder (~> 3.0.0)
|
12
|
+
activesupport (3.2.1)
|
13
|
+
i18n (~> 0.6)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
bson (1.5.2)
|
16
|
+
bson_ext (1.5.2)
|
17
|
+
bson (= 1.5.2)
|
18
|
+
builder (3.0.0)
|
19
|
+
diff-lcs (1.1.3)
|
20
|
+
i18n (0.6.0)
|
21
|
+
mongo (1.5.2)
|
22
|
+
bson (= 1.5.2)
|
23
|
+
mongoid (2.4.3)
|
24
|
+
activemodel (~> 3.1)
|
22
25
|
mongo (~> 1.3)
|
23
26
|
tzinfo (~> 0.3.22)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
rspec-
|
28
|
-
rspec-
|
29
|
-
|
30
|
-
rspec-
|
27
|
+
multi_json (1.0.4)
|
28
|
+
rake (0.9.2.2)
|
29
|
+
rspec (2.6.0)
|
30
|
+
rspec-core (~> 2.6.0)
|
31
|
+
rspec-expectations (~> 2.6.0)
|
32
|
+
rspec-mocks (~> 2.6.0)
|
33
|
+
rspec-core (2.6.4)
|
34
|
+
rspec-expectations (2.6.0)
|
31
35
|
diff-lcs (~> 1.1.2)
|
32
|
-
rspec-mocks (2.
|
33
|
-
tzinfo (0.3.
|
36
|
+
rspec-mocks (2.6.0)
|
37
|
+
tzinfo (0.3.31)
|
34
38
|
|
35
39
|
PLATFORMS
|
36
40
|
ruby
|
37
41
|
|
38
42
|
DEPENDENCIES
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
bson_ext (~> 1.5)
|
44
|
+
mongoid (~> 2.4)
|
45
|
+
rake
|
46
|
+
rspec (~> 2.5)
|
47
|
+
streama!
|
data/README.md
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# Streama
|
2
|
+
|
3
|
+
**ALPHA**
|
4
|
+
|
5
|
+
Streama is a simple Ruby activity stream gem for use with the Mongoid ODM framework.
|
6
|
+
|
7
|
+
[![travis](https://secure.travis-ci.org/christospappas/streama.png)](http://travis-ci.org/christospappas/streama)
|
8
|
+
|
9
|
+
## Install
|
10
|
+
|
11
|
+
gem install streama
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### Define Activities
|
16
|
+
|
17
|
+
Create an Activity model and define the activities and the fields you would like to cache within the activity.
|
18
|
+
|
19
|
+
An activity consists of an actor, a verb, an object, and a target.
|
20
|
+
|
21
|
+
``` ruby
|
22
|
+
class Activity
|
23
|
+
include Streama::Activity
|
24
|
+
|
25
|
+
activity :new_photo do
|
26
|
+
actor :user, :cache => [:full_name]
|
27
|
+
object :photo, :cache => [:subject, :comment]
|
28
|
+
target_object :album, :cache => [:title]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
The activity verb is implied from the activity name, in the above example the verb is :new_photo
|
35
|
+
|
36
|
+
The object may be the entity performing the activity, or the entity on which the activity was performed.
|
37
|
+
e.g John(actor) shared a video(object)
|
38
|
+
|
39
|
+
The target is the object that the verb is enacted on.
|
40
|
+
e.g. Geraldine(actor) posted a photo(object) to her album(target)
|
41
|
+
|
42
|
+
This is based on the Activity Streams 1.0 specification (http://activitystrea.ms)
|
43
|
+
|
44
|
+
### Setup Actors
|
45
|
+
|
46
|
+
Include the Actor module in a class and override the default followers method.
|
47
|
+
|
48
|
+
``` ruby
|
49
|
+
class User
|
50
|
+
include Mongoid::Document
|
51
|
+
include Streama::Actor
|
52
|
+
|
53
|
+
field :full_name, :type => String
|
54
|
+
|
55
|
+
def followers
|
56
|
+
User.excludes(:id => self.id).all
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
### Setup Indexes
|
62
|
+
|
63
|
+
Create the indexes for the Activities collection. You can do so by calling the create_indexes method.
|
64
|
+
|
65
|
+
``` ruby
|
66
|
+
Activity.create_indexes
|
67
|
+
```
|
68
|
+
|
69
|
+
### Publishing Activity
|
70
|
+
|
71
|
+
In your controller or background worker:
|
72
|
+
|
73
|
+
``` ruby
|
74
|
+
current_user.publish_activity(:new_photo, :object => @photo, :target_object => @album)
|
75
|
+
```
|
76
|
+
|
77
|
+
This will publish the activity to the mongoid objects returned by the #followers method in the Actor.
|
78
|
+
|
79
|
+
To send your activity to different receievers, pass in an additional :receivers parameter.
|
80
|
+
|
81
|
+
``` ruby
|
82
|
+
current_user.publish_activity(:new_photo, :object => @photo, :target_object => @album, :receivers => :friends) # calls friends method
|
83
|
+
```
|
84
|
+
|
85
|
+
``` ruby
|
86
|
+
current_user.publish_activity(:new_photo, :object => @photo, :target_object => @album, :receivers => current_user.find(:all, :conditions => {:group_id => mygroup}))
|
87
|
+
```
|
88
|
+
|
89
|
+
## Retrieving Activity
|
90
|
+
|
91
|
+
To retrieve all activity for an actor
|
92
|
+
|
93
|
+
``` ruby
|
94
|
+
current_user.activity_stream
|
95
|
+
```
|
96
|
+
|
97
|
+
To retrieve and filter to a particular activity type
|
98
|
+
|
99
|
+
``` ruby
|
100
|
+
current_user.activity_stream(:type => :activity_verb)
|
101
|
+
```
|
102
|
+
If you need to return the instance of an :actor, :object or :target_object from an activity call the Activity#load_instance method
|
103
|
+
|
104
|
+
``` ruby
|
105
|
+
activity.load_instance(:actor)
|
106
|
+
```
|
107
|
+
|
108
|
+
You can also refresh the cached activity data by calling the Activity#refresh_data method
|
109
|
+
|
110
|
+
``` ruby
|
111
|
+
activity.refresh_data
|
112
|
+
```
|
113
|
+
|
114
|
+
## Upgrading
|
115
|
+
|
116
|
+
### 0.3.3
|
117
|
+
|
118
|
+
The Activity "target" field was renamed to "target_object". If you are upgrading from a previous version of Streama you will need to rename the field in existing documents.
|
119
|
+
|
120
|
+
http://www.mongodb.org/display/DOCS/Updating#Updating-%24rename
|
121
|
+
|
122
|
+
## Contributing
|
123
|
+
|
124
|
+
Once you've made your great commits
|
125
|
+
|
126
|
+
1. Fork
|
127
|
+
1. Create a topic branch - git checkout -b my_branch
|
128
|
+
1. Push to your branch - git push origin my_branch
|
129
|
+
1. Create a Pull Request from your branch
|
130
|
+
1. That's it!
|
131
|
+
|
132
|
+
## Contributors
|
133
|
+
|
134
|
+
* Christos Pappas (@christospappas)
|
data/Rakefile
CHANGED
@@ -1,46 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'rake'
|
11
|
-
|
12
|
-
require 'jeweler'
|
13
|
-
Jeweler::Tasks.new do |gem|
|
14
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
-
gem.name = "streama"
|
16
|
-
gem.homepage = "http://github.com/christospappas/streama"
|
17
|
-
gem.license = "MIT"
|
18
|
-
gem.summary = %Q{Streama is a simple activity stream gem for use with the Mongoid ODM framework.}
|
19
|
-
gem.description = %Q{Streama is a simple activity stream gem for use with the Mongoid ODM framework.}
|
20
|
-
gem.email = "christos.pappas@gmail.com"
|
21
|
-
gem.authors = ["Christos Pappas"]
|
22
|
-
end
|
23
|
-
Jeweler::RubygemsDotOrgTasks.new
|
24
|
-
|
25
|
-
require 'rspec/core'
|
1
|
+
require "bundler/gem_tasks"
|
26
2
|
require 'rspec/core/rake_task'
|
27
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
28
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
29
|
-
end
|
30
|
-
|
31
|
-
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
32
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
-
spec.rcov = true
|
34
|
-
end
|
35
|
-
|
36
|
-
task :default => :spec
|
37
3
|
|
38
|
-
|
39
|
-
Rake::RDocTask.new do |rdoc|
|
40
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
41
5
|
|
42
|
-
|
43
|
-
rdoc.title = "streama #{version}"
|
44
|
-
rdoc.rdoc_files.include('README*')
|
45
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
-
end
|
6
|
+
task default: :spec
|
data/lib/streama.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
|
1
|
+
require "mongoid"
|
2
|
+
require "streama/version"
|
3
|
+
require "streama/actor"
|
4
|
+
require "streama/activity"
|
5
|
+
require "streama/definition"
|
6
|
+
require "streama/definition_dsl"
|
7
|
+
require "streama/errors"
|
data/lib/streama/activity.rb
CHANGED
@@ -7,16 +7,16 @@ module Streama
|
|
7
7
|
include Mongoid::Document
|
8
8
|
include Mongoid::Timestamps
|
9
9
|
|
10
|
-
field :verb,
|
11
|
-
field :actor,
|
12
|
-
field :object,
|
13
|
-
field :
|
14
|
-
field :receivers,
|
10
|
+
field :verb, :type => Symbol
|
11
|
+
field :actor, :type => Hash
|
12
|
+
field :object, :type => Hash
|
13
|
+
field :target_object, :type => Hash
|
14
|
+
field :receivers, :type => Array
|
15
15
|
|
16
16
|
index :name
|
17
17
|
index [['actor._id', Mongo::ASCENDING], ['actor._type', Mongo::ASCENDING]]
|
18
18
|
index [['object._id', Mongo::ASCENDING], ['object._type', Mongo::ASCENDING]]
|
19
|
-
index [['
|
19
|
+
index [['target_object._id', Mongo::ASCENDING], ['target_object._type', Mongo::ASCENDING]]
|
20
20
|
index [['receivers.id', Mongo::ASCENDING], ['receivers.type', Mongo::ASCENDING]]
|
21
21
|
|
22
22
|
validates_presence_of :actor, :verb
|
@@ -34,7 +34,7 @@ module Streama
|
|
34
34
|
# activity(:enquiry) do
|
35
35
|
# actor :user, :cache => [:full_name]
|
36
36
|
# object :enquiry, :cache => [:subject]
|
37
|
-
#
|
37
|
+
# target_object :listing, :cache => [:title]
|
38
38
|
# end
|
39
39
|
#
|
40
40
|
# @return [Definition] Returns the registered definition
|
@@ -63,62 +63,58 @@ module Streama
|
|
63
63
|
|
64
64
|
end
|
65
65
|
|
66
|
-
|
67
|
-
module InstanceMethods
|
68
|
-
|
69
|
-
# Publishes the activity to the receivers
|
70
|
-
#
|
71
|
-
# @param [ Hash ] options The options to publish with.
|
72
|
-
#
|
73
|
-
def publish(options = {})
|
74
|
-
actor = load_instance(:actor)
|
75
|
-
self.receivers = (options[:receivers] || actor.followers).map { |r| { :id => r.id, :type => r.class.to_s } }
|
76
|
-
self.save
|
77
|
-
self
|
78
|
-
end
|
79
|
-
|
80
|
-
# Returns an instance of an actor, object or target
|
81
|
-
#
|
82
|
-
# @param [ Symbol ] type The data type (actor, object, target) to return an instance for.
|
83
|
-
#
|
84
|
-
# @return [Mongoid::Document] document A mongoid document instance
|
85
|
-
def load_instance(type)
|
86
|
-
(data = self.send(type)).is_a?(Hash) ? data['type'].to_s.camelcase.constantize.find(data['id']) : data
|
87
|
-
end
|
88
66
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
67
|
+
# Publishes the activity to the receivers
|
68
|
+
#
|
69
|
+
# @param [ Hash ] options The options to publish with.
|
70
|
+
#
|
71
|
+
def publish(options = {})
|
72
|
+
actor = load_instance(:actor)
|
73
|
+
self.receivers = (options[:receivers] || actor.followers).map { |r| { :id => r.id, :type => r.class.to_s } }
|
74
|
+
self.save
|
75
|
+
self
|
76
|
+
end
|
93
77
|
|
94
|
-
|
95
|
-
|
96
|
-
|
78
|
+
# Returns an instance of an actor, object or target
|
79
|
+
#
|
80
|
+
# @param [ Symbol ] type The data type (actor, object, target) to return an instance for.
|
81
|
+
#
|
82
|
+
# @return [Mongoid::Document] document A mongoid document instance
|
83
|
+
def load_instance(type)
|
84
|
+
(data = self.send(type)).is_a?(Hash) ? data['type'].to_s.camelcase.constantize.find(data['id']) : data
|
85
|
+
end
|
86
|
+
|
87
|
+
def refresh_data
|
88
|
+
assign_data
|
89
|
+
save(:validate => false)
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
97
93
|
|
98
|
-
|
99
|
-
|
94
|
+
def assign_data
|
95
|
+
|
96
|
+
[:actor, :object, :target_object].each do |type|
|
97
|
+
next unless object = load_instance(type)
|
100
98
|
|
101
|
-
|
99
|
+
class_sym = object.class.name.underscore.to_sym
|
102
100
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
101
|
+
raise Streama::InvalidData.new(class_sym) unless definition.send(type).has_key?(class_sym)
|
102
|
+
|
103
|
+
hash = {'id' => object.id, 'type' => object.class.name}
|
104
|
+
|
105
|
+
if fields = definition.send(type)[class_sym].try(:[],:cache)
|
106
|
+
fields.each do |field|
|
107
|
+
raise Streama::InvalidField.new(field) unless object.respond_to?(field)
|
108
|
+
hash[field.to_s] = object.send(field)
|
112
109
|
end
|
113
|
-
write_attribute(type, hash)
|
114
110
|
end
|
111
|
+
write_attribute(type, hash)
|
115
112
|
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
end
|
114
|
+
|
115
|
+
def definition
|
116
|
+
@definition ||= Streama::Definition.find(verb)
|
121
117
|
end
|
122
118
|
|
123
119
|
end
|
124
|
-
end
|
120
|
+
end
|
data/lib/streama/actor.rb
CHANGED
@@ -15,29 +15,25 @@ module Streama
|
|
15
15
|
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def activity_stream(options = {})
|
33
|
-
activity_class.stream_for(self, options)
|
34
|
-
end
|
35
|
-
|
36
|
-
def activity_class
|
37
|
-
@activity_klass ||= activity_klass ? activity_klass.classify.constantize : ::Activity
|
38
|
-
end
|
18
|
+
# Publishes the activity to the receivers
|
19
|
+
#
|
20
|
+
# @param [ Hash ] options The options to publish with.
|
21
|
+
#
|
22
|
+
# @example publish an activity with a object and target
|
23
|
+
# current_user.publish_activity(:enquiry, :object => @enquiry, :target => @listing)
|
24
|
+
#
|
25
|
+
def publish_activity(name, options={})
|
26
|
+
options[:receivers] = self.send(options[:receivers]) if options[:receivers].is_a?(Symbol)
|
27
|
+
activity = activity_class.publish(name, {:actor => self}.merge(options))
|
28
|
+
end
|
29
|
+
|
30
|
+
def activity_stream(options = {})
|
31
|
+
activity_class.stream_for(self, options)
|
39
32
|
end
|
40
33
|
|
41
|
-
|
34
|
+
def activity_class
|
35
|
+
@activity_klass ||= activity_klass ? activity_klass.classify.constantize : ::Activity
|
36
|
+
end
|
37
|
+
end
|
42
38
|
|
43
39
|
end
|