streamit 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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