paritytimeline 0.4
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +152 -0
- data/Rakefile +38 -0
- data/lib/redis_timeline.rb +21 -0
- data/lib/tasks/timeline_tasks.rake +4 -0
- data/lib/timeline/activity.rb +11 -0
- data/lib/timeline/actor.rb +36 -0
- data/lib/timeline/config.rb +42 -0
- data/lib/timeline/controller_helper.rb +153 -0
- data/lib/timeline/helpers.rb +23 -0
- data/lib/timeline/notification_helper.rb +98 -0
- data/lib/timeline/track.rb +116 -0
- data/lib/timeline/untitled.txt +9 -0
- data/lib/timeline/version.rb +3 -0
- data/spec/activity_spec.rb +12 -0
- data/spec/actor_spec.rb +23 -0
- data/spec/redis-test.conf +598 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/timeline_spec.rb +12 -0
- data/spec/track_spec.rb +139 -0
- metadata +198 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
module Timeline::Track
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def track(name, options={})
|
6
|
+
@name = name
|
7
|
+
@actor = options.delete :actor
|
8
|
+
@actor ||= :creator
|
9
|
+
@object = options.delete :object
|
10
|
+
@target = options.delete :target
|
11
|
+
@followers = options.delete :followers
|
12
|
+
@followers ||= :followers
|
13
|
+
@mentionable = options.delete :mentionable
|
14
|
+
|
15
|
+
method_name = "track_#{@name}_after_#{@callback}".to_sym
|
16
|
+
define_activity_method method_name, actor: @actor, object: @object, target: @target, followers: @followers, verb: name, mentionable: @mentionable
|
17
|
+
|
18
|
+
send "after_#{@callback}".to_sym, method_name, if: options.delete(:if)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def define_activity_method(method_name, options={})
|
23
|
+
define_method method_name do
|
24
|
+
@actor = send(options[:actor])
|
25
|
+
@fields_for = {}
|
26
|
+
@object = set_object(options[:object])
|
27
|
+
@target = !options[:target].nil? ? send(options[:target].to_sym) : nil
|
28
|
+
@extra_fields ||= nil
|
29
|
+
@followers = @actor.send(options[:followers].to_sym)
|
30
|
+
@mentionable = options[:mentionable]
|
31
|
+
add_activity activity(verb: options[:verb])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def activity(options={})
|
38
|
+
{
|
39
|
+
verb: options[:verb],
|
40
|
+
actor: options_for(@actor),
|
41
|
+
object: options_for(@object),
|
42
|
+
target: options_for(@target),
|
43
|
+
created_at: Time.now
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_activity(activity_item)
|
48
|
+
redis_add "global:activity", activity_item
|
49
|
+
add_activity_to_user(activity_item[:actor][:id], activity_item)
|
50
|
+
add_activity_by_user(activity_item[:actor][:id], activity_item)
|
51
|
+
add_mentions(activity_item)
|
52
|
+
add_activity_to_followers(activity_item) if @followers.any?
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_activity_by_user(user_id, activity_item)
|
56
|
+
redis_add "user:id:#{user_id}:posts", activity_item
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_activity_to_user(user_id, activity_item)
|
60
|
+
redis_add "user:id:#{user_id}:activity", activity_item
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_activity_to_followers(activity_item)
|
64
|
+
@followers.each { |follower| add_activity_to_user(follower.id, activity_item) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_mentions(activity_item)
|
68
|
+
return unless @mentionable and @object.send(@mentionable)
|
69
|
+
@object.send(@mentionable).scan(/@\w+/).each do |mention|
|
70
|
+
if user = @actor.class.find_by_username(mention[1..-1])
|
71
|
+
add_mention_to_user(user.id, activity_item)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_mention_to_user(user_id, activity_item)
|
77
|
+
redis_add "user:id:#{user_id}:mentions", activity_item
|
78
|
+
end
|
79
|
+
|
80
|
+
def extra_fields_for(object)
|
81
|
+
return {} unless @fields_for.has_key?(object.class.to_s.downcase.to_sym)
|
82
|
+
@fields_for[object.class.to_s.downcase.to_sym].inject({}) do |sum, method|
|
83
|
+
sum[method.to_sym] = @object.send(method.to_sym)
|
84
|
+
sum
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def options_for(target)
|
89
|
+
if !target.nil?
|
90
|
+
{
|
91
|
+
id: target.id,
|
92
|
+
class: target.class.to_s,
|
93
|
+
display_name: target.to_s
|
94
|
+
}.merge(extra_fields_for(target))
|
95
|
+
else
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def redis_add(list, activity_item)
|
101
|
+
Timeline.redis.lpush list, Timeline.encode(activity_item)
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_object(object)
|
105
|
+
case
|
106
|
+
when object.is_a?(Symbol)
|
107
|
+
send(object)
|
108
|
+
when object.is_a?(Array)
|
109
|
+
@fields_for[self.class.to_s.downcase.to_sym] = object
|
110
|
+
self
|
111
|
+
else
|
112
|
+
self
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
1.upto(User.last.id).each do |u|
|
2
|
+
list = "user:id:#{u}:notification"
|
3
|
+
Timeline.redis.ltrim list, 0, 30
|
4
|
+
list = "user:id:#{u}:posts"
|
5
|
+
Timeline.redis.ltrim list, 0, 30
|
6
|
+
list = "user:id:#{u}:activity"
|
7
|
+
Timeline.redis.ltrim list, 0, 30
|
8
|
+
Timeline.redis.ltrim "global:activity:new_premium_deal", 0, 200
|
9
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Timeline::Activity do
|
4
|
+
describe "initialized with json" do
|
5
|
+
let(:json) { { id: "1", verb: "new_post" } }
|
6
|
+
|
7
|
+
it "returns a Hashie-fied object" do
|
8
|
+
Timeline::Activity.new(json).id.should == "1"
|
9
|
+
Timeline::Activity.new(json).verb.should == "new_post"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/spec/actor_spec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
class User
|
4
|
+
include Timeline::Actor
|
5
|
+
|
6
|
+
attr_accessor :id
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Timeline::Actor do
|
10
|
+
describe "when included" do
|
11
|
+
before { @user = User.new }
|
12
|
+
|
13
|
+
it "defines a timeline association" do
|
14
|
+
@user.should respond_to :timeline
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".timeline" do
|
18
|
+
subject { @user.timeline }
|
19
|
+
|
20
|
+
it { should == [] }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|