Skip to content

Commit

Permalink
Conform to the Activity Streams specification (http://activitystrea.ms/
Browse files Browse the repository at this point in the history
…). The activity "target" is now called "object", the "referrer: is now called the "target". Updated readme to make things clearer.
  • Loading branch information
christospappas committed Jun 23, 2011
1 parent 1da5016 commit a57f1ca
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 65 deletions.
36 changes: 25 additions & 11 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,29 @@ Streama is a simple Ruby activity stream gem for use with the Mongoid ODM framew

Create an Activity model and define the activities and the fields you would like to cache within the activity.

An activity consists of an actor, a verb, an object, and a target.

class Activity
include Streama::Activity

activity :enquiry do
activity :new_enquiry do
actor :user, :cache => [:full_name]
target :enquiry, :cache => [:subject]
referrer :listing, :cache => [:title]
object :enquiry, :cache => [:subject, :comment]
target :listing, :cache => [:title]
end

end

The activity verb is implied from the activity name, in the above example the verb is :new_enquiry

the object may be the entity performing the activity, or the entity on which the activity was performed.
e.g John(actor) shared a video(object)

The target allows you to relate the object with a target
e.g. Geraldine(actor) posted a photo(object) to her album(target)

This is based on the Activity Streams 1.0 specification (http://activitystrea.ms)

=== Setup Actors

Include the Actor module in a class and override the default followers method.
Expand All @@ -31,8 +43,10 @@ Include the Actor module in a class and override the default followers method.
include Mongoid::Document
include Streama::Actor

field :full_name, :type => String

def followers
...
User.excludes(:id => self.id).all
end
end

Expand All @@ -46,14 +60,14 @@ Create the indexes for the Activities collection. You can do so by calling the c

In your controller or background worker:

current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing)
current_user.publish_activity(:new_enquiry, :object => @enquiry, :target => @listing)

This will publish the activity to the objects returned by the "followers" method in the Actor.
This will publish the activity to the mongoid objects returned by the #followers method in the Actor.

To send your activity to different receievers, pass in an additional :receivers parameter.

current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing, :receivers => :friends) # calls friends method
current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing, :receivers => current_user.find(:all, :conditions => {:group_id => mygroup}))
current_user.publish_activity(:new_enquiry, :object => @enquiry, :target => @listing, :receivers => :friends) # calls friends method
current_user.publish_activity(:new_enquiry, :object => @enquiry, :target => @listing, :receivers => current_user.find(:all, :conditions => {:group_id => mygroup}))

== Retrieving Activity

Expand All @@ -63,9 +77,9 @@ To retrieve all activity for an actor

To retrieve and filter to a particular activity type

current_user.activity_stream(:type => :activity_type)
current_user.activity_stream(:type => :activity_verb)

If you need to return the instance of an :actor, :target or :referrer from an activity call the Activity#load_instance method
If you need to return the instance of an :actor, :object or :target from an activity call the Activity#load_instance method

activity.load_instance(:actor)

Expand All @@ -75,7 +89,7 @@ You can also refresh the cached activity data by calling the Activity#refresh_da

== Compatibility

Streama is developed against Ruby 1.9.2 and Mongoid 2.0.0.rc7
Streama is developed against Ruby 1.9.2 and Mongoid 2

== TODO

Expand Down
30 changes: 15 additions & 15 deletions lib/streama/activity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ module Activity
include Mongoid::Document
include Mongoid::Timestamps

field :name, :type => Symbol
field :verb, :type => Symbol
field :actor, :type => Hash
field :object, :type => Hash
field :target, :type => Hash
field :referrer, :type => Hash
field :receivers, :type => Array

index :name
index [['actor._id', Mongo::ASCENDING], ['actor._type', Mongo::ASCENDING]]
index [['object._id', Mongo::ASCENDING], ['object._type', Mongo::ASCENDING]]
index [['target._id', Mongo::ASCENDING], ['target._type', Mongo::ASCENDING]]
index [['referrer._id', Mongo::ASCENDING], ['referrer._type', Mongo::ASCENDING]]
index [['receivers.id', Mongo::ASCENDING], ['receivers.type', Mongo::ASCENDING]]

validates_presence_of :actor, :name
validates_presence_of :actor, :verb
before_save :assign_data

