activist 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ .rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in activist.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,50 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ activist (0.0.1)
5
+ activesupport (~> 3.0)
6
+ redis (~> 2.2)
7
+ redis-namespace (= 0.10.0)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activemodel (3.0.7)
13
+ activesupport (= 3.0.7)
14
+ builder (~> 2.1.2)
15
+ i18n (~> 0.5.0)
16
+ activerecord (3.0.7)
17
+ activemodel (= 3.0.7)
18
+ activesupport (= 3.0.7)
19
+ arel (~> 2.0.2)
20
+ tzinfo (~> 0.3.23)
21
+ activesupport (3.0.7)
22
+ arel (2.0.9)
23
+ builder (2.1.2)
24
+ diff-lcs (1.1.2)
25
+ i18n (0.5.0)
26
+ redis (2.2.0)
27
+ redis-namespace (0.10.0)
28
+ redis (< 3.0.0)
29
+ rspec (2.5.0)
30
+ rspec-core (~> 2.5.0)
31
+ rspec-expectations (~> 2.5.0)
32
+ rspec-mocks (~> 2.5.0)
33
+ rspec-core (2.5.1)
34
+ rspec-expectations (2.5.0)
35
+ diff-lcs (~> 1.1.2)
36
+ rspec-mocks (2.5.0)
37
+ sqlite3 (1.3.3)
38
+ sqlite3-ruby (1.3.3)
39
+ sqlite3 (>= 1.3.3)
40
+ tzinfo (0.3.27)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ activerecord (~> 3.0)
47
+ activist!
48
+ bundler (~> 1.0)
49
+ rspec (~> 2.0)
50
+ sqlite3-ruby (~> 1.3.2)
data/LICENCE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Adrian Dulić
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.markdown ADDED
@@ -0,0 +1,49 @@
1
+ # Activist #
2
+
3
+ Activity stream in rails 3.0 applications
4
+
5
+ Based on http://activitystrea.ms/spec/1.0/atom-activity-01.html
6
+
7
+ ## Installation ##
8
+
9
+ Just run the following command :
10
+
11
+ gem install activist
12
+
13
+ Then in your Gemfile add the following line :
14
+
15
+ gem 'activist'
16
+
17
+ And run
18
+
19
+ bundle install
20
+
21
+ ## Usage ##
22
+
23
+ First generate a friendship model :
24
+
25
+ rails generate activist:install
26
+
27
+ This command creates a new model called __Action__ in *'app/models'* :
28
+
29
+ class Status < ActiveRecord::Base
30
+ serialize :data, Hash
31
+ end
32
+
33
+ It also creates a new migration for the Status model so don't forget to migrate your database :
34
+
35
+ rake db:migrate
36
+
37
+ Then add __activist__ in your user model :
38
+
39
+ class User < ActiveRecord::Base
40
+ include Activist::Actor
41
+
42
+ stream :public do
43
+ all
44
+ end
45
+
46
+ stream :private do
47
+ [user]
48
+ end
49
+ end
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec'
5
+ require 'rspec/core/rake_task'
6
+
7
+ Rspec::Core::RakeTask.new(:spec)
data/activist.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "activist/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "activist"
7
+ s.version = Activist::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Adrian Dulić"]
10
+ s.email = ["adulic@gmail.com"]
11
+ s.homepage = "http://github.com/adriandulic/activist"
12
+ s.summary = %q{Activity stream in rails 3.0 application}
13
+ s.description = %q{Activity stream in rails 3.0 application}
14
+
15
+ s.extra_rdoc_files = ["README.markdown"]
16
+
17
+ s.required_rubygems_version = ">= 1.3.6"
18
+ s.rubyforge_project = s.name
19
+
20
+ s.add_dependency "redis", "~> 2.2"
21
+ s.add_dependency "redis-namespace", "0.10.0"
22
+ s.add_dependency "activesupport", "~> 3.0"
23
+
24
+ s.add_development_dependency "bundler", "~> 1.0"
25
+ s.add_development_dependency "rspec", "~> 2.0"
26
+ s.add_development_dependency "activerecord", "~> 3.0"
27
+ s.add_development_dependency "sqlite3-ruby", "~> 1.3.2"
28
+
29
+ s.files = `git ls-files`.split("\n")
30
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
32
+ s.require_paths = ["lib"]
33
+ end
data/lib/activist.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'active_support/configurable'
2
+ require 'active_support/concern'
3
+ require 'redis/namespace'
4
+ require 'redis'
5
+
6
+ module Activist
7
+ autoload :Redis, 'activist/redis'
8
+ autoload :Store, 'activist/store'
9
+ autoload :Actor, 'activist/actor'
10
+ autoload :Action, 'activist/action'
11
+ autoload :Stream, 'activist/stream'
12
+ end
@@ -0,0 +1,25 @@
1
+ module Activist
2
+ module Action
3
+ extend ActiveSupport::Concern
4
+ include Store
5
+
6
+ module ClassMethods
7
+ def activities(stream, options = {})
8
+ options.symbolize_keys!
9
+ callback = options[:when]
10
+
11
+ define_method "activist_#{stream}_#{callback}" do
12
+ store_activities(stream, options)
13
+ end
14
+
15
+ send(callback, "activist_#{stream}_#{callback}")
16
+ end
17
+ end
18
+
19
+ module InstanceMethods
20
+ def activity(stream, options = {})
21
+ store_activities(stream, options)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ module Activist
2
+ module Actor
3
+ def self.included(receiver)
4
+ receiver.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def stream(stream, &block)
9
+ define_method "#{stream}_stream" do
10
+ Activist::Stream.new(stream, self, block)
11
+ end
12
+
13
+ after_destroy "delete_activist_#{stream}_stream"
14
+
15
+ private
16
+
17
+ define_method "delete_activist_#{stream}_stream" do
18
+ send("#{stream}_stream").destroy
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module Activist
2
+ class Redis
3
+ include ActiveSupport::Configurable
4
+
5
+ config_accessor :host, :port, :db
6
+
7
+ def self.execute
8
+ @connection ||= ::Redis.new(:host => host || 'localhost', :port => port || 6379, :db => db || nil)
9
+ @redis ||= ::Redis::Namespace.new(:activist, :redis => @connection)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,53 @@
1
+ module Activist
2
+ module Store
3
+ extend ActiveSupport::Concern
4
+
5
+ module InstanceMethods
6
+ def store_activities(stream, options = {})
7
+ options.symbolize_keys!
8
+ callback = options.delete(:when)
9
+ actor = case options[:actor]
10
+ when nil
11
+ send(:user)
12
+ when Symbol
13
+ send(options[:actor])
14
+ when Proc
15
+ options[:actor].call(self)
16
+ else
17
+ options[:actor]
18
+ end
19
+ action = if options[:action].nil?
20
+ case callback
21
+ when :before_create, :after_create
22
+ options[:action] = :created
23
+ when :before_save, :after_save
24
+ options[:action] = :saved
25
+ when :before_update, :after_update
26
+ options[:action] = :updated
27
+ when :before_destroy, :after_destroy
28
+ options[:action] = :destroyed
29
+ else
30
+ options[:action] = :undefined
31
+ end
32
+ else
33
+ options[:action]
34
+ end
35
+ data = options[:data]
36
+
37
+ status = ::Status.create! do |s|
38
+ s.actor_class = actor.class.to_s
39
+ s.actor_id = actor.id
40
+ s.action = action
41
+ s.target_class = self.class.to_s
42
+ s.target_id = self.id
43
+ s.data = data
44
+ s.created_at = Time.now.utc
45
+ end
46
+
47
+ actor.send("#{stream}_stream").subscribers.each do |subscriber|
48
+ Redis.execute.lpush("#{subscriber.class}.#{subscriber.id}:#{stream}", status.id)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,34 @@
1
+ module Activist
2
+ class Stream
3
+ attr_reader :name, :actor, :subscribers
4
+
5
+ def initialize(name, actor, block)
6
+ @name = name.to_sym
7
+ @actor = actor
8
+ scoped = block.call(actor)
9
+ @subscribers = case scoped
10
+ when Symbol
11
+ actor.class.send(scoped)
12
+ when Array
13
+ scoped
14
+ end
15
+ end
16
+
17
+ def all(options={})
18
+ activities = Redis.execute.lrange(to_key, options[:offset] || 0, options[:limit] || size)
19
+ ::Status.where(:id => activities)
20
+ end
21
+
22
+ def size
23
+ @size ||= Redis.execute.llen(to_key)
24
+ end
25
+
26
+ def destroy
27
+ Redis.execute.del(to_key)
28
+ end
29
+
30
+ def to_key
31
+ "#{@actor.class}.#{@actor.id}:#{@name}"
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Activist
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,24 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module Activist
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+
9
+ def self.source_root
10
+ @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
11
+ end
12
+
13
+ def self.next_migration_number
14
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
15
+ end
16
+
17
+ desc "This generator creates a status model and its migration file"
18
+ def create_friendship_model_files
19
+ template 'status.rb', 'app/models/status.rb'
20
+ template 'create_statuses.rb', "db/migrate/#{self.class.next_migration_number}_create_statuses.rb"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ class CreateStatuses < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :statuses do |t|
4
+ t.string :actor_class
5
+ t.integer :actor_id
6
+ t.string :action
7
+ t.string :target_class
8
+ t.integer :target_id
9
+ t.text :data
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+
15
+ def self.down
16
+ drop_table :statuses
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ class Status < ActiveRecord::Base
2
+ serialize :data, Hash
3
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Activist do
4
+ before do
5
+ @region = Region.create!(:name => "Mazovia")
6
+ @kate = User.create!(:name => "Kate", :regions => Region.all)
7
+ @john = User.create!(:name => "John", :regions => Region.all)
8
+ end
9
+
10
+ context "actor" do
11
+ it "should create streams for actor" do
12
+ @kate.public_stream.should be_kind_of Activist::Stream
13
+ @kate.regional_stream.should be_kind_of Activist::Stream
14
+ @kate.private_stream.should be_kind_of Activist::Stream
15
+ end
16
+ end
17
+
18
+ context "action" do
19
+ end
20
+
21
+ context "stream" do
22
+ end
23
+ end
data/spec/setup.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Base.establish_connection(
4
+ :adapter => "sqlite3",
5
+ :database => ":memory:"
6
+ )
7
+ ActiveRecord::Migration.verbose = false
8
+
9
+ ActiveRecord::Schema.define do
10
+ create_table :statuses, :force => true do |t|
11
+ t.string :actor_class
12
+ t.integer :actor_id
13
+ t.string :action
14
+ t.string :target_class
15
+ t.integer :target_id
16
+ t.text :data
17
+ t.datetime :created_at
18
+ t.datetime :updated_at
19
+ end
20
+
21
+ create_table :regions, :force => true do |t|
22
+ t.string :name
23
+ end
24
+
25
+ create_table :regions_users, :id => false, :force => true do |t|
26
+ t.integer :user_id
27
+ t.integer :region_id
28
+ end
29
+
30
+ create_table :users, :force => true do |t|
31
+ t.string :name
32
+ end
33
+
34
+ create_table :notes, :force => true do |t|
35
+ t.integer :user_id
36
+ t.string :note
37
+ end
38
+ end
39
+
40
+ Activist::Redis.host = 'localhost'
41
+ Activist::Redis.port = 6379
42
+ Activist::Redis.execute.flushall
43
+
44
+ class Status < ActiveRecord::Base
45
+ serialize :data, Hash
46
+ end
47
+
48
+ class Region < ActiveRecord::Base
49
+ has_and_belongs_to_many :users
50
+ end
51
+
52
+ class User < ActiveRecord::Base
53
+ include Activist::Actor
54
+ has_many :notes
55
+ has_and_belongs_to_many :regions
56
+
57
+ stream :public do
58
+ all
59
+ end
60
+
61
+ stream :regional do |user|
62
+ User.joins(:regions).where(:'regions.id' => user.regions).all
63
+ end
64
+
65
+ stream :private do |user|
66
+ [user]
67
+ end
68
+ end
69
+
70
+ class Note < ActiveRecord::Base
71
+ include Activist::Action
72
+ belongs_to :user
73
+
74
+ activities :regional, :when => :after_create
75
+ activities :private, :when => :after_create
76
+
77
+ after_destroy do |note|
78
+ activity :private, :action => :deleted
79
+ end
80
+
81
+ def test
82
+ self.note = "#{self.note}. Tested."
83
+ activity :private, :action => :tested
84
+ end
85
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+ require 'activist'
3
+ require 'setup'
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activist
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.2
6
+ platform: ruby
7
+ authors:
8
+ - "Adrian Duli\xC4\x87"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-04-29 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: redis
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: "2.2"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: redis-namespace
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - "="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.10.0
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: activesupport
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: "3.0"
46
+ type: :runtime
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: bundler
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: "1.0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rspec
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: "2.0"
68
+ type: :development
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: activerecord
72
+ prerelease: false
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: "3.0"
79
+ type: :development
80
+ version_requirements: *id006
81
+ - !ruby/object:Gem::Dependency
82
+ name: sqlite3-ruby
83
+ prerelease: false
84
+ requirement: &id007 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 1.3.2
90
+ type: :development
91
+ version_requirements: *id007
92
+ description: Activity stream in rails 3.0 application
93
+ email:
94
+ - adulic@gmail.com
95
+ executables: []
96
+
97
+ extensions: []
98
+
99
+ extra_rdoc_files:
100
+ - README.markdown
101
+ files:
102
+ - .gitignore
103
+ - Gemfile
104
+ - Gemfile.lock
105
+ - LICENCE
106
+ - README.markdown
107
+ - Rakefile
108
+ - activist.gemspec
109
+ - lib/activist.rb
110
+ - lib/activist/action.rb
111
+ - lib/activist/actor.rb
112
+ - lib/activist/redis.rb
113
+ - lib/activist/store.rb
114
+ - lib/activist/stream.rb
115
+ - lib/activist/version.rb
116
+ - lib/generators/activist/install/install_generator.rb
117
+ - lib/generators/activist/install/templates/create_statuses.rb
118
+ - lib/generators/activist/install/templates/status.rb
119
+ - spec/activist_spec.rb
120
+ - spec/setup.rb
121
+ - spec/spec_helper.rb
122
+ homepage: http://github.com/adriandulic/activist
123
+ licenses: []
124
+
125
+ post_install_message:
126
+ rdoc_options: []
127
+
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: "0"
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: 1.3.6
142
+ requirements: []
143
+
144
+ rubyforge_project: activist
145
+ rubygems_version: 1.7.2
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: Activity stream in rails 3.0 application
149
+ test_files:
150
+ - spec/activist_spec.rb
151
+ - spec/setup.rb
152
+ - spec/spec_helper.rb