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 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"
@@ -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
- class Streamit::Stream < ActiveRecord::Base
8
- belongs_to :actor, :polymorphic => true
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, :after, :limit].inject(store.scoped) do |scp, sym|
19
- scp = scp.send(sym, params[sym]) if params[sym]
20
- scp
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 %>
@@ -26,6 +26,10 @@ CONTENT
26
26
  def create_stream_view
27
27
  copy_file "_stream.html.erb", "app/views/streamit/streams/_stream.html.erb"
28
28
  end
29
+
30
+ def create_initializer
31
+ copy_file "streamit.rb", "app/config/initializers/streamit.rb"
32
+ end
29
33
 
30
34
  protected
31
35
 
@@ -1,4 +1,3 @@
1
- TODO:
2
1
  <%= content_tag_for(:li, stream) do %>
3
2
  <%= stream.actor %> <%= stream.stream_type_in_words %> <%= stream.subject %> to <%= stream.receiver %> <%= time_ago_in_words(stream.started_at) %> ago
4
- <% end %>
3
+ <% end %>
@@ -0,0 +1,3 @@
1
+ Streamit.setup do |config|
2
+ require 'streamit/orm/mongo_mapper'
3
+ end
@@ -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
- module ORM
8
- autoload :ActiveRecord, 'streamit/orm/active_record'
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
- store.save_stream!(args)
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'
@@ -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(:stream_type, :actor, :subject, :receiver, :attributes)
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
- attr_changed = if action == :update
39
- case attributes
40
- when nil
41
- changed?
42
- when Array
43
- attributes.any? { |attr| send(:"#{attr}_changed?") }
44
- when Symbol
45
- send(:"#{attributes}_changed?")
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,3 +1,4 @@
1
- class Stream < ActiveRecord::Base
2
- include Streamit::ORM::ActiveRecord
1
+ class Stream
2
+ include MongoMapper::Document
3
+ include Streamit::ORM::MongoMapper
3
4
  end
@@ -0,0 +1,3 @@
1
+ Streamit.setup do |config|
2
+ require 'streamit/orm/mongo_mapper'
3
+ end
@@ -1,6 +1,3 @@
1
- # Sample localization file for English. Add more files in this directory for other locales.
2
- # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
-
4
1
  en:
5
2
  streamit:
6
3
  users:
@@ -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 recent streams" do
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
- visit "/streamit/fetch"
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 from after an id" do
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
- visit "/streamit/fetch?after=#{Stream.last.id}"
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
 
@@ -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
@@ -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
- - 5
9
- version: 0.0.5
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