seymour 0.0.7 → 0.0.8

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/.gitignore CHANGED
@@ -6,3 +6,5 @@ spec/dummy/log/*.log
6
6
  spec/dummy/tmp/
7
7
  tmp/
8
8
  .rspec
9
+ Gemfile.lock
10
+ Gemfile.local
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - ree
4
+
5
+ before_script: "sh -c 'cd spec/dummy && bundle exec rake db:migrate'"
6
+
7
+ gemfile: Gemfile.ci
@@ -1,3 +1,17 @@
1
+ ## 0.0.8 (2012-2-06)
2
+
3
+ * travis build status; clean Gemfile dependencies
4
+ * Move rails initialization to railtie
5
+ * Added support for zunionstore and zinterstore
6
+ * extract redis list object from feed
7
+ * feed class method 'key' to define key override
8
+
9
+ ## 0.0.7 (2011-12-04)
10
+
11
+ * Support for zset feeds
12
+ * Extract redis methods to store module
13
+ * Rails generator for basic feed
14
+
1
15
  ## 0.0.6 (2011-10-24)
2
16
 
3
17
  * Ruby 1.8.7 compatiblity
data/Gemfile CHANGED
@@ -1,23 +1,21 @@
1
- source "http://rubygems.org"
1
+ source :rubygems
2
2
 
3
- # Declare your gem's dependencies in seymour.gemspec.
4
- # Bundler will treat runtime dependencies like base dependencies, and
5
- # development dependencies will be added by default to the :development group.
6
3
  gemspec
4
+ gem 'redis-namespace', :git => "git://github.com/defunkt/redis-namespace.git"
7
5
 
8
6
  # Declare any dependencies that are still in development here instead of in
9
7
  # your gemspec. These might include edge Rails or gems from your path or
10
8
  # Git. Remember to move these dependencies to your gemspec before releasing
11
9
  # your gem to rubygems.org.
12
10
 
13
- # To use debugger
14
- group :test, :development do
15
- gem 'ruby-debug19', :require => 'ruby-debug', :platform => :ruby_19
16
- gem 'ruby-debug', :platform => :ruby_18
17
- gem 'guard'
18
- gem 'guard-rspec'
19
- gem 'rb-fsevent' # Makes guard better
20
- gem 'growl_notify' # Makes guard better
21
- gem 'launchy'
22
- gem 'yard'
23
- end
11
+ # # To use debugger
12
+ # group :development do
13
+ # gem 'ruby-debug19', :require => 'ruby-debug', :platform => :ruby_19
14
+ # gem 'ruby-debug', :platform => :ruby_18
15
+ # gem 'guard'
16
+ # gem 'guard-rspec'
17
+ # gem 'rb-fsevent' # Makes guard better
18
+ # gem 'growl_notify' # Makes guard better
19
+ # gem 'launchy'
20
+ # gem 'yard'
21
+ # end
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+ gem 'redis-namespace', :git => "git://github.com/defunkt/redis-namespace.git"
data/README.md CHANGED
@@ -5,6 +5,9 @@ Feed me activities, Seymour, please!
5
5
  Seymour is a library for distributing activity items to Redis-backed activity feeds
6
6
  in a Rails application.
7
7
 
8
+ [![Build Status](https://secure.travis-ci.org/rossta/seymour.png)](http://travis-ci.org/rossta/seymour)
9
+
10
+
8
11
  ## Install
9
12
 
10
13
  In your Gemfile
@@ -1,10 +1,12 @@
1
1
  require "seymour/version"
2
2
  require "seymour/redis"
3
+ require "seymour/store"
3
4
  require "seymour/feed"
4
5
  require "seymour/acts_as_activity"
5
6
  require "seymour/distributable"
6
7
  require "seymour/renderable"
7
8
  require "seymour/render_controller"
9
+ require 'seymour/railtie' if defined?(Rails)
8
10
 
9
11
  module Seymour
10
12
  extend self
@@ -14,5 +14,3 @@ module Seymour
14
14
 
15
15
  end
16
16
  end
17
-
18
- ActiveRecord::Base.send :include, Seymour::ActsAsActivity
@@ -4,79 +4,55 @@ module Seymour
4
4
  attr_accessor :owner
5
5
 
6
6
  class << self
7
- @@feed_classes = []
7
+
8
+ def key(&block)
9
+ define_method('key_to_store', &block)
10
+ end
8
11
 
9
12
  def distribute(activity)
10
13
  activity.distribute
11
14
  end
12
15
 
13
16
  def inherited(subclass)
14
- @@feed_classes << subclass
17
+ feed_classes << subclass
15
18
  end
16
19
 
17
20
  def feed_classes
18
- @@feed_classes
21
+ @@feed_classes ||= []
19
22
  end
20
- end
21
-
22
- def initialize(owner)
23
- @owner = owner
24
- end
25
23
 
26
- def activity_ids
27
- redis.lrange(key, 0, max_size).map{|id| id.to_i }
28
- end
29
-
30
- def push(activity)
31
- perform_push(activity.id) if should_push?(activity)
32
- end
33
-
34
- def bulk_push(activities)
35
- activities.each do |activity|
36
- push(activity)
24
+ def store(store_type)
25
+ @store_type = "seymour/store/#{store_type}".camelize.constantize
37
26
  end
38
- end
39
27
 
40
- def remove(activity)
41
- remove_id activity.id
28
+ def store_type
29
+ @store_type ||= Seymour::Store::List
30
+ end
42
31
  end
43
32
 
44
- def remove_id(activity_id)
45
- redis.lrem(key, 0, activity_id)
33
+ def initialize(owner)
34
+ @owner = owner
46
35
  end
47
36
 
48
- def sort!(options = {})
49
- sort({ :order => "DESC", :store => key }.merge(options)) # replaces itself with sorted list
50
- end
37
+ delegate :key, :key=, :push, :sort, :sort!, :insert_and_order, :bulk_push,
38
+ :remove, :remove_id, :remove_all, :ids, :activity_ids, :to => :store
51
39
 
52
- def sort(options = {})
53
- redis.sort(key, options)
54
- end
40
+ delegate :union, :intersect, :to => :store
55
41
 
56
- def sorted_push(activities)
57
- bulk_push(activities)
58
- sort!
42
+ def store
43
+ @store ||= self.class.store_type.new(key_to_store)
59
44
  end
60
- alias_method :insert_and_order, :sorted_push
61
45
 
62
46
  protected
63
47
 
64
- def redis
65
- @redis ||= Seymour.redis
66
- end
67
-
68
- def remove_all
69
- redis.del(key)
48
+ def key_to_store
49
+ "#{owner_name}:#{id_for_key}/#{feed_name}"
70
50
  end
71
51
 
72
52
  def owner_name
73
53
  owner.class.name
74
54
  end
75
55
 
76
- def key
77
- "#{owner.class.name}:#{id_for_key}/#{feed_name}"
78
- end
79
-
80
56
  def id_for_key
81
57
  owner.id
82
58
  end
@@ -85,17 +61,5 @@ module Seymour
85
61
  self.class.name.downcase
86
62
  end
87
63
 
88
- def max_size
89
- 100
90
- end
91
-
92
- def should_push?(activity)
93
- !activity_ids.include?(activity.id)
94
- end
95
-
96
- def perform_push(id)
97
- redis.lpush(key, id)
98
- redis.ltrim(key, 0, max_size)
99
- end
100
64
  end
101
65
  end
@@ -0,0 +1,20 @@
1
+ module Seymour
2
+ class Railtie < Rails::Railtie
3
+ config.app_generators.integration_tool :rspec
4
+ config.app_generators.test_framework :rspec
5
+
6
+ generators do
7
+ require 'generators/seymour/feed/feed_generator'
8
+ end
9
+
10
+ rake_tasks do
11
+ require 'seymour/tasks/seymour_tasks'
12
+ end
13
+
14
+ initializer "seymour.acts_as_activity" do
15
+ ActiveSupport.on_load :active_record do
16
+ include ActsAsActivity
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,12 +1,17 @@
1
1
  require 'redis-namespace'
2
2
 
3
3
  module Seymour
4
+
5
+ module Redis
6
+
7
+ end
8
+
4
9
  ## Courtesy of resque
5
10
  # Returns the current Redis connection. If none has been created, will
6
11
  # create a new one.
7
12
  def redis
8
13
  return @redis if @redis
9
- self.redis = Redis.respond_to?(:connect) ? Redis.connect : "localhost:6379"
14
+ self.redis = ::Redis.respond_to?(:connect) ? ::Redis.connect : "localhost:6379"
10
15
  self.redis
11
16
  end
12
17
 
@@ -21,20 +26,20 @@ module Seymour
21
26
  case server
22
27
  when String
23
28
  if server =~ /redis\:\/\//
24
- redis = Redis.connect(:url => server, :thread_safe => true)
29
+ redis = ::Redis.connect(:url => server, :thread_safe => true)
25
30
  else
26
31
  server, namespace = server.split('/', 2)
27
32
  host, port, db = server.split(':')
28
- redis = Redis.new(:host => host, :port => port,
33
+ redis = ::Redis.new(:host => host, :port => port,
29
34
  :thread_safe => true, :db => db)
30
35
  end
31
36
  namespace ||= :seymour
32
37
 
33
- @redis = Redis::Namespace.new(namespace, :redis => redis)
34
- when Redis::Namespace
38
+ @redis = ::Redis::Namespace.new(namespace, :redis => redis)
39
+ when ::Redis::Namespace
35
40
  @redis = server
36
41
  else
37
- @redis = Redis::Namespace.new(:seymour, :redis => server)
42
+ @redis = ::Redis::Namespace.new(:seymour, :redis => server)
38
43
  end
39
44
  end
40
45
  end
@@ -0,0 +1,7 @@
1
+ module Seymour
2
+ module Store
3
+ end
4
+ end
5
+ require 'seymour/store/base'
6
+ require 'seymour/store/list'
7
+ require 'seymour/store/zset'
@@ -0,0 +1,35 @@
1
+ module Seymour
2
+ module Store
3
+ class Base
4
+ attr_accessor :key
5
+
6
+ def initialize(key, options = {})
7
+ @key = key
8
+ @options = options
9
+ end
10
+
11
+ def redis
12
+ @redis ||= Seymour.redis
13
+ end
14
+
15
+ def activity_ids
16
+ ids
17
+ end
18
+
19
+ def max_size
20
+ 100
21
+ end
22
+
23
+ def bulk_push(activities)
24
+ activities.each do |activity|
25
+ push(activity)
26
+ end
27
+ end
28
+
29
+ def remove(activity)
30
+ remove_id(activity.id)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,104 @@
1
+ module Seymour
2
+ module Store
3
+ class List < Seymour::Store::Base
4
+
5
+ def ids
6
+ redis.lrange(key, 0, max_size).map(&:to_i)
7
+ end
8
+
9
+ def push(activity)
10
+ perform_push(activity.id) if should_push?(activity)
11
+ end
12
+
13
+ def remove_id(id)
14
+ redis.lrem(key, 0, id)
15
+ end
16
+
17
+ def remove_all
18
+ redis.del(key)
19
+ end
20
+
21
+ def sort!(options = {})
22
+ sort({ :order => "DESC", :store => key }.merge(options)) # replaces itself with sorted list
23
+ end
24
+
25
+ def sort(options = {})
26
+ redis.sort(key, options)
27
+ end
28
+
29
+ def sorted_push(activities)
30
+ bulk_push(activities)
31
+ sort!
32
+ end
33
+ alias_method :insert_and_order, :sorted_push
34
+
35
+ private
36
+
37
+ def perform_push(id)
38
+ redis.lpush(key, id)
39
+ redis.ltrim(key, 0, max_size)
40
+ end
41
+
42
+ def should_push?(activity)
43
+ !activity_ids.include?(activity.id)
44
+ end
45
+
46
+ # def llen
47
+ # redis.llen(@key)
48
+ # end
49
+ #
50
+ # def rpop
51
+ # redis.rpop(@key)
52
+ # end
53
+ #
54
+ # def rpoplpush(destination)
55
+ # if destination.is_a?(RedisList)
56
+ # redis.rpoplpush(@key, destination.key)
57
+ # destination.trim_to_max_size
58
+ # else
59
+ # redis.rpoplpush(@key, destination)
60
+ # end
61
+ # end
62
+ #
63
+ # def lpush(val)
64
+ # redis.lpush(@key, val)
65
+ # trim_to_max_size
66
+ # end
67
+ #
68
+ # def push_multi(elements)
69
+ # redis.pipelined do
70
+ # elements.each { |element| redis.rpush(@key, element) }
71
+ # end
72
+ # end
73
+ #
74
+ # def lrange(start_index, end_index)
75
+ # arr = redis.lrange(@key, start_index, end_index)
76
+ # typecast arr
77
+ # end
78
+ #
79
+ # def all
80
+ # lrange(0, -1)
81
+ # end
82
+ #
83
+ # def ltrim(start_index, end_index)
84
+ # redis.ltrim(@key, start_index, end_index)
85
+ # rescue => ex
86
+ # raise unless ex.message =~ /no such key/
87
+ # end
88
+ #
89
+ # def trim_to_max_size
90
+ # if max_size
91
+ # redis.ltrim(@key, 0, max_size - 1)
92
+ # end
93
+ # end
94
+ #
95
+ # def lrem(value, count = 1)
96
+ # redis.lrem(@key, count, value)
97
+ # end
98
+ #
99
+ # def max_size
100
+ # @options[:max_size]
101
+ # end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,75 @@
1
+ module Seymour
2
+ module Store
3
+ class Zset < Seymour::Store::Base
4
+
5
+ def push(activity, score = activity.score)
6
+ redis.zadd(key, score, activity.id)
7
+ end
8
+
9
+ def ids
10
+ redis.zrevrange(key, 0, max_size).map(&:to_i)
11
+ end
12
+
13
+ def remove_id(id)
14
+ redis.zrem(key, id)
15
+ end
16
+
17
+ def union_keys(keys, options = {})
18
+ redis.zunionstore key, keys, options
19
+ end
20
+
21
+ def union(feeds, options = { :exclude_options => true })
22
+ redis.zunionstore key, feeds.map(&:key), options
23
+ end
24
+
25
+ def intersect(feeds, options = {})
26
+ redis.zinterstore key, feeds.map(&:key), options
27
+ end
28
+
29
+ # def zadd(score, member)
30
+ # redis.zadd(@key, score, member)
31
+ # end
32
+
33
+ # def zrange(range_start, range_end)
34
+ # typecast redis.zrange(@key, range_start, range_end)
35
+ # end
36
+ #
37
+ # def zrem(member)
38
+ # redis.zrem(@key, member)
39
+ # end
40
+ #
41
+ # def zincrby(increment, member)
42
+ # redis.zincrby(@key, increment, member)
43
+ # end
44
+ #
45
+ # def zincr(member)
46
+ # zincrby(1, member)
47
+ # end
48
+ #
49
+ # def zrevrange(range_start, range_end)
50
+ # typecast redis.zrevrange(@key, range_start, range_end)
51
+ # end
52
+ #
53
+ # def zrangebyscore(min, max)
54
+ # typecast redis.zrangebyscore(@key, min, max)
55
+ # end
56
+ #
57
+ # def zcard
58
+ # redis.zcard(@key)
59
+ # end
60
+ #
61
+ # def zscore(member)
62
+ # redis.zscore(@key, member).to_f
63
+ # end
64
+ #
65
+ # def zremrangebyscore(min, max)
66
+ # redis.zremrangebyscore(@key, min, max)
67
+ # end
68
+ #
69
+ # def zremrangebyrank(start, _end)
70
+ # redis.zremrangebyrank(@key, start, _end)
71
+ # end
72
+
73
+ end
74
+ end
75
+ end