seymour 0.0.7 → 0.0.8

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