end
Expand All @@ -33,8 +33,8 @@ module ClassMethods
# @example Define a new activity
# activity(:enquiry) do
# actor :user, :cache => [:full_name]
# target :enquiry, :cache => [:subject]
# referrer :listing, :cache => [:title]
# object :enquiry, :cache => [:subject]
# target :listing, :cache => [:title]
# end
#
# @return [Definition] Returns the registered definition
Expand All @@ -46,18 +46,18 @@ def activity(name, &block)

# Publishes an activity using an activity name and data
#
# @param [ String ] name The name of the activity
# @param [ String ] verb The verb of the activity
# @param [ Hash ] data The data to initialize the activity with.
#
# @return [Streama::Activity] An Activity instance with data
def publish(name, data)
def publish(verb, data)
receivers = data.delete(:receivers)
new({:name => name}.merge(data)).publish(:receivers => receivers)
new({:verb => verb}.merge(data)).publish(:receivers => receivers)
end

def stream_for(actor, options={})
query = {:receivers => {'$elemMatch' => {:id => actor.id, :type => actor.class.to_s}}}
query.merge!({:name => options[:type]}) if options[:type]
query.merge!({:verb => options[:type]}) if options[:type]
self.where(query).without(:receivers).desc(:created_at)
end

Expand All @@ -77,11 +77,11 @@ def publish(options = {})
self
end

# Returns an instance of an actor, target or referrer
# Returns an instance of an actor, object or target
#
# @param [ Symbol ] type The data type (actor, target, referrer) to return an instance for.
# @param [ Symbol ] type The data type (actor, object, target) to return an instance for.
#
# @return [Object] object An object instance
# @return [Mongoid::Document] document A mongoid document instance
def load_instance(type)
(data = self.send(type)).is_a?(Hash) ? data['type'].to_s.camelcase.constantize.find(data['id']) : data
end
Expand All @@ -95,7 +95,7 @@ def refresh_data

def assign_data

[:actor, :target, :referrer].each do |type|
[:actor, :object, :target].each do |type|
next unless object = load_instance(type)

class_sym = object.class.name.underscore.to_sym
Expand All @@ -115,7 +115,7 @@ def assign_data
end

def definition
@definition ||= Streama::Definition.find(name)
@definition ||= Streama::Definition.find(verb)
end

end
Expand Down
6 changes: 3 additions & 3 deletions lib/streama/actor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ module InstanceMethods
#
# @param [ Hash ] options The options to publish with.
#
# @example publish an activity with a target and referrer
# current_user.publish_activity(:enquiry, :target => @enquiry, :referrer => @listing)
# @example publish an activity with a object and target
# current_user.publish_activity(:enquiry, :object => @enquiry, :target => @listing)
#
def publish_activity(name, options={})
options[:receivers] = self.send(options[:receivers]) if options[:receivers].is_a?(Symbol)
Expand All @@ -34,7 +34,7 @@ def activity_stream(options = {})
end

def followers
self.class.all
raise Streama::NoFollowersDefined
end

def activity_class
Expand Down
4 changes: 2 additions & 2 deletions lib/streama/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ module Streama

class Definition

attr_reader :name, :actor, :target, :referrer, :receivers
attr_reader :name, :actor, :object, :target, :receivers

# @param dsl [Streama::DefinitionDSL] A DSL object
def initialize(definition)
@name = definition[:name]
@actor = definition[:actor] || {}
@object = definition[:object] || {}
@target = definition[:target] || {}
@referrer = definition[:referrer] || {}
end

#
Expand Down
6 changes: 3 additions & 3 deletions lib/streama/definition_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ def initialize(name)
@attributes = {
:name => name.to_sym,
:actor => {},
:target => {},
:referrer => {}
:object => {},
:target => {}
}
end

Expand All @@ -22,7 +22,7 @@ def self.data_methods(*args)
end
end
end
data_methods :actor, :target, :referrer
data_methods :actor, :object, :target

end

Expand Down
5 changes: 4 additions & 1 deletion lib/streama/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class InvalidActivity < StreamaError
end

# This error is raised when an object isn't defined
# as an actor, target or referrer
# as an actor, object or target
#
# Example:
#
Expand Down Expand Up @@ -38,4 +38,7 @@ def initialize message
class ActivityNotSaved < StreamaError
end

class NoFollowersDefined < StreamaError
end

end
22 changes: 11 additions & 11 deletions spec/lib/activity_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
it "registers and return a valid definition" do
@definition = Activity.activity(:new_enquiry) do
actor :user, :cache => [:full_name]
target :enquiry, :cache => [:comment]
target :listing, :cache => [:title, :full_address]
referrer :listing, :cache => [:title]
object :enquiry, :cache => [:comment]
object :listing, :cache => [:title, :full_address]
target :listing, :cache => [:title]
end

