streama 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +45 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +98 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/lib/streama/activity.rb +124 -0
- data/lib/streama/actor.rb +47 -0
- data/lib/streama/definition.rb +43 -0
- data/lib/streama/definition_dsl.rb +29 -0
- data/lib/streama/errors.rb +41 -0
- data/lib/streama.rb +7 -0
- data/spec/lib/activity_spec.rb +100 -0
- data/spec/lib/actor_spec.rb +54 -0
- data/spec/lib/definition_dsl_spec.rb +36 -0
- data/spec/lib/definition_spec.rb +65 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/models/activity.rb +10 -0
- data/spec/support/models/enquiry.rb +6 -0
- data/spec/support/models/listing.rb +6 -0
- data/spec/support/models/user.rb +12 -0
- data/streama.gemspec +78 -0
- metadata +148 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.0.7)
|
5
|
+
activesupport (= 3.0.7)
|
6
|
+
builder (~> 2.1.2)
|
7
|
+
i18n (~> 0.5.0)
|
8
|
+
activesupport (3.0.7)
|
9
|
+
bson (1.3.1)
|
10
|
+
bson_ext (1.3.1)
|
11
|
+
builder (2.1.2)
|
12
|
+
diff-lcs (1.1.2)
|
13
|
+
git (1.2.5)
|
14
|
+
i18n (0.5.0)
|
15
|
+
jeweler (1.6.1)
|
16
|
+
bundler (~> 1.0.0)
|
17
|
+
git (>= 1.2.5)
|
18
|
+
rake
|
19
|
+
mongo (1.3.1)
|
20
|
+
bson (>= 1.3.1)
|
21
|
+
mongoid (2.0.2)
|
22
|
+
activemodel (~> 3.0)
|
23
|
+
mongo (~> 1.3)
|
24
|
+
tzinfo (~> 0.3.22)
|
25
|
+
rake (0.9.0)
|
26
|
+
rspec (2.3.0)
|
27
|
+
rspec-core (~> 2.3.0)
|
28
|
+
rspec-expectations (~> 2.3.0)
|
29
|
+
rspec-mocks (~> 2.3.0)
|
30
|
+
rspec-core (2.3.1)
|
31
|
+
rspec-expectations (2.3.0)
|
32
|
+
diff-lcs (~> 1.1.2)
|
33
|
+
rspec-mocks (2.3.0)
|
34
|
+
tzinfo (0.3.27)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
activesupport (~> 3.0)
|
41
|
+
bson_ext (~> 1.2)
|
42
|
+
bundler (~> 1.0.0)
|
43
|
+
jeweler (~> 1.6.1)
|
44
|
+
mongoid (~> 2.0.0.rc)
|
45
|
+
rspec (~> 2.3.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Christos Pappas
|
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.rdoc
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
= Streama
|
2
|
+
|
3
|
+
Streama is a simple Ruby activity stream gem for use with the Mongoid ODM framework.
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
$ gem install streama
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
=== Define Activities
|
12
|
+
|
13
|
+
Create an Activity model and define the activities and the fields you would like to cache within the activity.
|
14
|
+
|
15
|
+
class Activity
|
16
|
+
include Streama::Activity
|
17
|
+
|
18
|
+
activity :enquiry do
|
19
|
+
actor :user, :cache => [:full_name]
|
20
|
+
target :enquiry, :cache => [:subject]
|
21
|
+
referrer :listing, :cache => [:title]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
=== Setup Actors
|
27
|
+
|
28
|
+
Include the Actor module in a class and override the default followers method.
|
29
|
+
|
30
|
+
class User
|
31
|
+
include Mongoid::Document
|
32
|
+
include Streama::Actor
|
33
|
+
|
34
|
+
def followers
|
35
|
+
...
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
=== Setup Indexes
|
40
|
+
|
41
|
+
Create the indexes for the Activities collection. You can do so by calling the create_indexes method.
|
42
|
+
|
43
|
+
Activity.create_indexes
|
44
|
+
|
45
|
+
=== Publishing Activity
|
46
|
+
|
47
|
+
In your controller or background worker:
|
48
|
+
|
49
|
+
current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing)
|
50
|
+
|
51
|
+
This will publish the activity to the objects returned by the "followers" method in the Actor.
|
52
|
+
|
53
|
+
To send your activity to different receievers, pass in an additional :receivers parameter.
|
54
|
+
|
55
|
+
current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing, :receivers => :friends) # calls friends method
|
56
|
+
current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing, :receivers => current_user.find(:all, :conditions => {:group_id => mygroup}))
|
57
|
+
|
58
|
+
== Retrieving Activity
|
59
|
+
|
60
|
+
To retrieve all activity for an actor
|
61
|
+
|
62
|
+
current_user.activity_stream
|
63
|
+
|
64
|
+
To retrieve and filter to a particular activity type
|
65
|
+
|
66
|
+
current_user.activity_stream(:type => :activity_type)
|
67
|
+
|
68
|
+
If you need to return the instance of an :actor, :target or :referrer from an activity call the Activity#load_instance method
|
69
|
+
|
70
|
+
activity.load_instance(:actor)
|
71
|
+
|
72
|
+
You can also refresh the cached activity data by calling the Activity#refresh_data method
|
73
|
+
|
74
|
+
activity.refresh_data
|
75
|
+
|
76
|
+
== Compatibility
|
77
|
+
|
78
|
+
Streama is developed against Ruby 1.9.2 and Mongoid 2.0.0.rc7
|
79
|
+
|
80
|
+
== TODO
|
81
|
+
|
82
|
+
* Write more documentation, YARD
|
83
|
+
* Write more tests
|
84
|
+
* Benchmarks
|
85
|
+
|
86
|
+
= License
|
87
|
+
|
88
|
+
Copyright © 2011 Christos Pappas
|
89
|
+
|
90
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
91
|
+
|
92
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
93
|
+
|
94
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
95
|
+
|
96
|
+
= Credits
|
97
|
+
|
98
|
+
Christos Pappas: christos dot pappas at gmail dot com
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
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'
|
26
|
+
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
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
41
|
+
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = "streama #{version}"
|
44
|
+
rdoc.rdoc_files.include('README*')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Streama
|
2
|
+
module Activity
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
|
10
|
+
field :name, :type => Symbol
|
11
|
+
field :actor, :type => Hash
|
12
|
+
field :target, :type => Hash
|
13
|
+
field :referrer, :type => Hash
|
14
|
+
field :receivers, :type => Array
|
15
|
+
|
16
|
+
index :name
|
17
|
+
index [['actor._id', Mongo::ASCENDING], ['actor._type', Mongo::ASCENDING]]
|
18
|
+
index [['target._id', Mongo::ASCENDING], ['target._type', Mongo::ASCENDING]]
|
19
|
+
index [['referrer._id', Mongo::ASCENDING], ['referrer._type', Mongo::ASCENDING]]
|
20
|
+
index [['receivers.id', Mongo::ASCENDING], ['receivers.type', Mongo::ASCENDING]]
|
21
|
+
|
22
|
+
validates_presence_of :actor, :name
|
23
|
+
before_save :assign_data
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
|
29
|
+
# Defines a new activity type and registers a definition
|
30
|
+
#
|
31
|
+
# @param [ String ] name The name of the activity
|
32
|
+
#
|
33
|
+
# @example Define a new activity
|
34
|
+
# activity(:enquiry) do
|
35
|
+
# actor :user, :cache => [:full_name]
|
36
|
+
# target :enquiry, :cache => [:subject]
|
37
|
+
# referrer :listing, :cache => [:title]
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# @return [Definition] Returns the registered definition
|
41
|
+
def activity(name, &block)
|
42
|
+
definition = Streama::DefinitionDSL.new(name)
|
43
|
+
definition.instance_eval(&block)
|
44
|
+
Streama::Definition.register(definition)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Publishes an activity using an activity name and data
|
48
|
+
#
|
49
|
+
# @param [ String ] name The name of the activity
|
50
|
+
# @param [ Hash ] data The data to initialize the activity with.
|
51
|
+
#
|
52
|
+
# @return [Streama::Activity] An Activity instance with data
|
53
|
+
def publish(name, data)
|
54
|
+
receivers = data.delete(:receivers)
|
55
|
+
new({:name => name}.merge(data)).publish(:receivers => receivers)
|
56
|
+
end
|
57
|
+
|
58
|
+
def stream_for(actor, options={})
|
59
|
+
query = {:receivers => {'$elemMatch' => {:id => actor.id, :type => actor.class.to_s}}}
|
60
|
+
query.merge!({:name => options[:type]}) if options[:type]
|
61
|
+
self.where(query).without(:receivers).desc(:created_at)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
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, target or referrer
|
81
|
+
#
|
82
|
+
# @param [ Symbol ] type The data type (actor, target, referrer) to return an instance for.
|
83
|
+
#
|
84
|
+
# @return [Object] object An object 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
|
+
|
89
|
+
def refresh_data
|
90
|
+
assign_data
|
91
|
+
save(:validate => false)
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
95
|
+
|
96
|
+
def assign_data
|
97
|
+
|
98
|
+
[:actor, :target, :referrer].each do |type|
|
99
|
+
next unless object = load_instance(type)
|
100
|
+
|
101
|
+
class_sym = object.class.name.underscore.to_sym
|
102
|
+
|
103
|
+
raise Streama::InvalidData.new(class_sym) unless definition.send(type).has_key?(class_sym)
|
104
|
+
|
105
|
+
hash = {'id' => object.id, 'type' => object.class.name}
|
106
|
+
|
107
|
+
if fields = definition.send(type)[class_sym][:cache]
|
108
|
+
fields.each do |field|
|
109
|
+
raise Streama::InvalidField.new(field) unless object.respond_to?(field)
|
110
|
+
hash[field.to_s] = object.send(field)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
write_attribute(type, hash)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def definition
|
118
|
+
@definition ||= Streama::Definition.find(name)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Streama
|
2
|
+
|
3
|
+
module Actor
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
cattr_accessor :activity_klass
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
def activity_class(klass)
|
13
|
+
self.activity_klass = klass.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstanceMethods
|
19
|
+
|
20
|
+
# Publishes the activity to the receivers
|
21
|
+
#
|
22
|
+
# @param [ Hash ] options The options to publish with.
|
23
|
+
#
|
24
|
+
# @example publish an activity with a target and referrer
|
25
|
+
# current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing)
|
26
|
+
#
|
27
|
+
def publish_activity(name, options={})
|
28
|
+
options[:receivers] = self.send(options[:receivers]) if options[:receivers].is_a?(Symbol)
|
29
|
+
activity = activity_class.publish(name, {:actor => self}.merge(options))
|
30
|
+
end
|
31
|
+
|
32
|
+
def activity_stream(options = {})
|
33
|
+
activity_class.stream_for(self, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def followers
|
37
|
+
self.class.all
|
38
|
+
end
|
39
|
+
|
40
|
+
def activity_class
|
41
|
+
@activity_klass ||= activity_klass ? activity_klass.classify.constantize : ::Activity
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Streama
|
2
|
+
|
3
|
+
class Definition
|
4
|
+
|
5
|
+
attr_reader :name, :actor, :target, :referrer, :receivers
|
6
|
+
|
7
|
+
# @param dsl [Streama::DefinitionDSL] A DSL object
|
8
|
+
def initialize(definition)
|
9
|
+
@name = definition[:name]
|
10
|
+
@actor = definition[:actor] || {}
|
11
|
+
@target = definition[:target] || {}
|
12
|
+
@referrer = definition[:referrer] || {}
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Registers a new definition
|
17
|
+
#
|
18
|
+
# @param definition [Definition] The definition to register
|
19
|
+
# @return [Definition] Returns the registered definition
|
20
|
+
def self.register(definition)
|
21
|
+
return false unless definition.is_a? DefinitionDSL
|
22
|
+
definition = new(definition)
|
23
|
+
self.registered << definition
|
24
|
+
return definition || false
|
25
|
+
end
|
26
|
+
|
27
|
+
# List of registered definitions
|
28
|
+
# @return [Array<Streama::Definition>]
|
29
|
+
def self.registered
|
30
|
+
@definitions ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.find(name)
|
34
|
+
unless definition = registered.find{|definition| definition.name == name.to_sym}
|
35
|
+
raise Streama::InvalidActivity, "Could not find a definition for `#{name}`"
|
36
|
+
else
|
37
|
+
definition
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Streama
|
2
|
+
|
3
|
+
class DefinitionDSL
|
4
|
+
|
5
|
+
attr_reader :attributes
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@attributes = {
|
9
|
+
:name => name.to_sym,
|
10
|
+
:actor => {},
|
11
|
+
:target => {},
|
12
|
+
:referrer => {}
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
delegate :[], :to => :@attributes
|
17
|
+
|
18
|
+
def self.data_methods(*args)
|
19
|
+
args.each do |method|
|
20
|
+
define_method method do |*args|
|
21
|
+
@attributes[method].store(args[0].is_a?(Symbol) ? args[0] : args[0].class.to_sym, args[1])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
data_methods :actor, :target, :referrer
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Streama
|
2
|
+
|
3
|
+
class StreamaError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class InvalidActivity < StreamaError
|
7
|
+
end
|
8
|
+
|
9
|
+
# This error is raised when an object isn't defined
|
10
|
+
# as an actor, target or referrer
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
#
|
14
|
+
# <tt>InvalidField.new('field_name')</tt>
|
15
|
+
class InvalidData < StreamaError
|
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 < StreamaError
|
30
|
+
attr_reader :message
|
31
|
+
|
32
|
+
def initialize message
|
33
|
+
@message = "Invalid Field: #{message}"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class ActivityNotSaved < StreamaError
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/lib/streama.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Activity" do
|
4
|
+
|
5
|
+
let(:enquiry) { Enquiry.create(:comment => "I'm interested") }
|
6
|
+
let(:listing) { Listing.create(:title => "A test listing") }
|
7
|
+
let(:user) { User.create(:full_name => "Christos") }
|
8
|
+
|
9
|
+
describe '.activity' do
|
10
|
+
it "registers and return a valid definition" do
|
11
|
+
@definition = Activity.activity(:new_enquiry) do
|
12
|
+
actor :user, :cache => [:full_name]
|
13
|
+
target :enquiry, :cache => [:comment]
|
14
|
+
target :listing, :cache => [:title, :full_address]
|
15
|
+
referrer :listing, :cache => [:title]
|
16
|
+
end
|
17
|
+
|
18
|
+
@definition.is_a?(Streama::Definition).should be true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#publish' do
|
23
|
+
|
24
|
+
before :each do
|
25
|
+
@actor = user
|
26
|
+
@activity = Activity.publish(:new_enquiry, {:actor => @actor, :target => enquiry, :referrer => listing})
|
27
|
+
end
|
28
|
+
|
29
|
+
it "overrides the recievers if option passed" do
|
30
|
+
send_to = []
|
31
|
+
2.times { |n| send_to << User.create(:full_name => "Custom Receiver #{n}") }
|
32
|
+
5.times { |n| User.create(:full_name => "Receiver #{n}") }
|
33
|
+
|
34
|
+
# @activity.receivers << send_to
|
35
|
+
# @activity.receivers.size.should == 2
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when republishing"
|
39
|
+
before :each do
|
40
|
+
@activity.publish
|
41
|
+
end
|
42
|
+
|
43
|
+
it "updates metadata" do
|
44
|
+
@actor.full_name = "testing"
|
45
|
+
@actor.save
|
46
|
+
@activity.publish
|
47
|
+
@activity.actor['full_name'].should eq "testing"
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
describe '.publish' do
|
54
|
+
it "creates a new activity" do
|
55
|
+
activity = Activity.publish(:new_enquiry, {:actor => user, :target => enquiry, :referrer => listing})
|
56
|
+
activity.should be_an_instance_of Activity
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#refresh' do
|
61
|
+
|
62
|
+
before :each do
|
63
|
+
@user = user
|
64
|
+
@activity = Activity.publish(:new_enquiry, {:actor => @user, :target => enquiry, :referrer => listing})
|
65
|
+
end
|
66
|
+
|
67
|
+
it "reloads instances and updates activities stored data" do
|
68
|
+
@activity.save
|
69
|
+
@activity = Activity.last
|
70
|
+
|
71
|
+
expect do
|
72
|
+
@user.update_attribute(:full_name, "Test")
|
73
|
+
@activity.refresh_data
|
74
|
+
end.to change{ @activity.load_instance(:actor).full_name}.from("Christos").to("Test")
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#load_instance' do
|
80
|
+
|
81
|
+
before :each do
|
82
|
+
@activity = Activity.publish(:new_enquiry, {:actor => user, :target => enquiry, :referrer => listing})
|
83
|
+
@activity = Activity.last
|
84
|
+
end
|
85
|
+
|
86
|
+
it "loads an actor instance" do
|
87
|
+
@activity.load_instance(:actor).should be_instance_of User
|
88
|
+
end
|
89
|
+
|
90
|
+
it "loads a target instance" do
|
91
|
+
@activity.load_instance(:target).should be_instance_of Enquiry
|
92
|
+
end
|
93
|
+
|
94
|
+
it "loads a referrer instance" do
|
95
|
+
@activity.load_instance(:referrer).should be_instance_of Listing
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Actor" do
|
4
|
+
|
5
|
+
let(:enquiry) { Enquiry.create(:comment => "I'm interested") }
|
6
|
+
let(:listing) { Listing.create(:title => "A test listing") }
|
7
|
+
let(:user) { User.create(:full_name => "Christos") }
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
Activity.activity :new_comment do
|
11
|
+
actor :user, :cache => [:full_name]
|
12
|
+
target :listing, :cache => [:title]
|
13
|
+
referrer :listing, :cache => [:title]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#publish_activity" do
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
5.times { |n| User.create(:full_name => "Receiver #{n}") }
|
21
|
+
end
|
22
|
+
|
23
|
+
it "pushes activity to receivers" do
|
24
|
+
activity = user.publish_activity(:new_enquiry, :target => enquiry, :referrer => listing)
|
25
|
+
activity.receivers.size == 6
|
26
|
+
end
|
27
|
+
|
28
|
+
it "pushes to a defined stream" do
|
29
|
+
activity = user.publish_activity(:new_enquiry, :target => enquiry, :referrer => listing, :receivers => :friends)
|
30
|
+
activity.receivers.size == 6
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#activity_stream" do
|
36
|
+
|
37
|
+
before :each do
|
38
|
+
5.times { |n| User.create(:full_name => "Receiver #{n}") }
|
39
|
+
user.publish_activity(:new_enquiry, :target => enquiry, :referrer => listing)
|
40
|
+
user.publish_activity(:new_comment, :target => listing)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "retrieves the stream for an actor" do
|
44
|
+
user.activity_stream.size.should eq 2
|
45
|
+
end
|
46
|
+
|
47
|
+
it "retrieves the stream and filters to a particular activity type" do
|
48
|
+
user.activity_stream(:type => :new_comment).size.should eq 1
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Definition" do
|
4
|
+
|
5
|
+
let(:definition_dsl) {Streama::DefinitionDSL.new(:new_enquiry)}
|
6
|
+
|
7
|
+
it "initializes with name" do
|
8
|
+
definition_dsl.attributes[:name].should eq :new_enquiry
|
9
|
+
end
|
10
|
+
|
11
|
+
it "adds an actor to the definition" do
|
12
|
+
dsl = definition_dsl
|
13
|
+
dsl.actor(:user, :cache => [:id, :full_name])
|
14
|
+
dsl.attributes[:actor].should eq :user => { :cache=>[:id, :full_name] }
|
15
|
+
end
|
16
|
+
|
17
|
+
it "adds multiple actors to the definition" do
|
18
|
+
dsl = definition_dsl
|
19
|
+
dsl.actor(:user, :cache => [:id, :full_name])
|
20
|
+
dsl.actor(:company, :cache => [:id, :name])
|
21
|
+
dsl.attributes[:actor].should eq :user => { :cache=>[:id, :full_name] }, :company => { :cache=>[:id, :name] }
|
22
|
+
end
|
23
|
+
|
24
|
+
it "adds a target to the definition" do
|
25
|
+
dsl = definition_dsl
|
26
|
+
dsl.target(:listing, :cache => [:id, :title])
|
27
|
+
dsl.attributes[:target].should eq :listing => { :cache=>[:id, :title] }
|
28
|
+
end
|
29
|
+
|
30
|
+
it "adds a referrer to the definition" do
|
31
|
+
dsl = definition_dsl
|
32
|
+
dsl.referrer(:company, :cache => [:id, :name])
|
33
|
+
dsl.attributes[:referrer].should eq :company => { :cache=>[:id, :name] }
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Definition" do
|
4
|
+
|
5
|
+
let(:definition_dsl) do
|
6
|
+
dsl = Streama::DefinitionDSL.new(:new_enquiry)
|
7
|
+
dsl.actor(:user, :cache => [:id, :full_name])
|
8
|
+
dsl.target(:enquiry, :cache => [:id, :full_name])
|
9
|
+
dsl.referrer(:listing, :cache => [:id, :name, :full_address])
|
10
|
+
dsl
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
before(:all) do
|
15
|
+
@definition_dsl = definition_dsl
|
16
|
+
@definition = Streama::Definition.new(@definition_dsl)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "assigns @actor" do
|
20
|
+
@definition.actor.has_key?(:user).should be true
|
21
|
+
end
|
22
|
+
it "assigns @target" do
|
23
|
+
@definition.target.has_key?(:enquiry).should be true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "assigns @referrer" do
|
27
|
+
@definition.referrer.has_key?(:listing).should be true
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '.register' do
|
33
|
+
|
34
|
+
it "registers a definition and return new definition" do
|
35
|
+
Streama::Definition.register(definition_dsl).is_a?(Streama::Definition).should eq true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns false if invalid definition" do
|
39
|
+
Streama::Definition.register(false).should be false
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.registered' do
|
45
|
+
|
46
|
+
it "returns registered definitions" do
|
47
|
+
Streama::Definition.register(definition_dsl)
|
48
|
+
Streama::Definition.registered.size.should be > 0
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '.find' do
|
54
|
+
|
55
|
+
it "returns the definition by name" do
|
56
|
+
Streama::Definition.find(:new_enquiry).name.should eq :new_enquiry
|
57
|
+
end
|
58
|
+
|
59
|
+
it "raises an exception if invalid activity" do
|
60
|
+
lambda { Streama::Definition.find(:unknown_activity) }.should raise_error Streama::InvalidActivity
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'streama'
|
6
|
+
require 'mongoid'
|
7
|
+
|
8
|
+
# Requires supporting files with custom matchers and macros, etc,
|
9
|
+
# in ./support/ and its subdirectories.
|
10
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
11
|
+
|
12
|
+
Mongoid.configure do |config|
|
13
|
+
name = "streama-rspec-test"
|
14
|
+
host = "localhost"
|
15
|
+
config.master = Mongo::Connection.new.db(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.include RSpec::Matchers
|
20
|
+
config.include Mongoid::Matchers
|
21
|
+
config.mock_with :rspec
|
22
|
+
config.after :each do
|
23
|
+
Mongoid.master.collections.select { |c| c.name != 'system.indexes' }.each(&:drop)
|
24
|
+
end
|
25
|
+
end
|
data/streama.gemspec
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{streama}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Christos Pappas"]
|
12
|
+
s.date = %q{2011-05-31}
|
13
|
+
s.description = %q{Streama is a simple activity stream gem for use with the Mongoid ODM framework.}
|
14
|
+
s.email = %q{christos.pappas@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"lib/streama.rb",
|
29
|
+
"lib/streama/activity.rb",
|
30
|
+
"lib/streama/actor.rb",
|
31
|
+
"lib/streama/definition.rb",
|
32
|
+
"lib/streama/definition_dsl.rb",
|
33
|
+
"lib/streama/errors.rb",
|
34
|
+
"spec/lib/activity_spec.rb",
|
35
|
+
"spec/lib/actor_spec.rb",
|
36
|
+
"spec/lib/definition_dsl_spec.rb",
|
37
|
+
"spec/lib/definition_spec.rb",
|
38
|
+
"spec/spec_helper.rb",
|
39
|
+
"spec/support/models/activity.rb",
|
40
|
+
"spec/support/models/enquiry.rb",
|
41
|
+
"spec/support/models/listing.rb",
|
42
|
+
"spec/support/models/user.rb",
|
43
|
+
"streama.gemspec"
|
44
|
+
]
|
45
|
+
s.homepage = %q{http://github.com/christospappas/streama}
|
46
|
+
s.licenses = ["MIT"]
|
47
|
+
s.require_paths = ["lib"]
|
48
|
+
s.rubygems_version = %q{1.6.2}
|
49
|
+
s.summary = %q{Streama is a simple activity stream gem for use with the Mongoid ODM framework.}
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_runtime_dependency(%q<activesupport>, ["~> 3.0"])
|
56
|
+
s.add_runtime_dependency(%q<mongoid>, ["~> 2.0.0.rc"])
|
57
|
+
s.add_runtime_dependency(%q<bson_ext>, ["~> 1.2"])
|
58
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
59
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
60
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.1"])
|
61
|
+
else
|
62
|
+
s.add_dependency(%q<activesupport>, ["~> 3.0"])
|
63
|
+
s.add_dependency(%q<mongoid>, ["~> 2.0.0.rc"])
|
64
|
+
s.add_dependency(%q<bson_ext>, ["~> 1.2"])
|
65
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
66
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
67
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.1"])
|
68
|
+
end
|
69
|
+
else
|
70
|
+
s.add_dependency(%q<activesupport>, ["~> 3.0"])
|
71
|
+
s.add_dependency(%q<mongoid>, ["~> 2.0.0.rc"])
|
72
|
+
s.add_dependency(%q<bson_ext>, ["~> 1.2"])
|
73
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
74
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
75
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.1"])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: streama
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.2.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Christos Pappas
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-31 00:00:00 +10:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: activesupport
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "3.0"
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mongoid
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.0.0.rc
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: bson_ext
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "1.2"
|
46
|
+
type: :runtime
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 2.3.0
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: bundler
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ~>
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.0.0
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: jeweler
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 1.6.1
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *id006
|
82
|
+
description: Streama is a simple activity stream gem for use with the Mongoid ODM framework.
|
83
|
+
email: christos.pappas@gmail.com
|
84
|
+
executables: []
|
85
|
+
|
86
|
+
extensions: []
|
87
|
+
|
88
|
+
extra_rdoc_files:
|
89
|
+
- LICENSE.txt
|
90
|
+
- README.rdoc
|
91
|
+
files:
|
92
|
+
- .document
|
93
|
+
- .rspec
|
94
|
+
- Gemfile
|
95
|
+
- Gemfile.lock
|
96
|
+
- LICENSE.txt
|
97
|
+
- README.rdoc
|
98
|
+
- Rakefile
|
99
|
+
- VERSION
|
100
|
+
- lib/streama.rb
|
101
|
+
- lib/streama/activity.rb
|
102
|
+
- lib/streama/actor.rb
|
103
|
+
- lib/streama/definition.rb
|
104
|
+
- lib/streama/definition_dsl.rb
|
105
|
+
- lib/streama/errors.rb
|
106
|
+
- spec/lib/activity_spec.rb
|
107
|
+
- spec/lib/actor_spec.rb
|
108
|
+
- spec/lib/definition_dsl_spec.rb
|
109
|
+
- spec/lib/definition_spec.rb
|
110
|
+
- spec/spec_helper.rb
|
111
|
+
- spec/support/models/activity.rb
|
112
|
+
- spec/support/models/enquiry.rb
|
113
|
+
- spec/support/models/listing.rb
|
114
|
+
- spec/support/models/user.rb
|
115
|
+
- streama.gemspec
|
116
|
+
has_rdoc: true
|
117
|
+
homepage: http://github.com/christospappas/streama
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: -386201865970004577
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: "0"
|
140
|
+
requirements: []
|
141
|
+
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 1.6.2
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: Streama is a simple activity stream gem for use with the Mongoid ODM framework.
|
147
|
+
test_files: []
|
148
|
+
|