protocolist 0.9.0.beta → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Guardfile +1 -1
- data/README.md +13 -15
- data/Rakefile +1 -1
- data/lib/generators/protocolist/install/install_generator.rb +65 -10
- data/lib/generators/protocolist/install/templates/migration.rb +5 -4
- data/lib/protocolist.rb +11 -20
- data/lib/protocolist/controller_additions.rb +32 -37
- data/lib/protocolist/controller_additions/initializer.rb +16 -0
- data/lib/protocolist/model_additions.rb +30 -28
- data/lib/protocolist/railtie.rb +9 -2
- data/lib/protocolist/util/data_proc.rb +23 -0
- data/lib/protocolist/version.rb +1 -1
- data/protocolist.gemspec +6 -3
- data/spec/protocolist/controller_additions_spec.rb +42 -45
- data/spec/protocolist/model_additions_spec.rb +66 -67
- data/spec/protocolist_spec.rb +29 -24
- data/spec/spec_helper.rb +4 -1
- metadata +90 -21
data/.gitignore
CHANGED
data/Guardfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'guard/guard'
|
2
2
|
|
3
|
-
guard :rspec, :
|
3
|
+
guard :rspec, all_on_start: false, all_after_pass: false, cli: '--fail-fast --format doc' do
|
4
4
|
watch(%r{^spec/.+_spec\.rb$})
|
5
5
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
6
6
|
watch('spec/spec_helper.rb') { "spec" }
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#Protocolist
|
1
|
+
#Protocolist
|
2
|
+
[![Build Status](https://secure.travis-ci.org/welldan97/protocolist.png?branch=master)](http://travis-ci.org/welldan97/protocolist) [![Dependency Status](https://gemnasium.com/welldan97/protocolist.png)](https://gemnasium.com/welldan97/protocolist) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/welldan97/protocolist)
|
2
3
|
|
3
4
|
Simple activity feeds solution for Rails applications. Gives a flexible way to build activity feeds infrastructure over it.
|
4
5
|
|
@@ -27,7 +28,7 @@ Getting started
|
|
27
28
|
---------------
|
28
29
|
|
29
30
|
Activity model has four attributes: actor("who did it"), activity_type("what
|
30
|
-
they did"), target("what they did it to") and data(additional information).
|
31
|
+
they did"), target("what they did it to") and data(additional information). Actor will be
|
31
32
|
set as current user by default.
|
32
33
|
|
33
34
|
Protocolist expects you to have `current_user` method in a
|
@@ -51,12 +52,12 @@ Activity with current user set as actor, `:create` as type,
|
|
51
52
|
The more convenient usage:
|
52
53
|
|
53
54
|
```ruby
|
54
|
-
fires :edit,
|
55
|
-
:
|
56
|
-
:
|
55
|
+
fires :edit, on: :update,
|
56
|
+
data: :changes,
|
57
|
+
if: 'changes.any?'
|
57
58
|
```
|
58
59
|
|
59
|
-
The event type will be `edit`. A proc, symbol
|
60
|
+
The event type will be `edit`. A proc, symbol and a string for data
|
60
61
|
option represent a method, else types will be stored as is.
|
61
62
|
|
62
63
|
The `unless` option also can be passed.
|
@@ -64,7 +65,7 @@ The `unless` option also can be passed.
|
|
64
65
|
The `on` option can be an array:
|
65
66
|
|
66
67
|
```ruby
|
67
|
-
fires :comment_activity, :
|
68
|
+
fires :comment_activity, on: [:create, :update, :destroy]
|
68
69
|
```
|
69
70
|
|
70
71
|
The most flexible way is to use `fire` method:
|
@@ -72,7 +73,7 @@ The most flexible way is to use `fire` method:
|
|
72
73
|
```ruby
|
73
74
|
def destroy_projects
|
74
75
|
self.projects.destroy_all
|
75
|
-
fire :destroy_all, :
|
76
|
+
fire :destroy_all, target: false, data: { company_id: company_id }
|
76
77
|
end
|
77
78
|
```
|
78
79
|
|
@@ -92,9 +93,9 @@ which will strike after download action.
|
|
92
93
|
The customized one:
|
93
94
|
|
94
95
|
```ruby
|
95
|
-
fires :download, :
|
96
|
-
:
|
97
|
-
:
|
96
|
+
fires :download, only: [:download_report, :download_file, :download_map],
|
97
|
+
data: ->(c) { c.params[:city] },
|
98
|
+
if: ->(c) { c.response.status == 200 }
|
98
99
|
```
|
99
100
|
|
100
101
|
The `fire` method can be used same way as in models, but also if type is not
|
@@ -111,7 +112,7 @@ is the same as
|
|
111
112
|
```ruby
|
112
113
|
def show
|
113
114
|
@article = Article.find(params[:id])
|
114
|
-
fire :show, :
|
115
|
+
fire :show, target: @article
|
115
116
|
end
|
116
117
|
```
|
117
118
|
|
@@ -130,6 +131,3 @@ Protocolist was inspired by
|
|
130
131
|
[timeline_fu](https://github.com/jamesgolick/timeline_fu). I used it,
|
131
132
|
but its functionality wasn't enough for me, so I made my own with
|
132
133
|
blackjack and stewardesses.
|
133
|
-
|
134
|
-
|
135
|
-
|
data/Rakefile
CHANGED
@@ -7,23 +7,78 @@ module Protocolist
|
|
7
7
|
|
8
8
|
source_root File.expand_path("../templates", __FILE__)
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
model_content = <<CONTENT
|
14
|
-
attr_accessible :activity_type, :target, :actor, :data
|
15
|
-
belongs_to :target, :polymorphic => true
|
16
|
-
belongs_to :actor, :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'))
|
10
|
+
class_option 'model-orm', type: :string, default: 'active_record', aliases: '-o', desc: 'Model ORM (ActiveRecord or MongoId)'
|
11
|
+
class_option 'model-classname', type: :string, default: 'Activity', aliases: '-c'
|
12
|
+
class_option 'model-filename', type: :string, default: 'app/models/activity.rb', aliases: '-f'
|
20
13
|
|
21
14
|
|
15
|
+
def generate_activity_model
|
16
|
+
if model_orm == 'mongoid' && defined?(Mongoid)
|
17
|
+
generate_mongoid_activity_model
|
18
|
+
elsif model_orm == 'active_record' && defined?(ActiveRecord)
|
19
|
+
generate_active_record_activity_model
|
20
|
+
end
|
22
21
|
end
|
23
22
|
|
24
23
|
def self.next_migration_number(dirname) #:nodoc:
|
25
24
|
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
26
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_mongoid_activity_model
|
30
|
+
content = <<-CONTENT.gsub(/^ +/, ' ')
|
31
|
+
|
32
|
+
belongs_to :actor, polymorphic: true
|
33
|
+
belongs_to :target, polymorphic: true
|
34
|
+
|
35
|
+
field :activity_type, type: String
|
36
|
+
field :data, type: Hash
|
37
|
+
CONTENT
|
38
|
+
|
39
|
+
|
40
|
+
invoke "mongoid:model", [model_classname]
|
41
|
+
|
42
|
+
if model_exists?
|
43
|
+
inject_into_file(model_filename, content, after: "include Mongoid::Document\n")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_active_record_activity_model
|
48
|
+
content = <<-CONTENT.gsub(/^ +/, ' ')
|
49
|
+
attr_accessible :activity_type, :target, :actor, :data
|
50
|
+
|
51
|
+
belongs_to :target, polymorphic: true
|
52
|
+
belongs_to :actor, polymorphic: true
|
53
|
+
|
54
|
+
serialize :data
|
55
|
+
CONTENT
|
56
|
+
|
57
|
+
|
58
|
+
migration_template "migration.rb", "db/migrate/create_activities"
|
59
|
+
invoke "active_record:model", [model_classname], migration: false
|
60
|
+
|
61
|
+
if model_exists?
|
62
|
+
gsub_file model_filename, / +# attr_accessible :title, :body\n/, ''
|
63
|
+
inject_into_class(model_filename, model_classname, content)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def model_exists?
|
68
|
+
File.exists?(File.join(destination_root, model_filename))
|
69
|
+
end
|
70
|
+
|
71
|
+
def model_filename
|
72
|
+
options['model-filename']
|
73
|
+
end
|
74
|
+
|
75
|
+
def model_classname
|
76
|
+
options['model-classname']
|
77
|
+
end
|
78
|
+
|
79
|
+
def model_orm
|
80
|
+
options['model-orm']
|
81
|
+
end
|
27
82
|
end
|
28
83
|
end
|
29
84
|
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
class CreateActivities < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table :activities do |t|
|
4
|
-
t.references :actor,
|
5
|
-
t.references :target, :
|
4
|
+
t.references :actor, polymorphic: true
|
5
|
+
t.references :target, polymorphic: true
|
6
|
+
|
6
7
|
t.string :activity_type
|
7
8
|
t.text :data
|
8
9
|
|
9
10
|
t.timestamps
|
10
11
|
end
|
11
|
-
add_index :activities, :actor_id
|
12
|
-
add_index :activities, :target_id
|
12
|
+
add_index :activities, [:actor_id, :actor_type]
|
13
|
+
add_index :activities, [:target_id, :target_type]
|
13
14
|
end
|
14
15
|
end
|
data/lib/protocolist.rb
CHANGED
@@ -1,29 +1,20 @@
|
|
1
|
-
require
|
2
|
-
require "protocolist/model_additions"
|
3
|
-
require "protocolist/controller_additions"
|
4
|
-
require "protocolist/railtie" if defined? Rails
|
1
|
+
require 'active_support'
|
5
2
|
|
3
|
+
require 'protocolist/version'
|
4
|
+
require 'protocolist/model_additions'
|
5
|
+
require 'protocolist/controller_additions'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
def self.fire activity_type, options={}
|
10
|
-
options = {:actor => @actor, :activity_type => activity_type}.merge options
|
11
|
-
@activity_class.create options if options[:actor] && @activity_class
|
12
|
-
end
|
7
|
+
require 'protocolist/railtie' if defined? Rails
|
13
8
|
|
14
|
-
def self.actor
|
15
|
-
@actor
|
16
|
-
end
|
17
9
|
|
18
|
-
|
19
|
-
@actor = actor
|
20
|
-
end
|
10
|
+
module Protocolist
|
21
11
|
|
22
|
-
def self.
|
23
|
-
|
12
|
+
def self.fire(activity_type, options = {})
|
13
|
+
options = options.reverse_merge(actor:@actor, activity_type: activity_type)
|
14
|
+
@activity_class.try(:create, options) if options[:actor]
|
24
15
|
end
|
25
16
|
|
26
|
-
|
27
|
-
|
17
|
+
class << self
|
18
|
+
attr_accessor :actor, :activity_class
|
28
19
|
end
|
29
20
|
end
|
@@ -1,50 +1,45 @@
|
|
1
|
+
require 'protocolist/controller_additions/initializer'
|
2
|
+
require 'protocolist/util/data_proc'
|
3
|
+
|
1
4
|
module Protocolist
|
2
5
|
module ControllerAdditions
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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 }
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include Initializer
|
8
|
+
include Util::DataProc
|
9
|
+
|
10
|
+
def fire(activity_type = nil, options = {})
|
11
|
+
target = case options[:target]
|
12
|
+
when nil
|
13
|
+
instance_variable_get("@#{controller_name.singularize}")
|
14
|
+
when false
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
options[:target]
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
}
|
20
|
+
activity_type ||= action_name.to_sym
|
21
|
+
options = options.merge(target: target)
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
Protocolist.fire(activity_type, options)
|
24
|
+
end
|
26
25
|
|
26
|
+
module ClassMethods
|
27
|
+
def fires(activity_type, options = {})
|
28
|
+
options = options.merge(only: activity_type) unless options[:only] || options[:except]
|
27
29
|
|
28
|
-
|
29
|
-
base.send(:before_filter, :initilize_protocolist)
|
30
|
-
end
|
31
|
-
end
|
30
|
+
data_proc = extract_data_proc(options[:data])
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
end
|
32
|
+
options_for_callback = options.slice(:if, :unless, :only, :except)
|
33
|
+
options_for_fire = options.except(:if, :unless, :only, :except)
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
options[:target] = nil if options[:target] == false
|
40
|
-
activity_type ||= action_name.to_sym
|
35
|
+
callback_proc = ->(controller; options) do
|
36
|
+
options = options_for_fire.merge(data: data_proc.call(controller))
|
41
37
|
|
42
|
-
|
43
|
-
|
38
|
+
controller.fire(activity_type, options)
|
39
|
+
end
|
44
40
|
|
45
|
-
|
46
|
-
|
47
|
-
Protocolist.activity_class = Activity
|
41
|
+
send(:after_filter, callback_proc, options_for_callback)
|
42
|
+
end
|
48
43
|
end
|
49
44
|
end
|
50
45
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Protocolist
|
2
|
+
module ControllerAdditions
|
3
|
+
module Initializer
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before_filter :initialize_protocolist
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize_protocolist
|
11
|
+
Protocolist.actor = current_user
|
12
|
+
Protocolist.activity_class = Activity
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,41 +1,43 @@
|
|
1
|
+
require 'protocolist/util/data_proc'
|
2
|
+
|
1
3
|
module Protocolist
|
2
4
|
module ModelAdditions
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Util::DataProc
|
7
|
+
|
8
|
+
def fire(activity_type, options = {})
|
9
|
+
target = case options[:target]
|
10
|
+
when nil
|
11
|
+
self
|
12
|
+
when false
|
13
|
+
nil
|
14
|
+
else
|
15
|
+
options[:target]
|
16
|
+
end
|
17
|
+
|
18
|
+
options = options.merge(target: target)
|
19
|
+
|
20
|
+
Protocolist.fire(activity_type, options)
|
21
|
+
end
|
7
22
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
else
|
13
|
-
lambda{|record| options[:data] }
|
14
|
-
end
|
23
|
+
module ClassMethods
|
24
|
+
def fires(activity_type, options = {})
|
25
|
+
fires_on = [*options[:on] || activity_type]
|
26
|
+
data_proc = extract_data_proc(options[:data])
|
15
27
|
|
16
|
-
options_for_callback = options.
|
28
|
+
options_for_callback = options.slice(:if, :unless)
|
29
|
+
options_for_fire = options.except(:if, :unless, :on)
|
17
30
|
|
18
|
-
|
31
|
+
callback_proc = ->(record; options) do
|
32
|
+
options = options_for_fire.merge(data: data_proc.call(record))
|
19
33
|
|
20
|
-
|
21
|
-
|
22
|
-
}
|
34
|
+
record.fire(activity_type, options)
|
35
|
+
end
|
23
36
|
|
24
37
|
fires_on.each do |on|
|
25
|
-
send("after_#{on
|
38
|
+
send("after_#{on}", callback_proc, options_for_callback)
|
26
39
|
end
|
27
40
|
end
|
28
41
|
end
|
29
|
-
|
30
|
-
def self.included base
|
31
|
-
base.extend ClassMethods
|
32
|
-
end
|
33
|
-
|
34
|
-
def fire activity_type, options={}
|
35
|
-
options[:target] = self if options[:target] == nil
|
36
|
-
options[:target] = nil if options[:target] == false
|
37
|
-
|
38
|
-
Protocolist.fire activity_type, options
|
39
|
-
end
|
40
42
|
end
|
41
43
|
end
|
data/lib/protocolist/railtie.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
module Protocolist
|
2
2
|
class Railtie < Rails::Railtie
|
3
3
|
initializer 'protocolist.model_additions' do
|
4
|
-
ActiveSupport.on_load
|
4
|
+
ActiveSupport.on_load(:active_record) do
|
5
5
|
include ModelAdditions
|
6
6
|
end
|
7
|
+
if defined?(Mongoid)
|
8
|
+
Mongoid::Document.module_eval do
|
9
|
+
included do
|
10
|
+
include ModelAdditions
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
7
14
|
end
|
8
15
|
initializer 'protocolist.controller_additions' do
|
9
|
-
ActiveSupport.on_load
|
16
|
+
ActiveSupport.on_load(:action_controller) do
|
10
17
|
include ControllerAdditions
|
11
18
|
end
|
12
19
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Protocolist
|
2
|
+
module Util
|
3
|
+
module DataProc
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
private
|
8
|
+
|
9
|
+
def extract_data_proc(data)
|
10
|
+
if data.respond_to?(:call)
|
11
|
+
->(o) { data.call(o) }
|
12
|
+
elsif data.is_a?(Symbol)
|
13
|
+
->(o) { o.send(data) }
|
14
|
+
elsif data.is_a?(String)
|
15
|
+
->(o) { o.instance_eval "(#{data})" }
|
16
|
+
else
|
17
|
+
->(_) { data }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/protocolist/version.rb
CHANGED
data/protocolist.gemspec
CHANGED
@@ -18,9 +18,12 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
+
s.add_dependency 'activesupport', '~> 3.0'
|
22
|
+
|
21
23
|
s.add_development_dependency 'rake'
|
22
|
-
s.add_development_dependency 'rspec', '~> 2.
|
23
|
-
s.add_development_dependency 'guard-rspec', '~>
|
24
|
-
s.add_development_dependency 'supermodel'
|
24
|
+
s.add_development_dependency 'rspec', '~> 2.12.0'
|
25
|
+
s.add_development_dependency 'guard-rspec', '~> 2.3.0'
|
26
|
+
s.add_development_dependency 'supermodel', '~> 0.1.6'
|
27
|
+
s.add_development_dependency 'psych', '~> 1.3.0' # fixes ' superclass mismatch for class Mark ' error
|
25
28
|
s.add_development_dependency 'railties', '~> 3.0'
|
26
29
|
end
|
@@ -1,59 +1,57 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
class User < SuperModel::Base
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
class Activity < SuperModel::Base
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
3
|
class FirestartersController
|
12
4
|
#stub before filter
|
13
5
|
def self.before_filter *args
|
14
6
|
end
|
15
7
|
|
16
8
|
include Protocolist::ControllerAdditions
|
17
|
-
|
18
|
-
|
9
|
+
|
10
|
+
def explicit_use(target, data)
|
11
|
+
fire :gogogo, target: target, data: data
|
19
12
|
end
|
20
13
|
|
21
|
-
def implicit_use
|
22
|
-
@firestarter =
|
14
|
+
def implicit_use(target)
|
15
|
+
@firestarter = target
|
23
16
|
fire
|
24
17
|
end
|
25
18
|
end
|
26
19
|
|
27
20
|
describe Protocolist::ControllerAdditions do
|
21
|
+
let(:controller) { FirestartersController.new }
|
22
|
+
let(:actor) { User.new(name: 'Bill') }
|
23
|
+
let(:lisa) { User.new(name: 'Lisa') }
|
24
|
+
let(:mary) { User.new(name: 'Mary') }
|
25
|
+
|
28
26
|
before :each do
|
29
27
|
Activity.destroy_all
|
30
|
-
user = User.new(:name => 'Bill')
|
31
|
-
@controller = FirestartersController.new
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
controller.stub(:current_user).and_return(actor)
|
30
|
+
controller.stub(:controller_name).and_return('firestarters')
|
31
|
+
controller.stub(:action_name).and_return('quick_and_dirty_action_stub')
|
32
|
+
controller.stub(:params).and_return('les params')
|
37
33
|
|
38
|
-
|
34
|
+
controller.initialize_protocolist
|
39
35
|
end
|
40
36
|
|
41
37
|
describe 'direct fire method call' do
|
42
38
|
it 'saves record with target and data when called explicitly' do
|
43
|
-
|
39
|
+
controller.explicit_use(lisa, '<3 <3 <3')
|
44
40
|
|
45
|
-
Activity.last
|
46
|
-
|
47
|
-
|
48
|
-
|
41
|
+
activity = Activity.last
|
42
|
+
activity.actor.should == actor
|
43
|
+
activity.activity_type.should == :gogogo
|
44
|
+
activity.target.should == lisa
|
45
|
+
activity.data.should == '<3 <3 <3'
|
49
46
|
end
|
50
47
|
|
51
48
|
it 'saves record with target and data when called implicitly' do
|
52
|
-
|
49
|
+
controller.implicit_use(mary)
|
53
50
|
|
54
|
-
Activity.last
|
55
|
-
|
56
|
-
|
51
|
+
activity = Activity.last
|
52
|
+
activity.actor.should == actor
|
53
|
+
activity.activity_type.should == :quick_and_dirty_action_stub
|
54
|
+
activity.target.should == mary
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
@@ -61,36 +59,35 @@ describe Protocolist::ControllerAdditions do
|
|
61
59
|
it 'saves record when called with minimal options' do
|
62
60
|
FirestartersController.should_receive(:after_filter) do |callback_proc, options|
|
63
61
|
options[:only].should == :download
|
62
|
+
expect { callback_proc.call(controller) }.to change { Activity.count }.by(1)
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
Activity.last.activity_type.should == :download
|
70
|
-
Activity.last.target.should_not be
|
64
|
+
activity = Activity.last
|
65
|
+
activity.actor.should == actor
|
66
|
+
activity.activity_type.should == :download
|
67
|
+
activity.target.should_not be
|
71
68
|
end
|
69
|
+
|
72
70
|
FirestartersController.send(:fires, :download)
|
73
71
|
end
|
74
72
|
|
75
73
|
it 'saves record when called with complex options' do
|
76
74
|
FirestartersController.should_receive(:after_filter) do |callback_proc, options|
|
77
75
|
options[:only].should == [:download_report, :download_file, :download_map]
|
78
|
-
options[:if].should
|
76
|
+
options[:if].should == 'if condition'
|
79
77
|
|
80
|
-
expect {
|
81
|
-
callback_proc.call(@controller)
|
82
|
-
}.to change{Activity.count}.by 1
|
78
|
+
expect { callback_proc.call(controller) }.to change { Activity.count }.by(1)
|
83
79
|
|
84
|
-
Activity.last
|
85
|
-
|
86
|
-
|
87
|
-
|
80
|
+
activity = Activity.last
|
81
|
+
activity.actor.should == actor
|
82
|
+
activity.activity_type.should == :download
|
83
|
+
activity.data.should == 'les params'
|
84
|
+
activity.target.should_not be
|
88
85
|
end
|
89
86
|
|
90
87
|
FirestartersController.send(:fires, :download,
|
91
|
-
|
92
|
-
|
93
|
-
|
88
|
+
only: [:download_report, :download_file, :download_map],
|
89
|
+
data: ->(c) { c.params }, if: 'if condition'
|
90
|
+
)
|
94
91
|
end
|
95
92
|
end
|
96
93
|
end
|
@@ -1,41 +1,31 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
class User < SuperModel::Base
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
class Activity < SuperModel::Base
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
3
|
class Firestarter < SuperModel::Base
|
12
4
|
include Protocolist::ModelAdditions
|
13
5
|
|
14
6
|
def delete
|
15
|
-
fire :delete, :
|
7
|
+
fire :delete, target: false
|
16
8
|
end
|
17
9
|
|
18
10
|
def myself
|
19
11
|
fire :myself
|
20
12
|
end
|
21
13
|
|
22
|
-
def love_letter_for_mary
|
23
|
-
|
24
|
-
fire :love_letter, :target => user, :data => '<3 <3 <3'
|
14
|
+
def love_letter_for_mary(target, data)
|
15
|
+
fire :love_letter, target: target, data: data
|
25
16
|
end
|
26
17
|
end
|
27
18
|
|
28
19
|
class SimpleFirestarter < SuperModel::Base
|
29
20
|
include Protocolist::ModelAdditions
|
30
|
-
|
31
21
|
fires :create
|
32
22
|
end
|
33
23
|
|
34
24
|
class ConditionalFirestarter < SuperModel::Base
|
35
25
|
include Protocolist::ModelAdditions
|
36
26
|
|
37
|
-
fires :i_will_be_saved, :
|
38
|
-
fires :and_i_won_t,
|
27
|
+
fires :i_will_be_saved, on: :create, if: :return_true_please
|
28
|
+
fires :and_i_won_t, on: :create, if: :return_false_please
|
39
29
|
|
40
30
|
def return_false_please
|
41
31
|
false
|
@@ -49,7 +39,8 @@ end
|
|
49
39
|
class ComplexFirestarter < SuperModel::Base
|
50
40
|
include Protocolist::ModelAdditions
|
51
41
|
|
52
|
-
fires :yohoho, :
|
42
|
+
fires :yohoho, on: [:create, :destroy], target: false, data: :hi
|
43
|
+
fires :yohoho, on: :update, data: 'name * 2'
|
53
44
|
|
54
45
|
def hi
|
55
46
|
'Hi!'
|
@@ -57,87 +48,95 @@ class ComplexFirestarter < SuperModel::Base
|
|
57
48
|
end
|
58
49
|
|
59
50
|
describe Protocolist::ModelAdditions do
|
60
|
-
|
51
|
+
let(:actor) { User.new(name: 'Bill') }
|
52
|
+
let(:mary) { User.new(name: 'Mary') }
|
53
|
+
|
54
|
+
before do
|
61
55
|
Activity.destroy_all
|
62
|
-
|
63
|
-
Protocolist.actor =
|
56
|
+
|
57
|
+
Protocolist.actor = actor
|
64
58
|
Protocolist.activity_class = Activity
|
65
59
|
end
|
66
60
|
|
67
61
|
describe 'direct fire method call' do
|
68
|
-
|
69
|
-
@firestarter = Firestarter.new
|
70
|
-
end
|
62
|
+
let(:firestarter) { Firestarter.new }
|
71
63
|
|
72
64
|
it 'saves record with target and data' do
|
73
|
-
expect {
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
65
|
+
expect { firestarter.love_letter_for_mary(mary, '<3 <3 <3') }.to change { Activity.count }.by(1)
|
66
|
+
|
67
|
+
activity = Activity.last
|
68
|
+
activity.actor.should == actor
|
69
|
+
activity.activity_type.should == :love_letter
|
70
|
+
activity.target.should == mary
|
71
|
+
activity.data.should == '<3 <3 <3'
|
80
72
|
end
|
81
73
|
|
82
74
|
it 'saves record with self as target if target is not set' do
|
83
|
-
expect {
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
75
|
+
expect { firestarter.myself }.to change { Activity.count }.by(1)
|
76
|
+
|
77
|
+
activity = Activity.last
|
78
|
+
activity.actor.should == actor
|
79
|
+
activity.activity_type.should == :myself
|
80
|
+
activity.target.should == firestarter
|
89
81
|
end
|
90
82
|
|
91
83
|
it 'saves record without target if target set to false' do
|
92
|
-
expect {
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
84
|
+
expect { firestarter.delete }.to change { Activity.count }.by(1)
|
85
|
+
|
86
|
+
activity = Activity.last
|
87
|
+
activity.actor.should == actor
|
88
|
+
activity.activity_type.should == :delete
|
89
|
+
activity.target.should be_false
|
98
90
|
end
|
99
91
|
end
|
100
92
|
|
101
93
|
describe 'fires callback' do
|
102
94
|
it 'saves record when called with minimal options' do
|
103
|
-
expect {
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
95
|
+
expect { SimpleFirestarter.create(name: 'Ted') }.to change { Activity.count }.by(1)
|
96
|
+
|
97
|
+
activity = Activity.last
|
98
|
+
activity.actor.should == actor
|
99
|
+
activity.activity_type.should == :create
|
100
|
+
activity.target.name.should == 'Ted'
|
109
101
|
end
|
110
102
|
|
111
103
|
it 'saves record when called with complex options' do
|
112
104
|
|
113
105
|
#first create record
|
114
106
|
|
115
|
-
expect {
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
107
|
+
expect { ComplexFirestarter.create(name: 'Ted') }.to change { Activity.count }.by(1)
|
108
|
+
|
109
|
+
activity = Activity.last
|
110
|
+
activity.actor.should == actor
|
111
|
+
activity.activity_type.should == :yohoho
|
112
|
+
activity.target.should_not be
|
113
|
+
activity.data.should == 'Hi!'
|
122
114
|
|
123
115
|
#then destroy record
|
124
116
|
|
125
|
-
expect {
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
117
|
+
expect { ComplexFirestarter.last.destroy }.to change { Activity.count }.by(1)
|
118
|
+
|
119
|
+
activity = Activity.last
|
120
|
+
activity.actor.should == actor
|
121
|
+
activity.activity_type.should == :yohoho
|
122
|
+
activity.target.should_not be
|
123
|
+
activity.data.should == 'Hi!'
|
132
124
|
end
|
133
125
|
|
134
|
-
it 'saves
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
Activity.last
|
126
|
+
it 'saves record with string data attribute parsed' do
|
127
|
+
ComplexFirestarter.create(name: 'Ted')
|
128
|
+
ComplexFirestarter.last.update_attributes name: 'Bob'
|
129
|
+
|
130
|
+
activity = Activity.last
|
131
|
+
activity.data.should == 'BobBob'
|
139
132
|
end
|
140
|
-
end
|
141
133
|
|
134
|
+
it 'saves checks conditions' do
|
135
|
+
expect { ConditionalFirestarter.create(name: 'Ted') }.to change { Activity.count }.by(1)
|
142
136
|
|
137
|
+
activity = Activity.last
|
138
|
+
activity.actor.should == actor
|
139
|
+
activity.activity_type.should == :i_will_be_saved
|
140
|
+
end
|
141
|
+
end
|
143
142
|
end
|
data/spec/protocolist_spec.rb
CHANGED
@@ -9,46 +9,51 @@ class Activity < SuperModel::Base
|
|
9
9
|
end
|
10
10
|
|
11
11
|
describe Protocolist do
|
12
|
-
|
12
|
+
let(:actor) { User.new(name: 'Bill') }
|
13
|
+
let(:another_actor) { User.new(name: 'Bob') }
|
14
|
+
let(:target) { User.new(name: 'Mary') }
|
15
|
+
|
16
|
+
before do
|
13
17
|
Activity.destroy_all
|
14
|
-
|
15
|
-
Protocolist.actor =
|
18
|
+
|
19
|
+
Protocolist.actor = actor
|
16
20
|
Protocolist.activity_class = Activity
|
17
21
|
end
|
18
22
|
|
19
23
|
it 'should silently skip saving if actor is falsy' do
|
20
24
|
Protocolist.actor = nil
|
21
|
-
|
22
|
-
expect {Protocolist.fire
|
25
|
+
|
26
|
+
expect { Protocolist.fire(:alarm) }.not_to change { Activity.count }
|
27
|
+
expect { Protocolist.fire(:alarm) }.not_to raise_error
|
23
28
|
end
|
24
29
|
|
25
30
|
it 'should silently skip saving if activity_class is falsy' do
|
26
31
|
Protocolist.activity_class = nil
|
27
|
-
|
28
|
-
expect {Protocolist.fire
|
32
|
+
|
33
|
+
expect { Protocolist.fire(:alarm) }.not_to change { Activity.count }
|
34
|
+
expect { Protocolist.fire(:alarm) }.not_to raise_error
|
29
35
|
end
|
30
36
|
|
31
37
|
it 'should save a simple record' do
|
32
|
-
expect {Protocolist.fire
|
38
|
+
expect { Protocolist.fire(:alarm) }.to change { Activity.count }.by(1)
|
33
39
|
|
34
|
-
Activity.last
|
35
|
-
|
40
|
+
activity = Activity.last
|
41
|
+
activity.actor.should == actor
|
42
|
+
activity.activity_type.should == :alarm
|
36
43
|
end
|
37
44
|
|
38
45
|
it 'should save a complex record' do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
Activity.last.target.name.should == 'Mary'
|
52
|
-
Activity.last.data[:some_attr].should == :some_data
|
46
|
+
expect do
|
47
|
+
Protocolist.fire(:alarm,
|
48
|
+
actor: another_actor,
|
49
|
+
target: target,
|
50
|
+
data: { foo: :bar })
|
51
|
+
end.to change { Activity.count }.by(1)
|
52
|
+
|
53
|
+
activity = Activity.last
|
54
|
+
activity.actor.should == another_actor
|
55
|
+
activity.activity_type.should == :alarm
|
56
|
+
activity.target.should == target
|
57
|
+
activity.data[:foo].should == :bar
|
53
58
|
end
|
54
59
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,8 +2,11 @@ require 'protocolist'
|
|
2
2
|
require 'supermodel'
|
3
3
|
Bundler.require(:default)
|
4
4
|
|
5
|
+
User = Class.new(SuperModel::Base)
|
6
|
+
Activity = Class.new(SuperModel::Base)
|
7
|
+
|
5
8
|
RSpec.configure do |config|
|
6
9
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
-
config.filter_run
|
10
|
+
config.filter_run(focus: true)
|
8
11
|
config.run_all_when_everything_filtered = true
|
9
12
|
end
|
metadata
CHANGED
@@ -1,19 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocolist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Dmitry Yakimov
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rake
|
16
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
17
33
|
none: false
|
18
34
|
requirements:
|
19
35
|
- - ! '>='
|
@@ -21,43 +37,79 @@ dependencies:
|
|
21
37
|
version: '0'
|
22
38
|
type: :development
|
23
39
|
prerelease: false
|
24
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
25
46
|
- !ruby/object:Gem::Dependency
|
26
47
|
name: rspec
|
27
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
28
49
|
none: false
|
29
50
|
requirements:
|
30
51
|
- - ~>
|
31
52
|
- !ruby/object:Gem::Version
|
32
|
-
version: 2.
|
53
|
+
version: 2.12.0
|
33
54
|
type: :development
|
34
55
|
prerelease: false
|
35
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.12.0
|
36
62
|
- !ruby/object:Gem::Dependency
|
37
63
|
name: guard-rspec
|
38
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
39
65
|
none: false
|
40
66
|
requirements:
|
41
67
|
- - ~>
|
42
68
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
69
|
+
version: 2.3.0
|
44
70
|
type: :development
|
45
71
|
prerelease: false
|
46
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.3.0
|
47
78
|
- !ruby/object:Gem::Dependency
|
48
79
|
name: supermodel
|
49
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
50
81
|
none: false
|
51
82
|
requirements:
|
52
|
-
- -
|
83
|
+
- - ~>
|
53
84
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
85
|
+
version: 0.1.6
|
55
86
|
type: :development
|
56
87
|
prerelease: false
|
57
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.1.6
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: psych
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.3.0
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.3.0
|
58
110
|
- !ruby/object:Gem::Dependency
|
59
111
|
name: railties
|
60
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
61
113
|
none: false
|
62
114
|
requirements:
|
63
115
|
- - ~>
|
@@ -65,7 +117,12 @@ dependencies:
|
|
65
117
|
version: '3.0'
|
66
118
|
type: :development
|
67
119
|
prerelease: false
|
68
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '3.0'
|
69
126
|
description: ! 'Simple activity feeds solution for Rails applications. Gives a flexible
|
70
127
|
way to build activity feeds infrastructure over it. '
|
71
128
|
email:
|
@@ -87,8 +144,10 @@ files:
|
|
87
144
|
- lib/generators/protocolist/install/templates/migration.rb
|
88
145
|
- lib/protocolist.rb
|
89
146
|
- lib/protocolist/controller_additions.rb
|
147
|
+
- lib/protocolist/controller_additions/initializer.rb
|
90
148
|
- lib/protocolist/model_additions.rb
|
91
149
|
- lib/protocolist/railtie.rb
|
150
|
+
- lib/protocolist/util/data_proc.rb
|
92
151
|
- lib/protocolist/version.rb
|
93
152
|
- protocolist.gemspec
|
94
153
|
- spec/protocolist/controller_additions_spec.rb
|
@@ -107,16 +166,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
166
|
- - ! '>='
|
108
167
|
- !ruby/object:Gem::Version
|
109
168
|
version: '0'
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
hash: 1046353843920226917
|
110
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
173
|
none: false
|
112
174
|
requirements:
|
113
|
-
- - ! '
|
175
|
+
- - ! '>='
|
114
176
|
- !ruby/object:Gem::Version
|
115
|
-
version:
|
177
|
+
version: '0'
|
178
|
+
segments:
|
179
|
+
- 0
|
180
|
+
hash: 1046353843920226917
|
116
181
|
requirements: []
|
117
182
|
rubyforge_project: protocolist
|
118
|
-
rubygems_version: 1.8.
|
183
|
+
rubygems_version: 1.8.24
|
119
184
|
signing_key:
|
120
185
|
specification_version: 3
|
121
186
|
summary: Activity feeds solution for Rails.
|
122
|
-
test_files:
|
187
|
+
test_files:
|
188
|
+
- spec/protocolist/controller_additions_spec.rb
|
189
|
+
- spec/protocolist/model_additions_spec.rb
|
190
|
+
- spec/protocolist_spec.rb
|
191
|
+
- spec/spec_helper.rb
|