streamit 0.0.5 → 0.0.6
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/Gemfile +5 -1
- data/README.rdoc +32 -0
- data/TODO +2 -33
- data/app/controllers/streamit/streams_controller.rb +8 -3
- data/app/views/streamit/streams/fetch.html.erb +1 -1
- data/lib/generators/streamit_generator.rb +4 -0
- data/lib/generators/templates/_stream.html.erb +1 -2
- data/lib/generators/templates/streamit.rb +3 -0
- data/lib/streamit.rb +29 -3
- data/lib/streamit/dsl.rb +30 -14
- data/lib/streamit/orm/active_record.rb +0 -2
- data/lib/streamit/orm/mongo_mapper.rb +23 -0
- data/test/dummy/app/models/stream.rb +3 -2
- data/test/dummy/config/initializers/streamit.rb +3 -0
- data/test/dummy/config/locales/en.yml +0 -3
- data/test/integration/navigation_test.rb +17 -4
- data/test/streamit_test.rb +12 -1
- data/test/test_helper.rb +5 -1
- metadata +6 -2
data/Gemfile
CHANGED
|
@@ -7,4 +7,8 @@ gem "sqlite3-ruby", :require => "sqlite3"
|
|
|
7
7
|
gem "mocha", ">= 0.9.10"
|
|
8
8
|
gem "shoulda-context", "1.0.0.beta1"
|
|
9
9
|
gem "launchy", ">= 0.3.7"
|
|
10
|
-
gem "timecop", ">= 0.3.5"
|
|
10
|
+
gem "timecop", ">= 0.3.5"
|
|
11
|
+
|
|
12
|
+
gem "mongo_mapper", "~> 0.9.1"
|
|
13
|
+
gem "mongo", "~> 1.3.1"
|
|
14
|
+
gem 'bson_ext', "~> 1.3.1"
|
data/README.rdoc
CHANGED
|
@@ -1,2 +1,34 @@
|
|
|
1
1
|
= Streamit (Under development)
|
|
2
2
|
|
|
3
|
+
Provides feed stream like feature to rails apps
|
|
4
|
+
|
|
5
|
+
class Stream
|
|
6
|
+
include MongoMapper::Document
|
|
7
|
+
include Streamit::ORM::MongoMapper
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# "he9lin started watching auction ipad a minute ago"
|
|
11
|
+
#
|
|
12
|
+
# en:
|
|
13
|
+
# streamit:
|
|
14
|
+
# watching:
|
|
15
|
+
# create: "started watching"
|
|
16
|
+
#
|
|
17
|
+
class Watching < ActiveRecord::Base
|
|
18
|
+
belongs_to :watcher, :class_name => "User", :foreign_key => "user_id"
|
|
19
|
+
belongs_to :watched_item, :class_name => "Item", :foreign_key => "item_id"
|
|
20
|
+
|
|
21
|
+
stream :create, :actor => :watcher,
|
|
22
|
+
:receiver => :watched_item
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# "he9lin edited profile image just now"
|
|
26
|
+
#
|
|
27
|
+
# en:
|
|
28
|
+
# users:
|
|
29
|
+
# update:
|
|
30
|
+
# image_url: "edited profile image"
|
|
31
|
+
#
|
|
32
|
+
class User < ActiveRecord::Base
|
|
33
|
+
stream :update, :attributes => :image_url
|
|
34
|
+
end
|
data/TODO
CHANGED
|
@@ -1,35 +1,4 @@
|
|
|
1
1
|
TODO:
|
|
2
|
-
- use background job like tool to process creating of streams
|
|
3
|
-
- customizable views
|
|
4
|
-
- cleanup old streams
|
|
5
|
-
- add more detailed documentation
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
belongs_to :subject, :polymorphic => true
|
|
10
|
-
belongs_to :receiver, :polymorphic => true
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# "he9lin started watching auction ipad 001 a minute ago"
|
|
14
|
-
#
|
|
15
|
-
# en:
|
|
16
|
-
# streamit:
|
|
17
|
-
# watching:
|
|
18
|
-
# create: "started watching"
|
|
19
|
-
|
|
20
|
-
class Watching < ActiveRecord::Base
|
|
21
|
-
belongs_to :watcher, :class_name => "User", :foreign_key => "user_id"
|
|
22
|
-
belongs_to :watched_item, :class_name => "Item", :foreign_key => "item_id"
|
|
23
|
-
|
|
24
|
-
stream :create, :actor => :watcher,
|
|
25
|
-
:receiver => :watched_item
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# "he9lin just edited profile image just now"
|
|
29
|
-
#
|
|
30
|
-
# stream:
|
|
31
|
-
# stream_type: 'user.update.image_url'
|
|
32
|
-
#
|
|
33
|
-
class User < ActiveRecord::Base
|
|
34
|
-
stream :update, :attributes => :image_url
|
|
35
|
-
end
|
|
3
|
+
Support json format
|
|
4
|
+
Refactor
|
|
@@ -15,9 +15,14 @@ class Streamit::StreamsController < ApplicationController
|
|
|
15
15
|
private
|
|
16
16
|
|
|
17
17
|
def process_params
|
|
18
|
-
@streams = [:ago, :
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
@streams = [:ago, :limit].inject(store) do |memo, sym|
|
|
19
|
+
case sym
|
|
20
|
+
when :limit
|
|
21
|
+
params[sym] ? memo.send(sym, params[sym].to_i) : memo
|
|
22
|
+
else
|
|
23
|
+
params[sym] ? memo.send(sym, params[sym]) : memo
|
|
24
|
+
end
|
|
21
25
|
end
|
|
22
26
|
end
|
|
27
|
+
|
|
23
28
|
end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render @streams %>
|
|
1
|
+
<%= render @streams.all %>
|
data/lib/streamit.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
require 'active_support/core_ext/hash'
|
|
2
|
+
require "mongo_mapper"
|
|
3
|
+
|
|
4
|
+
# We are required to choose a database name
|
|
5
|
+
MongoMapper.database = "streamit-#{Rails.env}"
|
|
2
6
|
|
|
3
7
|
module Streamit
|
|
4
8
|
autoload :DSL, 'streamit/dsl'
|
|
5
9
|
autoload :Store, 'streamit/store'
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
def self.setup
|
|
12
|
+
yield self
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
# Set which store to use.
|
|
@@ -20,8 +24,30 @@ module Streamit
|
|
|
20
24
|
def self.store; end
|
|
21
25
|
|
|
22
26
|
def self.save_stream!(args)
|
|
23
|
-
|
|
27
|
+
# insert to queue
|
|
28
|
+
self.queue << args
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Queue related methods
|
|
32
|
+
def self.finish!
|
|
33
|
+
queue << nil
|
|
34
|
+
thread.join
|
|
35
|
+
@thread = nil
|
|
36
|
+
thread
|
|
24
37
|
end
|
|
38
|
+
|
|
39
|
+
def self.queue
|
|
40
|
+
@queue ||= Queue.new
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.thread
|
|
44
|
+
@thread ||= Thread.new do
|
|
45
|
+
while args = queue.pop
|
|
46
|
+
store.save_stream!(args)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
25
51
|
end
|
|
26
52
|
|
|
27
53
|
require 'streamit/engine'
|
data/lib/streamit/dsl.rb
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
module Streamit
|
|
2
2
|
module DSL
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
# A class method for ActiveRecord models
|
|
6
|
+
#
|
|
7
|
+
# Sample usage:
|
|
8
|
+
#
|
|
5
9
|
# stream :create, :actor => :watcher,
|
|
6
10
|
# :receiver => :watched_item
|
|
7
11
|
#
|
|
@@ -9,7 +13,7 @@ module Streamit
|
|
|
9
13
|
#
|
|
10
14
|
module ClassMethods
|
|
11
15
|
def stream(action, options={})
|
|
12
|
-
options.assert_valid_keys(:
|
|
16
|
+
options.assert_valid_keys(:actor, :subject, :receiver, :attributes)
|
|
13
17
|
raise ArgumentError, ":create or :update required as first parameter" \
|
|
14
18
|
unless [:create, :update].any? {|sym| sym == action }
|
|
15
19
|
|
|
@@ -27,26 +31,38 @@ module Streamit
|
|
|
27
31
|
|
|
28
32
|
stream_type = attr_name.nil? ? "streamit.#{table_name}.#{action}" :
|
|
29
33
|
"streamit.#{table_name}.#{action}.#{attr_name}"
|
|
30
|
-
|
|
34
|
+
|
|
31
35
|
method_name = :"_#{stream_type.gsub('.', '_')}"
|
|
36
|
+
|
|
32
37
|
define_method(method_name) do
|
|
33
38
|
stream_options = [:actor, :receiver, :subject].inject({}) do |memo, sym|
|
|
34
39
|
memo[sym] = options[sym] ? send(options[sym]) : (sym == :actor ? self : nil)
|
|
35
40
|
memo
|
|
36
41
|
end.merge(:stream_type => stream_type, :started_at => Time.now)
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
if (action != :update || instance_variable_get("@attr_changed"))
|
|
44
|
+
Streamit.save_stream!(stream_options)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
instance_variable_set("@attr_changed", false)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if action == :update
|
|
51
|
+
before_update_method_name = "_before#{method_name}"
|
|
52
|
+
define_method(before_update_method_name) do
|
|
53
|
+
attr_changed = if action == :update
|
|
54
|
+
case attributes
|
|
55
|
+
when nil
|
|
56
|
+
changed?
|
|
57
|
+
when Array
|
|
58
|
+
attributes.any? { |attr| send(:"#{attr}_changed?") }
|
|
59
|
+
when Symbol
|
|
60
|
+
send(:"#{attributes}_changed?")
|
|
61
|
+
end
|
|
46
62
|
end
|
|
63
|
+
instance_variable_set("@attr_changed", attr_changed)
|
|
47
64
|
end
|
|
48
|
-
|
|
49
|
-
Streamit.save_stream!(stream_options) if (action != :update || attr_changed)
|
|
65
|
+
send(:"before_update", before_update_method_name)
|
|
50
66
|
end
|
|
51
67
|
|
|
52
68
|
send(:"after_#{action}", method_name)
|
|
@@ -54,4 +70,4 @@ module Streamit
|
|
|
54
70
|
end
|
|
55
71
|
|
|
56
72
|
end # DSL
|
|
57
|
-
end # Streamit
|
|
73
|
+
end # Streamit
|
|
@@ -11,13 +11,11 @@ module Streamit
|
|
|
11
11
|
|
|
12
12
|
default_scope order("started_at DESC")
|
|
13
13
|
scope :ago, lambda { |num| where ["started_at > ?", Time.now - num.to_i.seconds] }
|
|
14
|
-
scope :after, lambda { |id| where("id > #{id}") }
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
def save_stream!
|
|
18
17
|
save!
|
|
19
18
|
end
|
|
20
19
|
end
|
|
21
|
-
|
|
22
20
|
end
|
|
23
21
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Streamit
|
|
2
|
+
module ORM
|
|
3
|
+
module MongoMapper
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
include Streamit::Store
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
key :stream_type, String
|
|
9
|
+
key :started_at, Time
|
|
10
|
+
|
|
11
|
+
belongs_to :actor, :polymorphic => true
|
|
12
|
+
belongs_to :subject, :polymorphic => true
|
|
13
|
+
belongs_to :receiver, :polymorphic => true
|
|
14
|
+
|
|
15
|
+
scope :ago, lambda { |num| where(:started_at.gt => Time.now - num.to_i.seconds) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def save_stream!
|
|
19
|
+
save!
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
3
|
class NavigationTest < ActiveSupport::IntegrationCase
|
|
4
|
+
|
|
5
|
+
def wait_and_finish
|
|
6
|
+
Streamit.finish!
|
|
7
|
+
end
|
|
4
8
|
|
|
5
9
|
def register_new_user
|
|
6
10
|
visit "/users/new"
|
|
7
11
|
fill_in "Name", :with => "davis"
|
|
8
12
|
click_button "Create User"
|
|
13
|
+
wait_and_finish
|
|
9
14
|
end
|
|
10
15
|
|
|
11
|
-
should "fetch
|
|
16
|
+
should "fetch limited number of streams" do
|
|
17
|
+
register_new_user
|
|
18
|
+
register_new_user
|
|
12
19
|
register_new_user
|
|
13
20
|
register_new_user
|
|
14
|
-
|
|
21
|
+
wait_and_finish
|
|
22
|
+
visit "/streamit/fetch?limit=2"
|
|
15
23
|
assert page.has_selector?("li.stream", :count => 2), "Expected 2 streams, Got:\n#{page.body.inspect}"
|
|
16
24
|
end
|
|
17
25
|
|
|
@@ -21,15 +29,20 @@ class NavigationTest < ActiveSupport::IntegrationCase
|
|
|
21
29
|
end
|
|
22
30
|
register_new_user
|
|
23
31
|
register_new_user
|
|
32
|
+
wait_and_finish
|
|
24
33
|
visit "/streamit/fetch?ago=30"
|
|
25
34
|
assert page.has_selector?("li.stream", :count => 2), "Expected 2 streams, Got:\n#{page.body.inspect}"
|
|
26
35
|
end
|
|
27
36
|
|
|
28
|
-
should "fetch streams
|
|
37
|
+
should "fetch limited number of streams in last ? seconds" do
|
|
38
|
+
Timecop.freeze(Time.now - 30.seconds) do
|
|
39
|
+
register_new_user
|
|
40
|
+
end
|
|
29
41
|
register_new_user
|
|
30
42
|
register_new_user
|
|
31
43
|
register_new_user
|
|
32
|
-
|
|
44
|
+
wait_and_finish
|
|
45
|
+
visit "/streamit/fetch?ago=30&limit=2"
|
|
33
46
|
assert page.has_selector?("li.stream", :count => 2), "Expected 2 streams, Got:\n#{page.body.inspect}"
|
|
34
47
|
end
|
|
35
48
|
|
data/test/streamit_test.rb
CHANGED
|
@@ -5,6 +5,10 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
5
5
|
Streamit.store
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
def wait_and_finish
|
|
9
|
+
Streamit.finish!
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
context "when user watches an item" do
|
|
9
13
|
setup do
|
|
10
14
|
TestWatching.class_eval do
|
|
@@ -15,6 +19,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
15
19
|
|
|
16
20
|
should "create a stream if watching is created successfully" do
|
|
17
21
|
@watch.save
|
|
22
|
+
wait_and_finish
|
|
18
23
|
stream = stream_store.last
|
|
19
24
|
assert_not_nil stream
|
|
20
25
|
assert_equal "streamit.testwatchings.create", stream.stream_type
|
|
@@ -27,7 +32,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
27
32
|
TestWatching.class_eval do
|
|
28
33
|
before_create { return false }
|
|
29
34
|
end
|
|
30
|
-
assert_no_difference("stream_store.count") { @watch.save }
|
|
35
|
+
assert_no_difference("stream_store.count") { @watch.save; wait_and_finish }
|
|
31
36
|
end
|
|
32
37
|
end
|
|
33
38
|
|
|
@@ -44,6 +49,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
44
49
|
stream :create
|
|
45
50
|
end
|
|
46
51
|
@user.save
|
|
52
|
+
wait_and_finish
|
|
47
53
|
stream = stream_store.last
|
|
48
54
|
assert_not_nil stream
|
|
49
55
|
assert_equal "streamit.testusers.create", stream.stream_type
|
|
@@ -55,6 +61,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
55
61
|
context "when user updates her attributes" do
|
|
56
62
|
setup do
|
|
57
63
|
@user.save
|
|
64
|
+
wait_and_finish
|
|
58
65
|
end
|
|
59
66
|
|
|
60
67
|
should "create a stream the attribute specified has changed" do
|
|
@@ -63,6 +70,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
63
70
|
end
|
|
64
71
|
@user.image_url = "image"
|
|
65
72
|
@user.save
|
|
73
|
+
wait_and_finish
|
|
66
74
|
stream = stream_store.last
|
|
67
75
|
assert_not_nil stream
|
|
68
76
|
assert_equal "streamit.testusers.update.image_url", stream.stream_type
|
|
@@ -77,6 +85,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
77
85
|
end
|
|
78
86
|
@user.name = "davis"
|
|
79
87
|
@user.save
|
|
88
|
+
wait_and_finish
|
|
80
89
|
stream = stream_store.last
|
|
81
90
|
assert_not_nil stream
|
|
82
91
|
assert_equal "streamit.testusers.update.default", stream.stream_type
|
|
@@ -91,6 +100,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
91
100
|
end
|
|
92
101
|
@user.name = "davis"
|
|
93
102
|
@user.save
|
|
103
|
+
wait_and_finish
|
|
94
104
|
stream = stream_store.last
|
|
95
105
|
assert_not_nil stream
|
|
96
106
|
assert_equal "streamit.testusers.update.default", stream.stream_type
|
|
@@ -109,6 +119,7 @@ class StreamitTest < ActiveSupport::TestCase
|
|
|
109
119
|
end
|
|
110
120
|
@user.image_url = "image"
|
|
111
121
|
@user.save
|
|
122
|
+
wait_and_finish
|
|
112
123
|
assert_equal 0, stream_store.count
|
|
113
124
|
end
|
|
114
125
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -19,4 +19,8 @@ Capybara.default_selector = :css
|
|
|
19
19
|
ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
|
|
20
20
|
|
|
21
21
|
# Load support files
|
|
22
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
22
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
23
|
+
|
|
24
|
+
class ActiveSupport::TestCase
|
|
25
|
+
setup { Streamit.store.delete_all }
|
|
26
|
+
end
|
metadata
CHANGED
|
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
7
|
- 0
|
|
8
|
-
-
|
|
9
|
-
version: 0.0.
|
|
8
|
+
- 6
|
|
9
|
+
version: 0.0.6
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Lin He
|
|
@@ -38,11 +38,13 @@ files:
|
|
|
38
38
|
- lib/streamit.rb
|
|
39
39
|
- lib/generators/streamit_generator.rb
|
|
40
40
|
- lib/generators/templates/_stream.html.erb
|
|
41
|
+
- lib/generators/templates/streamit.rb
|
|
41
42
|
- lib/streamit/dsl.rb
|
|
42
43
|
- lib/streamit/engine.rb
|
|
43
44
|
- lib/streamit/store.rb
|
|
44
45
|
- lib/streamit/locales/en.yml
|
|
45
46
|
- lib/streamit/orm/active_record.rb
|
|
47
|
+
- lib/streamit/orm/mongo_mapper.rb
|
|
46
48
|
- test/dummy/app/controllers/application_controller.rb
|
|
47
49
|
- test/dummy/app/controllers/users_controller.rb
|
|
48
50
|
- test/dummy/app/models/stream.rb
|
|
@@ -64,6 +66,7 @@ files:
|
|
|
64
66
|
- test/dummy/config/initializers/backtrace_silencers.rb
|
|
65
67
|
- test/dummy/config/initializers/secret_token.rb
|
|
66
68
|
- test/dummy/config/initializers/session_store.rb
|
|
69
|
+
- test/dummy/config/initializers/streamit.rb
|
|
67
70
|
- test/dummy/config/locales/en.yml
|
|
68
71
|
- test/dummy/db/migrate/20110204210955_create_users.rb
|
|
69
72
|
- test/dummy/db/migrate/20110204210910_create_items.rb
|
|
@@ -137,6 +140,7 @@ test_files:
|
|
|
137
140
|
- test/dummy/config/initializers/backtrace_silencers.rb
|
|
138
141
|
- test/dummy/config/initializers/secret_token.rb
|
|
139
142
|
- test/dummy/config/initializers/session_store.rb
|
|
143
|
+
- test/dummy/config/initializers/streamit.rb
|
|
140
144
|
- test/dummy/config/locales/en.yml
|
|
141
145
|
- test/dummy/db/migrate/20110204210955_create_users.rb
|
|
142
146
|
- test/dummy/db/migrate/20110204210910_create_items.rb
|