activity_stream 0.0.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.
- data/.gitignore +10 -0
- data/.yardopts +4 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +70 -0
- data/Rakefile +10 -0
- data/Readme.md +71 -0
- data/activity_stream.gemspec +25 -0
- data/app/models/activity.rb +46 -0
- data/generators/activity_stream/activity_stream_generator.rb +28 -0
- data/generators/activity_stream/lib/insert_commands.rb +33 -0
- data/generators/activity_stream/templates/example_activity.rb +6 -0
- data/generators/activity_stream/templates/migration.rb +30 -0
- data/generators/activity_stream/templates/user.rb +5 -0
- data/lib/activity_stream.rb +9 -0
- data/lib/activity_stream/activities_helper.rb +15 -0
- data/lib/activity_stream/actor.rb +68 -0
- data/lib/activity_stream/definition.rb +80 -0
- data/lib/activity_stream/errors.rb +16 -0
- data/lib/activity_stream/metadata.rb +15 -0
- data/lib/activity_stream/stream.rb +38 -0
- data/lib/activity_stream/version.rb +3 -0
- data/rails/init.rb +5 -0
- data/spec/dummy/Gemfile +3 -0
- data/spec/dummy/Gemfile.lock +35 -0
- data/spec/dummy/README +243 -0
- data/spec/dummy/Rakefile +10 -0
- data/spec/dummy/app/controllers/application_controller.rb +10 -0
- data/spec/dummy/app/helpers/application_helper.rb +3 -0
- data/spec/dummy/app/models/activities/example_activity.rb +6 -0
- data/spec/dummy/app/models/user.rb +5 -0
- data/spec/dummy/config/boot.rb +128 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +41 -0
- data/spec/dummy/config/environments/development.rb +17 -0
- data/spec/dummy/config/environments/production.rb +28 -0
- data/spec/dummy/config/environments/test.rb +28 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookie_verification_secret.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/new_rails_defaults.rb +21 -0
- data/spec/dummy/config/initializers/session_store.rb +15 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/preinitializer.rb +20 -0
- data/spec/dummy/config/routes.rb +43 -0
- data/spec/dummy/db/migrate/20101101154941_create_activity_stream_tables.rb +30 -0
- data/spec/dummy/db/schema.rb +28 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/public/404.html +30 -0
- data/spec/dummy/public/422.html +30 -0
- data/spec/dummy/public/500.html +30 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/images/rails.png +0 -0
- data/spec/dummy/public/index.html +275 -0
- data/spec/dummy/public/javascripts/application.js +2 -0
- data/spec/dummy/public/javascripts/controls.js +963 -0
- data/spec/dummy/public/javascripts/dragdrop.js +973 -0
- data/spec/dummy/public/javascripts/effects.js +1128 -0
- data/spec/dummy/public/javascripts/prototype.js +4320 -0
- data/spec/dummy/public/robots.txt +5 -0
- data/spec/dummy/script/about +4 -0
- data/spec/dummy/script/console +3 -0
- data/spec/dummy/script/dbconsole +3 -0
- data/spec/dummy/script/destroy +3 -0
- data/spec/dummy/script/generate +3 -0
- data/spec/dummy/script/performance/benchmarker +3 -0
- data/spec/dummy/script/performance/profiler +3 -0
- data/spec/dummy/script/plugin +3 -0
- data/spec/dummy/script/runner +3 -0
- data/spec/dummy/script/server +3 -0
- data/spec/dummy/test/performance/browsing_test.rb +9 -0
- data/spec/dummy/test/test_helper.rb +38 -0
- data/spec/integration/activity_model_spec.rb +7 -0
- data/spec/lib/actor_spec.rb +5 -0
- data/spec/lib/definition_spec.rb +11 -0
- data/spec/lib/stream_spec.rb +9 -0
- data/spec/spec_helper.rb +26 -0
- metadata +243 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
activity_stream (0.0.1)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: http://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
actionmailer (2.3.10)
|
|
10
|
+
actionpack (= 2.3.10)
|
|
11
|
+
actionpack (2.3.10)
|
|
12
|
+
activesupport (= 2.3.10)
|
|
13
|
+
rack (~> 1.1.0)
|
|
14
|
+
activerecord (2.3.10)
|
|
15
|
+
activesupport (= 2.3.10)
|
|
16
|
+
activeresource (2.3.10)
|
|
17
|
+
activesupport (= 2.3.10)
|
|
18
|
+
activesupport (2.3.10)
|
|
19
|
+
capybara (0.4.0)
|
|
20
|
+
celerity (>= 0.7.9)
|
|
21
|
+
culerity (>= 0.2.4)
|
|
22
|
+
mime-types (>= 1.16)
|
|
23
|
+
nokogiri (>= 1.3.3)
|
|
24
|
+
rack (>= 1.0.0)
|
|
25
|
+
rack-test (>= 0.5.4)
|
|
26
|
+
selenium-webdriver (>= 0.0.27)
|
|
27
|
+
xpath (~> 0.1.2)
|
|
28
|
+
celerity (0.8.2)
|
|
29
|
+
childprocess (0.1.3)
|
|
30
|
+
ffi (~> 0.6.3)
|
|
31
|
+
culerity (0.2.12)
|
|
32
|
+
ffi (0.6.3)
|
|
33
|
+
rake (>= 0.8.7)
|
|
34
|
+
json_pure (1.4.6)
|
|
35
|
+
mime-types (1.16)
|
|
36
|
+
nokogiri (1.4.3.1)
|
|
37
|
+
rack (1.1.0)
|
|
38
|
+
rack-test (0.5.6)
|
|
39
|
+
rack (>= 1.0)
|
|
40
|
+
rails (2.3.10)
|
|
41
|
+
actionmailer (= 2.3.10)
|
|
42
|
+
actionpack (= 2.3.10)
|
|
43
|
+
activerecord (= 2.3.10)
|
|
44
|
+
activeresource (= 2.3.10)
|
|
45
|
+
activesupport (= 2.3.10)
|
|
46
|
+
rake (>= 0.8.3)
|
|
47
|
+
rake (0.8.7)
|
|
48
|
+
rspec (1.3.1)
|
|
49
|
+
rspec-rails (1.3.3)
|
|
50
|
+
rack (>= 1.0.0)
|
|
51
|
+
rspec (= 1.3.1)
|
|
52
|
+
rubyzip (0.9.4)
|
|
53
|
+
selenium-webdriver (0.0.29)
|
|
54
|
+
childprocess (>= 0.0.7)
|
|
55
|
+
ffi (~> 0.6.3)
|
|
56
|
+
json_pure
|
|
57
|
+
rubyzip
|
|
58
|
+
sqlite3-ruby (1.3.2)
|
|
59
|
+
xpath (0.1.2)
|
|
60
|
+
nokogiri (~> 1.3)
|
|
61
|
+
|
|
62
|
+
PLATFORMS
|
|
63
|
+
ruby
|
|
64
|
+
|
|
65
|
+
DEPENDENCIES
|
|
66
|
+
activity_stream!
|
|
67
|
+
capybara
|
|
68
|
+
rails (~> 2.3.10)
|
|
69
|
+
rspec-rails (~> 1.3.0)
|
|
70
|
+
sqlite3-ruby
|
data/Rakefile
ADDED
data/Readme.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# ActivityStream (early alpha) #
|
|
2
|
+
|
|
3
|
+
Activity Stream provides a simple DSL to define, create,
|
|
4
|
+
and retrieve user activities.
|
|
5
|
+
|
|
6
|
+
## Installation ##
|
|
7
|
+
|
|
8
|
+
Add it to your Gemfile:
|
|
9
|
+
|
|
10
|
+
gem 'activity_stream'
|
|
11
|
+
|
|
12
|
+
Run the generator:
|
|
13
|
+
|
|
14
|
+
script/generate activity_stream
|
|
15
|
+
|
|
16
|
+
And migrate the database:
|
|
17
|
+
|
|
18
|
+
rake db:migrate
|
|
19
|
+
|
|
20
|
+
## Usage ##
|
|
21
|
+
|
|
22
|
+
### Defining Activities ###
|
|
23
|
+
|
|
24
|
+
In `app/models/activities/example_action_activity.rb`:
|
|
25
|
+
|
|
26
|
+
Activity.define(:example_action) do
|
|
27
|
+
metadata(:target, :default => :actor)
|
|
28
|
+
metadata(:referrer)
|
|
29
|
+
icon('example_activity_icon.png')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
### Extending User ###
|
|
33
|
+
|
|
34
|
+
In your User model:
|
|
35
|
+
|
|
36
|
+
class User < ActiveRecord::Base
|
|
37
|
+
|
|
38
|
+
include ActivityStream::Actor
|
|
39
|
+
|
|
40
|
+
def activity_stream_actors
|
|
41
|
+
[[User, 13], [User, 14], [Page, 9]]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
### Retrieving Activities ###
|
|
47
|
+
|
|
48
|
+
In your dashboard controller:
|
|
49
|
+
|
|
50
|
+
@activity_stream = current_user.activity_stream
|
|
51
|
+
|
|
52
|
+
### Creating Activies ###
|
|
53
|
+
|
|
54
|
+
When you want to create an activity:
|
|
55
|
+
|
|
56
|
+
current_user.create_activity(:example_action,
|
|
57
|
+
:target => @friend,
|
|
58
|
+
:referrer => @referrer)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## Notes ##
|
|
62
|
+
|
|
63
|
+
Currently designed for Rails 2.3.10, because the project
|
|
64
|
+
that prompted its creation is that version. I can't guarantee
|
|
65
|
+
that it will work in any other version of Rails.
|
|
66
|
+
|
|
67
|
+
However, I do have other projects, that are Rails 3, that will
|
|
68
|
+
benefit from a Rails 3 compatible version of activity_stream.
|
|
69
|
+
Be on the lookout for updates!
|
|
70
|
+
|
|
71
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "activity_stream/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "activity_stream"
|
|
7
|
+
s.version = ActivityStream::VERSION
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
s.authors = ["Andrew Smith"]
|
|
10
|
+
s.email = ["andrew@envylabs.com"]
|
|
11
|
+
s.homepage = "http://rubygems.org/gems/activity_stream"
|
|
12
|
+
s.summary = %q{Rails plugin to add activity streams for your users}
|
|
13
|
+
s.description = %q{Rails plugin to add activity streams for your users, highly opinionated.}
|
|
14
|
+
|
|
15
|
+
s.rubyforge_project = "activity_stream"
|
|
16
|
+
|
|
17
|
+
s.files = `git ls-files`.split("\n")
|
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
20
|
+
s.require_paths = ["lib"]
|
|
21
|
+
|
|
22
|
+
s.add_development_dependency "rspec-rails", "~> 1.3.0"
|
|
23
|
+
s.add_development_dependency "rails", "~> 2.3.10"
|
|
24
|
+
s.add_development_dependency "capybara"
|
|
25
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class Activity < ActiveRecord::Base
|
|
2
|
+
|
|
3
|
+
belongs_to :actor, :polymorphic => true
|
|
4
|
+
|
|
5
|
+
# @param name [Symbol] (see ActivityStream::Definition#new)
|
|
6
|
+
# @return [ActivityStream::Definition] the new definitions
|
|
7
|
+
#
|
|
8
|
+
def self.define(name, &block)
|
|
9
|
+
definition = ActivityStream::Definition.new(name)
|
|
10
|
+
definition.instance_eval(&block)
|
|
11
|
+
ActivityStream::Definition.register(definition)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
named_scope :in_reverse_chronological_order, :order => 'occurred_at DESC'
|
|
15
|
+
|
|
16
|
+
named_scope :in_chronological_order, :order => 'occurred_at ASC'
|
|
17
|
+
|
|
18
|
+
# @param actors [Array] An array of [ActorClass, actor_id] sets
|
|
19
|
+
# or [ActorClass, [actor_id, actor_id, actor_id...]
|
|
20
|
+
#
|
|
21
|
+
named_scope :by_actors, lambda { |actors|
|
|
22
|
+
if actors.first.is_a?(Array)
|
|
23
|
+
conditions = actors.map do |(actor_type, actor_id)|
|
|
24
|
+
%{("activities"."actor_id" = #{actor_id.to_param} AND "activities"."actor_type" = '#{actor_type.to_param}')}
|
|
25
|
+
end
|
|
26
|
+
{:conditions => conditions.join(' OR ') }
|
|
27
|
+
elsif actors.first.is_a?(Class)
|
|
28
|
+
{:conditions => {:actor_id => actors.last, :actor_type => actors.first.to_param}}
|
|
29
|
+
else
|
|
30
|
+
{} # Not sure what to do here.
|
|
31
|
+
end
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
serialize :metadata, ActivityStream::Metadata
|
|
35
|
+
|
|
36
|
+
delegate :template, :icon, :to => :definition
|
|
37
|
+
|
|
38
|
+
def metadata
|
|
39
|
+
self[:metadata] ||= ActivityStream::Metadata.new(self[:kind])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def definition
|
|
43
|
+
ActivityStream::Definition.find_by_name(self[:kind])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
|
|
2
|
+
# require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
|
|
3
|
+
|
|
4
|
+
class ActivityStreamGenerator < Rails::Generator::Base
|
|
5
|
+
|
|
6
|
+
def manifest
|
|
7
|
+
record do |m|
|
|
8
|
+
|
|
9
|
+
m.directory(File.join('app','models','activities'))
|
|
10
|
+
m.template('example_activity.rb', 'app/models/activities/example_activity.rb')
|
|
11
|
+
|
|
12
|
+
user_model = 'app/models/user.rb'
|
|
13
|
+
if File.exists?(user_model)
|
|
14
|
+
m.insert_into(user_model, "include ActivityStream::Actor")
|
|
15
|
+
else
|
|
16
|
+
m.directory(File.join('app', 'models'))
|
|
17
|
+
m.file('user.rb', user_model)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
m.migration_template('migration.rb',
|
|
21
|
+
'db/migrate',
|
|
22
|
+
:migration_file_name => 'create_activity_stream_tables',
|
|
23
|
+
:assigns => {:has_users => ActiveRecord::Base.connection.table_exists?(:users)})
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
|
|
2
|
+
|
|
3
|
+
Rails::Generator::Commands::Base.class_eval do
|
|
4
|
+
def file_contains?(relative_destination, line)
|
|
5
|
+
File.read(destination_path(relative_destination)).include?(line)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
Rails::Generator::Commands::Create.class_eval do
|
|
10
|
+
def insert_into(file, line)
|
|
11
|
+
logger.insert "#{line} into #{file}"
|
|
12
|
+
unless options[:pretend] || file_contains?(file, line)
|
|
13
|
+
gsub_file file, /^(class|module|.*Routes).*$/ do |match|
|
|
14
|
+
"#{match}\n #{line}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
|
21
|
+
def insert_into(file, line)
|
|
22
|
+
logger.remove "#{line} from #{file}"
|
|
23
|
+
unless options[:pretend]
|
|
24
|
+
gsub_file file, "\n #{line}", ''
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Rails::Generator::Commands::List.class_eval do
|
|
30
|
+
def insert_into(file, line)
|
|
31
|
+
logger.insert "#{line} into #{file}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class CreateActivityStreamTables < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
|
|
4
|
+
create_table :activities do |t|
|
|
5
|
+
t.integer :actor_id
|
|
6
|
+
t.string :actor_type
|
|
7
|
+
t.string :kind
|
|
8
|
+
t.text :metadata
|
|
9
|
+
t.datetime :occurred_at
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
add_index :activities, [:actor_id, :actor_type]
|
|
13
|
+
|
|
14
|
+
<% unless has_users %>
|
|
15
|
+
create_table :users do |t|
|
|
16
|
+
t.string :name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
<% end %>
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.down
|
|
23
|
+
<% unless has_users %>
|
|
24
|
+
drop_table :users
|
|
25
|
+
<% end %>
|
|
26
|
+
|
|
27
|
+
drop_table :activities
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ActivityStream
|
|
2
|
+
|
|
3
|
+
module ActivitiesHelper
|
|
4
|
+
|
|
5
|
+
def render_activities(activities)
|
|
6
|
+
return nil if activities.empty?
|
|
7
|
+
activities.map do |activity|
|
|
8
|
+
_partial_name = activity.template
|
|
9
|
+
template = self.view_paths.find_template(%{activities/_#{_partial_name}}, :html)
|
|
10
|
+
template.render_partial(self, activity)
|
|
11
|
+
end.join('').html_safe
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module ActivityStream
|
|
2
|
+
|
|
3
|
+
# @example Definition
|
|
4
|
+
# class User < ActiveRecord::Base
|
|
5
|
+
#
|
|
6
|
+
# include ActivityStream::Actor
|
|
7
|
+
#
|
|
8
|
+
# activity_stream(:friends, :actors => :friend_actors)
|
|
9
|
+
#
|
|
10
|
+
# def friend_actors
|
|
11
|
+
# friend_ids.map{|id| [User, id]}
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# def friend_ids
|
|
15
|
+
# # get friend ids
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# @example Usage
|
|
21
|
+
# @user.activity_stream(:friends) # => <ActivityStream::Stream>
|
|
22
|
+
module Actor
|
|
23
|
+
|
|
24
|
+
def self.included(base)
|
|
25
|
+
base.extend(ClassMethods)
|
|
26
|
+
base.class_eval do
|
|
27
|
+
has_many :activities, :as => :actor
|
|
28
|
+
activity_stream(:all, :actors => :activity_stream_actors)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param name [Symbol] An activity identifer defined by Activity.define
|
|
33
|
+
def create_activity(name)
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Creates and returns an ActivityStream::Stream for the predefined
|
|
38
|
+
# list of actors.
|
|
39
|
+
# @param name [Symbol] The key of a defined activity stream
|
|
40
|
+
def activity_stream(name)
|
|
41
|
+
ActivityStream::Stream.new(name, self, self.class.defined_streams[name])
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def activity_stream_actors
|
|
45
|
+
self.class.all.map{|actor| [actor.class, actor.id]}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module ClassMethods
|
|
49
|
+
|
|
50
|
+
# @attr_accessor defined_streams
|
|
51
|
+
attr_accessor :defined_streams
|
|
52
|
+
|
|
53
|
+
# Creates an activity_stream instance method that fetches
|
|
54
|
+
# all recent activity
|
|
55
|
+
#
|
|
56
|
+
# @param name [Symbol] the name for the sub stream you wish to access
|
|
57
|
+
# @option opts (see ActivityStream::Stream#new)
|
|
58
|
+
def activity_stream(name, opts = {})
|
|
59
|
+
self.defined_streams ||= {}
|
|
60
|
+
self.defined_streams[name.to_sym] = opts
|
|
61
|
+
return nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|