protocolist 0.8.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/Gemfile +5 -0
- data/Guardfile +7 -0
- data/LICENSE +20 -0
- data/README.md +134 -0
- data/Rakefile +1 -0
- data/lib/generators/protocolist/install/USAGE +1 -0
- data/lib/generators/protocolist/install/install_generator.rb +29 -0
- data/lib/generators/protocolist/install/templates/migration.rb +14 -0
- data/lib/protocolist.rb +29 -0
- data/lib/protocolist/controller_additions.rb +50 -0
- data/lib/protocolist/model_additions.rb +41 -0
- data/lib/protocolist/railtie.rb +14 -0
- data/lib/protocolist/version.rb +3 -0
- data/protocolist.gemspec +25 -0
- data/spec/protocolist/controller_additions_spec.rb +96 -0
- data/spec/protocolist/model_additions_spec.rb +143 -0
- data/spec/protocolist_spec.rb +54 -0
- data/spec/spec_helper.rb +9 -0
- metadata +110 -0
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Dmitry Yakimov
|
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.md
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
Protocolist
|
2
|
+
===========
|
3
|
+
|
4
|
+
Simple activity feeds solution for Rails applications. Gives a flexible way to build activity feeds infrastructure over it.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
Add the gem to your Gemfile and run the `bundle install` command to install it.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'protocolist'
|
13
|
+
```
|
14
|
+
|
15
|
+
Run the generator to create Activity model and migration.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
rails generate protocolist:install
|
19
|
+
```
|
20
|
+
|
21
|
+
Run migration then:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
rake db:migrate
|
25
|
+
```
|
26
|
+
|
27
|
+
Getting started
|
28
|
+
---------------
|
29
|
+
|
30
|
+
Activity model has four attributes: subject("who did it"), activity_type("what
|
31
|
+
they did"), object("what they did it to") and data(additional information). Subject will be
|
32
|
+
set as current user by default.
|
33
|
+
|
34
|
+
Protocolist expects you to have `current_user` method in a controller.
|
35
|
+
̶S̶e̶e̶ ̶C̶h̶a̶n̶g̶i̶n̶g̶ ̶D̶e̶f̶a̶u̶l̶t̶s̶ ̶t̶o̶ ̶c̶h̶a̶n̶g̶e̶ ̶t̶h̶i̶s̶ ̶b̶e̶h̶a̶v̶i̶o̶r̶.̶
|
36
|
+
|
37
|
+
Usage in models
|
38
|
+
---------------
|
39
|
+
|
40
|
+
The simplest way is just to write inside your model:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
fires :create
|
44
|
+
```
|
45
|
+
|
46
|
+
When "create" event will be triggered, it will automatically create
|
47
|
+
Activity with current user set as subject, `:create` as type,
|
48
|
+
`self` as object and empty data.
|
49
|
+
|
50
|
+
The more convenient usage:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
fires :edit, :on => :update,
|
54
|
+
:data => :changes,
|
55
|
+
:if => 'changes.any?'
|
56
|
+
```
|
57
|
+
|
58
|
+
The event type will be `edit`. A proc, symbol a̶n̶d̶ ̶a̶ ̶s̶t̶r̶i̶n̶g̶ for data
|
59
|
+
option represent a method, else types will be stored as is.
|
60
|
+
|
61
|
+
The `unless` option also can be passed.
|
62
|
+
|
63
|
+
The `on` option can be an array:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
fires :comment_activity, :on => [:create, :update, :destroy]
|
67
|
+
```
|
68
|
+
|
69
|
+
The most flexible way is to use `fire` method:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
def destroy_projects
|
73
|
+
self.projects.destroy_all
|
74
|
+
fire :destroy_all, :object => false, :data => {:company_id => company_id}
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
If you run without `:object` option set, it will default to `self`.
|
79
|
+
|
80
|
+
Usage in controllers
|
81
|
+
--------------------
|
82
|
+
|
83
|
+
The simple one:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
fires :download
|
87
|
+
```
|
88
|
+
|
89
|
+
which will strike after download action.
|
90
|
+
|
91
|
+
The customized one:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
fires :download, :only => [:download_report, :download_file, :download_map],
|
95
|
+
:data => lambda{|c| c.params[:city] },
|
96
|
+
:if => lambda{|c| c.response.status == 200 }
|
97
|
+
```
|
98
|
+
|
99
|
+
The `fire` method can be used same way as in models, but also if type is not
|
100
|
+
set, it will be set as `action_name`, and object will try to store `@model_instance`.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
def show
|
104
|
+
@article = Article.find(params[:id])
|
105
|
+
fire
|
106
|
+
end
|
107
|
+
```
|
108
|
+
is the same as
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
def show
|
112
|
+
@article = Article.find(params[:id])
|
113
|
+
fire :show, :object => @article
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
Contributing
|
118
|
+
------------
|
119
|
+
I would appreciate any help with gem development: pull requests, issue
|
120
|
+
posts, etc.
|
121
|
+
|
122
|
+
|
123
|
+
Also there is probably a bunch of mistakes in English grammar/spelling. Any
|
124
|
+
corrections are also appreciated, especially from native speakers.
|
125
|
+
|
126
|
+
Thanks
|
127
|
+
--------------
|
128
|
+
Protocolist was inspired by
|
129
|
+
[timeline_fu](https://github.com/jamesgolick/timeline_fu). I used it,
|
130
|
+
but its functionality wasn't enough for me, so I made my own with
|
131
|
+
blackjack and stewardesses.
|
132
|
+
|
133
|
+
|
134
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1 @@
|
|
1
|
+
Generates both the Activity class and the migration to create its table. The table will have subject, object, type and data columns.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module Protocolist
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
|
10
|
+
def generate_activity_model
|
11
|
+
migration_template "migration.rb", "db/migrate/create_activities"
|
12
|
+
invoke "active_record:model", ['Activity'], :migration => false
|
13
|
+
model_content = <<CONTENT
|
14
|
+
attr_accessible :activity_type, :object, :subject, :data
|
15
|
+
belongs_to :object, :polymorphic => true
|
16
|
+
belongs_to :subject, :polymorphic => true
|
17
|
+
serialize :data
|
18
|
+
CONTENT
|
19
|
+
inject_into_class('app/models/activity.rb', 'Activity', model_content) if File.exists?(File.join(destination_root, 'app/models/activity.rb'))
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.next_migration_number(dirname) #:nodoc:
|
25
|
+
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateActivities < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :activities do |t|
|
4
|
+
t.references :subject, :polymorphic => true
|
5
|
+
t.references :object, :polymorphic => true
|
6
|
+
t.string :activity_type
|
7
|
+
t.text :data
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
add_index :activities, :subject_id
|
12
|
+
add_index :activities, :object_id
|
13
|
+
end
|
14
|
+
end
|
data/lib/protocolist.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "protocolist/version"
|
2
|
+
require "protocolist/model_additions"
|
3
|
+
require "protocolist/controller_additions"
|
4
|
+
require "protocolist/railtie" if defined? Rails
|
5
|
+
|
6
|
+
|
7
|
+
module Protocolist
|
8
|
+
|
9
|
+
def self.fire activity_type, options={}
|
10
|
+
options = {:subject => @@subject, :activity_type => activity_type}.merge options
|
11
|
+
@@activity_class.create options if options[:subject] && @@activity_class
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.subject
|
15
|
+
@@subject
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.subject= subject
|
19
|
+
@@subject = subject
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.activity_class
|
23
|
+
@@activity_class
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.activity_class= activity_class
|
27
|
+
@@activity_class = activity_class
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Protocolist
|
2
|
+
module ControllerAdditions
|
3
|
+
module ClassMethods
|
4
|
+
def fires activity_type, options={}
|
5
|
+
#options normalization
|
6
|
+
options[:only] ||= activity_type unless options[:except]
|
7
|
+
|
8
|
+
data_proc = if options[:data].respond_to?(:call)
|
9
|
+
lambda{|controller| options[:data].call(controller)}
|
10
|
+
elsif options[:data].class == Symbol
|
11
|
+
lambda{|controller| controller.send(options[:data]) }
|
12
|
+
else
|
13
|
+
lambda{|record| options[:data] }
|
14
|
+
end
|
15
|
+
|
16
|
+
options_for_callback = options.select{|k,v| [:if, :unless, :only, :except].include? k }
|
17
|
+
|
18
|
+
options_for_fire = options.reject{|k,v| [:if, :unless, :only, :except].include? k }
|
19
|
+
|
20
|
+
callback_proc = lambda{|controller|
|
21
|
+
controller.fire activity_type, options_for_fire.merge({:data => data_proc.call(controller)})
|
22
|
+
}
|
23
|
+
|
24
|
+
send(:after_filter, callback_proc, options_for_callback)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def self.extended base
|
29
|
+
base.send(:before_filter, :initilize_protocolist)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.included base
|
34
|
+
base.extend ClassMethods
|
35
|
+
end
|
36
|
+
|
37
|
+
def fire activity_type=nil, options={}
|
38
|
+
options[:object] = instance_variable_get("@#{self.controller_name.singularize}") if options[:object] == nil
|
39
|
+
options[:object] = nil if options[:object] == false
|
40
|
+
activity_type ||= action_name.to_sym
|
41
|
+
|
42
|
+
Protocolist.fire activity_type, options
|
43
|
+
end
|
44
|
+
|
45
|
+
def initilize_protocolist
|
46
|
+
Protocolist.subject = current_user
|
47
|
+
Protocolist.activity_class = Activity
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Protocolist
|
2
|
+
module ModelAdditions
|
3
|
+
module ClassMethods
|
4
|
+
def fires activity_type, options={}
|
5
|
+
#options normalization
|
6
|
+
fires_on = Array(options[:on] || activity_type)
|
7
|
+
|
8
|
+
data_proc = if options[:data].respond_to?(:call)
|
9
|
+
lambda{|record| options[:data].call(record)}
|
10
|
+
elsif options[:data].class == Symbol
|
11
|
+
lambda{|record| record.send(options[:data]) }
|
12
|
+
else
|
13
|
+
lambda{|record| options[:data] }
|
14
|
+
end
|
15
|
+
|
16
|
+
options_for_callback = options.select{|k,v| [:if, :unless].include? k }
|
17
|
+
|
18
|
+
options_for_fire = options.reject{|k,v| [:if, :unless, :on].include? k }
|
19
|
+
|
20
|
+
callback_proc = lambda{|record|
|
21
|
+
record.fire activity_type, options_for_fire.merge({:data => data_proc.call(record)})
|
22
|
+
}
|
23
|
+
|
24
|
+
fires_on.each do |on|
|
25
|
+
send("after_#{on.to_s}".to_sym, callback_proc, options_for_callback)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.included base
|
31
|
+
base.extend ClassMethods
|
32
|
+
end
|
33
|
+
|
34
|
+
def fire activity_type, options={}
|
35
|
+
options[:object] = self if options[:object] == nil
|
36
|
+
options[:object] = nil if options[:object] == false
|
37
|
+
|
38
|
+
Protocolist.fire activity_type, options
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Protocolist
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer 'protocolist.model_additions' do
|
4
|
+
ActiveSupport.on_load :active_record do
|
5
|
+
include ModelAdditions
|
6
|
+
end
|
7
|
+
end
|
8
|
+
initializer 'protocolist.controller_additions' do
|
9
|
+
ActiveSupport.on_load :action_controller do
|
10
|
+
include ControllerAdditions
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/protocolist.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "protocolist/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "protocolist"
|
7
|
+
s.version = Protocolist::VERSION
|
8
|
+
s.authors = ["Dmitry Yakimov"]
|
9
|
+
s.email = ["welldan97@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Activity feeds solution for Rails.}
|
12
|
+
s.description = %q{Simple activity feeds solution for Rails applications. Gives a flexible way to build activity feeds infrastructure over it. }
|
13
|
+
|
14
|
+
s.rubyforge_project = "protocolist"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec', '~> 2.8.0'
|
22
|
+
s.add_development_dependency 'guard-rspec', '~> 0.6.0'
|
23
|
+
s.add_development_dependency 'supermodel'
|
24
|
+
s.add_development_dependency 'railties', '~> 3.0'
|
25
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class User < SuperModel::Base
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
class Activity < SuperModel::Base
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
class FirestartersController
|
12
|
+
#stub before filter
|
13
|
+
def self.before_filter *args
|
14
|
+
end
|
15
|
+
|
16
|
+
include Protocolist::ControllerAdditions
|
17
|
+
def explicit_use
|
18
|
+
fire :gogogo, :object => User.new(:name => 'Lisa'), :data => '<3 <3 <3'
|
19
|
+
end
|
20
|
+
|
21
|
+
def implicit_use
|
22
|
+
@firestarter = User.new(:name => 'Marge')
|
23
|
+
fire
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Protocolist::ControllerAdditions do
|
28
|
+
before :each do
|
29
|
+
Activity.destroy_all
|
30
|
+
user = User.new(:name => 'Bill')
|
31
|
+
@controller = FirestartersController.new
|
32
|
+
|
33
|
+
@controller.stub(:current_user){user}
|
34
|
+
@controller.stub(:controller_name){'firestarters'}
|
35
|
+
@controller.stub(:action_name){'quick_and_dirty_action_stub'}
|
36
|
+
@controller.stub(:params){'les params'}
|
37
|
+
|
38
|
+
@controller.initilize_protocolist
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'direct fire method call' do
|
42
|
+
it 'saves record with object and data when called explicitly' do
|
43
|
+
@controller.explicit_use
|
44
|
+
|
45
|
+
Activity.last.subject.name.should == 'Bill'
|
46
|
+
Activity.last.activity_type.should == :gogogo
|
47
|
+
Activity.last.object.name.should == 'Lisa'
|
48
|
+
Activity.last.data.should == '<3 <3 <3'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'saves record with object and data when called implicitly' do
|
52
|
+
@controller.implicit_use
|
53
|
+
|
54
|
+
Activity.last.subject.name.should == 'Bill'
|
55
|
+
Activity.last.activity_type.should == :quick_and_dirty_action_stub
|
56
|
+
Activity.last.object.name.should == 'Marge'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'fires callback' do
|
61
|
+
it 'saves record when called with minimal options' do
|
62
|
+
FirestartersController.should_receive(:after_filter) do |callback_proc, options|
|
63
|
+
options[:only].should == :download
|
64
|
+
|
65
|
+
expect {
|
66
|
+
callback_proc.call(@controller)
|
67
|
+
}.to change{Activity.count}.by 1
|
68
|
+
Activity.last.subject.name.should == 'Bill'
|
69
|
+
Activity.last.activity_type.should == :download
|
70
|
+
Activity.last.object.should_not be
|
71
|
+
end
|
72
|
+
FirestartersController.send(:fires, :download)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'saves record when called with complex options' do
|
76
|
+
FirestartersController.should_receive(:after_filter) do |callback_proc, options|
|
77
|
+
options[:only].should == [:download_report, :download_file, :download_map]
|
78
|
+
options[:if].should == 'if condition'
|
79
|
+
|
80
|
+
expect {
|
81
|
+
callback_proc.call(@controller)
|
82
|
+
}.to change{Activity.count}.by 1
|
83
|
+
|
84
|
+
Activity.last.subject.name.should == 'Bill'
|
85
|
+
Activity.last.activity_type.should == :download
|
86
|
+
Activity.last.data.should == 'les params'
|
87
|
+
Activity.last.object.should_not be
|
88
|
+
end
|
89
|
+
|
90
|
+
FirestartersController.send(:fires, :download,
|
91
|
+
:only => [:download_report, :download_file, :download_map],
|
92
|
+
:data => lambda{|c| c.params },
|
93
|
+
:if => 'if condition')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class User < SuperModel::Base
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
class Activity < SuperModel::Base
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
class Firestarter < SuperModel::Base
|
12
|
+
include Protocolist::ModelAdditions
|
13
|
+
|
14
|
+
def delete
|
15
|
+
fire :delete, :object => false
|
16
|
+
end
|
17
|
+
|
18
|
+
def myself
|
19
|
+
fire :myself
|
20
|
+
end
|
21
|
+
|
22
|
+
def love_letter_for_mary
|
23
|
+
user = User.create(:name => 'Mary')
|
24
|
+
fire :love_letter, :object => user, :data => '<3 <3 <3'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class SimpleFirestarter < SuperModel::Base
|
29
|
+
include Protocolist::ModelAdditions
|
30
|
+
|
31
|
+
fires :create
|
32
|
+
end
|
33
|
+
|
34
|
+
class ConditionalFirestarter < SuperModel::Base
|
35
|
+
include Protocolist::ModelAdditions
|
36
|
+
|
37
|
+
fires :i_will_be_saved, :on => :create, :if => :return_true_please
|
38
|
+
fires :and_i_won_t, :on => :create, :if => :return_false_please
|
39
|
+
|
40
|
+
def return_false_please
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def return_true_please
|
45
|
+
true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class ComplexFirestarter < SuperModel::Base
|
50
|
+
include Protocolist::ModelAdditions
|
51
|
+
|
52
|
+
fires :yohoho, :on =>[:create, :destroy], :object => false, :data => :hi
|
53
|
+
|
54
|
+
def hi
|
55
|
+
'Hi!'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Protocolist::ModelAdditions do
|
60
|
+
before :each do
|
61
|
+
Activity.destroy_all
|
62
|
+
@subject = User.new(:name => 'Bill')
|
63
|
+
Protocolist.subject = @subject
|
64
|
+
Protocolist.activity_class = Activity
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'direct fire method call' do
|
68
|
+
before :each do
|
69
|
+
@firestarter = Firestarter.new
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'saves record with object and data' do
|
73
|
+
expect {
|
74
|
+
@firestarter.love_letter_for_mary
|
75
|
+
}.to change{Activity.count}.by 1
|
76
|
+
Activity.last.subject.name.should == 'Bill'
|
77
|
+
Activity.last.activity_type.should == :love_letter
|
78
|
+
Activity.last.object.name.should == 'Mary'
|
79
|
+
Activity.last.data.should == '<3 <3 <3'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'saves record with self as object if object is not set' do
|
83
|
+
expect {
|
84
|
+
@firestarter.myself
|
85
|
+
}.to change{Activity.count}.by 1
|
86
|
+
Activity.last.subject.name.should == 'Bill'
|
87
|
+
Activity.last.activity_type.should == :myself
|
88
|
+
Activity.last.object.should == @firestarter
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'saves record without object if object set to false' do
|
92
|
+
expect {
|
93
|
+
@firestarter.delete
|
94
|
+
}.to change{Activity.count}.by 1
|
95
|
+
Activity.last.subject.name.should == 'Bill'
|
96
|
+
Activity.last.activity_type.should == :delete
|
97
|
+
Activity.last.object.should be_false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'fires callback' do
|
102
|
+
it 'saves record when called with minimal options' do
|
103
|
+
expect {
|
104
|
+
SimpleFirestarter.create(:name => 'Ted')
|
105
|
+
}.to change{Activity.count}.by 1
|
106
|
+
Activity.last.subject.name.should == 'Bill'
|
107
|
+
Activity.last.activity_type.should == :create
|
108
|
+
Activity.last.object.name.should == 'Ted'
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'saves record when called with complex options' do
|
112
|
+
|
113
|
+
#first create record
|
114
|
+
|
115
|
+
expect {
|
116
|
+
ComplexFirestarter.create(:name => 'Ted')
|
117
|
+
}.to change{Activity.count}.by 1
|
118
|
+
Activity.last.subject.name.should == 'Bill'
|
119
|
+
Activity.last.activity_type.should == :yohoho
|
120
|
+
Activity.last.object.should_not be
|
121
|
+
Activity.last.data.should == 'Hi!'
|
122
|
+
|
123
|
+
#then destroy record
|
124
|
+
|
125
|
+
expect {
|
126
|
+
ComplexFirestarter.last.destroy
|
127
|
+
}.to change{Activity.count}.by 1
|
128
|
+
Activity.last.subject.name.should == 'Bill'
|
129
|
+
Activity.last.activity_type.should == :yohoho
|
130
|
+
Activity.last.object.should_not be
|
131
|
+
Activity.last.data.should == 'Hi!'
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'saves checks conditions' do
|
135
|
+
expect {
|
136
|
+
ConditionalFirestarter.create(:name => 'Ted')
|
137
|
+
}.to change{Activity.count}.by 1
|
138
|
+
Activity.last.activity_type.should == :i_will_be_saved
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class User < SuperModel::Base
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
class Activity < SuperModel::Base
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Protocolist do
|
12
|
+
before :each do
|
13
|
+
Activity.destroy_all
|
14
|
+
@subject = User.new(:name => 'Bill')
|
15
|
+
Protocolist.subject = @subject
|
16
|
+
Protocolist.activity_class = Activity
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should silently skip saving if subject is falsy' do
|
20
|
+
Protocolist.subject = nil
|
21
|
+
expect {Protocolist.fire :alarm}.not_to change{Activity.count}
|
22
|
+
expect {Protocolist.fire :alarm}.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should silently skip saving if activity_class is falsy' do
|
26
|
+
Protocolist.activity_class = nil
|
27
|
+
expect {Protocolist.fire :alarm}.not_to change{Activity.count}
|
28
|
+
expect {Protocolist.fire :alarm}.not_to raise_error
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should save a simple record' do
|
32
|
+
expect {Protocolist.fire :alarm}.to change{Activity.count}.by 1
|
33
|
+
|
34
|
+
Activity.last.subject.should == @subject
|
35
|
+
Activity.last.activity_type.should == :alarm
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should save a complex record' do
|
39
|
+
another_subject = User.new(:name => 'Bob')
|
40
|
+
object = User.new(:name => 'Mary')
|
41
|
+
|
42
|
+
expect {
|
43
|
+
Protocolist.fire :alarm,
|
44
|
+
:subject => another_subject,
|
45
|
+
:object => object,
|
46
|
+
:data => {:some_attr => :some_data}
|
47
|
+
}.to change{Activity.count}.by 1
|
48
|
+
|
49
|
+
Activity.last.subject.name.should == 'Bob'
|
50
|
+
Activity.last.activity_type.should == :alarm
|
51
|
+
Activity.last.object.name.should == 'Mary'
|
52
|
+
Activity.last.data[:some_attr].should == :some_data
|
53
|
+
end
|
54
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: protocolist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0.beta
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dmitry Yakimov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &87740840 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.8.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *87740840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: guard-rspec
|
27
|
+
requirement: &87740470 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.6.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *87740470
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: supermodel
|
38
|
+
requirement: &87740210 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *87740210
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: railties
|
49
|
+
requirement: &87739830 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *87739830
|
58
|
+
description: ! 'Simple activity feeds solution for Rails applications. Gives a flexible
|
59
|
+
way to build activity feeds infrastructure over it. '
|
60
|
+
email:
|
61
|
+
- welldan97@gmail.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- .rspec
|
68
|
+
- Gemfile
|
69
|
+
- Guardfile
|
70
|
+
- LICENSE
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- lib/generators/protocolist/install/USAGE
|
74
|
+
- lib/generators/protocolist/install/install_generator.rb
|
75
|
+
- lib/generators/protocolist/install/templates/migration.rb
|
76
|
+
- lib/protocolist.rb
|
77
|
+
- lib/protocolist/controller_additions.rb
|
78
|
+
- lib/protocolist/model_additions.rb
|
79
|
+
- lib/protocolist/railtie.rb
|
80
|
+
- lib/protocolist/version.rb
|
81
|
+
- protocolist.gemspec
|
82
|
+
- spec/protocolist/controller_additions_spec.rb
|
83
|
+
- spec/protocolist/model_additions_spec.rb
|
84
|
+
- spec/protocolist_spec.rb
|
85
|
+
- spec/spec_helper.rb
|
86
|
+
homepage: ''
|
87
|
+
licenses: []
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ! '>'
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.3.1
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project: protocolist
|
106
|
+
rubygems_version: 1.8.10
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: Activity feeds solution for Rails.
|
110
|
+
test_files: []
|