protocolist 0.8.0.beta
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 +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: []
|