@definition.is_a?(Streama::Definition).should be true
Expand All @@ -23,7 +23,7 @@

before :each do
@actor = user
@activity = Activity.publish(:new_enquiry, {:actor => @actor, :target => enquiry, :referrer => listing})
@activity = Activity.publish(:new_enquiry, {:actor => @actor, :object => enquiry, :target => listing})
end

it "overrides the recievers if option passed" do
Expand Down Expand Up @@ -52,7 +52,7 @@

describe '.publish' do
it "creates a new activity" do
activity = Activity.publish(:new_enquiry, {:actor => user, :target => enquiry, :referrer => listing})
activity = Activity.publish(:new_enquiry, {:actor => user, :object => enquiry, :target => listing})
activity.should be_an_instance_of Activity
end
end
Expand All @@ -61,7 +61,7 @@

before :each do
@user = user
@activity = Activity.publish(:new_enquiry, {:actor => @user, :target => enquiry, :referrer => listing})
@activity = Activity.publish(:new_enquiry, {:actor => @user, :object => enquiry, :target => listing})
end

it "reloads instances and updates activities stored data" do
Expand All @@ -79,20 +79,20 @@
describe '#load_instance' do

before :each do
@activity = Activity.publish(:new_enquiry, {:actor => user, :target => enquiry, :referrer => listing})
@activity = Activity.publish(:new_enquiry, {:actor => user, :object => enquiry, :target => listing})
@activity = Activity.last
end

it "loads an actor instance" do
@activity.load_instance(:actor).should be_instance_of User
end

it "loads a target instance" do
@activity.load_instance(:target).should be_instance_of Enquiry
it "loads an object instance" do
@activity.load_instance(:object).should be_instance_of Enquiry
end

it "loads a referrer instance" do
@activity.load_instance(:referrer).should be_instance_of Listing
it "loads a target instance" do
@activity.load_instance(:target).should be_instance_of Listing
end

end
Expand Down
10 changes: 5 additions & 5 deletions spec/lib/actor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
before :all do
Activity.activity :new_comment do
actor :user, :cache => [:full_name]
object :listing, :cache => [:title]
target :listing, :cache => [:title]
referrer :listing, :cache => [:title]
end
end

Expand All @@ -21,12 +21,12 @@
end

it "pushes activity to receivers" do
activity = user.publish_activity(:new_enquiry, :target => enquiry, :referrer => listing)
activity = user.publish_activity(:new_enquiry, :object => enquiry, :target => listing)
activity.receivers.size == 6
end

it "pushes to a defined stream" do
activity = user.publish_activity(:new_enquiry, :target => enquiry, :referrer => listing, :receivers => :friends)
activity = user.publish_activity(:new_enquiry, :object => enquiry, :target => listing, :receivers => :friends)
activity.receivers.size == 6
end

Expand All @@ -36,8 +36,8 @@

before :each do
5.times { |n| User.create(:full_name => "Receiver #{n}") }
user.publish_activity(:new_enquiry, :target => enquiry, :referrer => listing)
user.publish_activity(:new_comment, :target => listing)
user.publish_activity(:new_enquiry, :object => enquiry, :target => listing)
user.publish_activity(:new_comment, :object => listing)
end

it "retrieves the stream for an actor" do
Expand Down
12 changes: 6 additions & 6 deletions spec/lib/definition_dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@
dsl.attributes[:actor].should eq :user => { :cache=>[:id, :full_name] }, :company => { :cache=>[:id, :name] }
end

it "adds a target to the definition" do
it "adds an object to the definition" do
dsl = definition_dsl
dsl.target(:listing, :cache => [:id, :title])
dsl.attributes[:target].should eq :listing => { :cache=>[:id, :title] }
dsl.object(:listing, :cache => [:id, :title])
dsl.attributes[:object].should eq :listing => { :cache=>[:id, :title] }
end

it "adds a referrer to the definition" do
it "adds a target to the definition" do
dsl = definition_dsl
dsl.referrer(:company, :cache => [:id, :name])
dsl.attributes[:referrer].should eq :company => { :cache=>[:id, :name] }
dsl.target(:company, :cache => [:id, :name])
dsl.attributes[:target].should eq :company => { :cache=>[:id, :name] }
end

end
Loading

0 comments on commit a57f1ca

Please sign in to comment.