rediline 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,3 @@
1
1
  .DS_Store
2
2
  .bundle/
3
-
3
+ pkg/*
data/Gemfile CHANGED
@@ -4,8 +4,12 @@ gem "redis", '2.0.7'
4
4
  gem "redis-namespace", '0.10.0'
5
5
  gem "json"
6
6
  gem "i18n"
7
- gem "activesupport", "~> 3.0.0"
8
- gem "activemodel", '~> 3.0.0'
7
+
8
+ #
9
+ # About the version required there, please see the "compatibility" section in the README
10
+ #
11
+ gem "activesupport", ">= 2"
12
+ gem "activemodel", "~> 3.0"
9
13
 
10
14
  group :development do
11
15
  gem "jeweler"
@@ -50,8 +50,8 @@ PLATFORMS
50
50
  ruby
51
51
 
52
52
  DEPENDENCIES
53
- activemodel (~> 3.0.0)
54
- activesupport (~> 3.0.0)
53
+ activemodel (~> 3.0)
54
+ activesupport (>= 2)
55
55
  i18n
56
56
  jeweler
57
57
  json
data/README.md CHANGED
@@ -3,6 +3,28 @@
3
3
 
4
4
  Rediline is a ruby library which intends to allow you to create timelines for your users in ruby.
5
5
 
6
+ ## Compatibility
7
+
8
+ Rediling has been built with the idea to make it compatible with any other ORM possible.
9
+ Whether your users and objects are in SQL, MongoDB, CouchDB or anything else, you should be able to use it.
10
+
11
+ There are several requirements though.
12
+
13
+ * The ORM should provide an ActiveModel::Calbacks similar API (most ORM depends of it anyway)
14
+ * The ORM should provide a #find method to query the objects (if it does not, you can use [complex queries](http://github.com/dmathieu/rediline/wiki/Complex-queries-to-get-an-object) though).
15
+
16
+ You should also be able to use Rediling in a non-rails application. Sinatra for example.
17
+ There are be dependencies to ActiveSupport and ActiveModel though.
18
+
19
+ ### Rails 2 and Rails 3
20
+
21
+ As we're using ActiveSupport (mainly for #constantize), there were some problems with the version of the gem we're using.
22
+
23
+ Currently, ActiveSupport is required on a very permissive way (>= 2). That's intended to allow you to run rediline on a Rails2 application.
24
+
25
+ Moreover, we're using ActiveModel for the callbacks. And it requires ActiveSupport 3.0.
26
+ So for now, there's no dependency to ActiveModel. But you must know that you need your models to behave correctly with it in order to have rediline to work.
27
+
6
28
  ## Installation
7
29
 
8
30
  Add the following to your Gemfile :
@@ -49,7 +71,7 @@ And a "public" one, which will contain all the actions made by this user's frien
49
71
 
50
72
  You can retrieve a list's actions with the each method.
51
73
 
52
- User.first.timeline.each(:egocentric) do |action|
74
+ User.first.timeline.limit(10).each(:egocentric) do |action|
53
75
  p action.inspect
54
76
  end
55
77
 
@@ -92,7 +114,7 @@ Rediline has a redis setter which can be given a string or a Redis object.
92
114
  This means if you're already using Redis in your app, Rediline can re-use the existing connection.
93
115
 
94
116
  String: `Rediline.redis = 'localhost:6379'`
95
- Redis: `Resque.redis = $redis`
117
+ Redis: `Rediline.redis = $redis`
96
118
 
97
119
  In a rails app, I have an initializer in `config/initializers/rediline.rb` where I load `config/rediline.yml` and set the redis information appropriately.
98
120
 
data/Rakefile CHANGED
@@ -27,7 +27,12 @@ begin
27
27
  gemspec.add_dependency "redis-namespace", '0.10.0'
28
28
  gemspec.add_dependency "json"
29
29
  gemspec.add_dependency "i18n"
30
- gemspec.add_dependency "activesupport", "3.0.0"
30
+
31
+ #
32
+ # About the version required there, please see the "compatibility" section in the README
33
+ #
34
+ gemspec.add_dependency "activesupport", ">= 2"
35
+ #gemspec.add_dependency "activemodel", "~> 3.0"
31
36
  end
32
37
  rescue LoadError
33
38
  puts "Jeweler not available. Install it with: gem install jeweler"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -4,10 +4,10 @@ require 'active_support/core_ext'
4
4
  module Rediline
5
5
 
6
6
  class Entry
7
- attr_reader :content
7
+ attr_reader :content, :queries
8
8
 
9
- def initialize(content)
10
- @content = parse(content)
9
+ def initialize(content, queries={})
10
+ @content, @queries = parse(content), queries
11
11
  @objects = {}
12
12
  end
13
13
 
@@ -18,7 +18,7 @@ module Rediline
18
18
  def method_missing(name, *args)
19
19
  return content[name] if content.include?(name)
20
20
  if content.include?(:"#{name}_object") && content.include?(:"#{name}_object")
21
- return @objects[name] ||= content[:"#{name}_object"].constantize.find(content[:"#{name}_id"])
21
+ return @objects[name] ||= find_query(name, content[:"#{name}_id"])
22
22
  end
23
23
  super
24
24
  end
@@ -33,12 +33,14 @@ module Rediline
33
33
  def parse(string)
34
34
  if string.is_a?(String)
35
35
  string = JSON.parse(string).symbolize_keys
36
+ string.delete :queries
36
37
 
37
38
  [:user_id, :user_object, :object_id, :object_object, :verb].each do |f|
38
39
  raise "invalid content : missing field #{f}" if string[f].nil?
39
40
  end
40
41
  else
41
42
  string.symbolize_keys!
43
+ string.delete :queries
42
44
 
43
45
  [:user, :object, :verb].each do |f|
44
46
  raise "invalid content : missing field #{f}" if string[f].nil?
@@ -61,5 +63,13 @@ module Rediline
61
63
  end
62
64
  string
63
65
  end
66
+
67
+ def find_query(name, id)
68
+ if queries.nil? or queries[name].nil?
69
+ return content[:"#{name}_object"].constantize.find(id)
70
+ else
71
+ return queries[name].call(self, id)
72
+ end
73
+ end
64
74
  end
65
75
  end
@@ -26,7 +26,7 @@ module Rediline
26
26
 
27
27
  define_method "rediline_#{callback}" do
28
28
  if attrs.frozen?
29
- entry = Rediline::Entry.new(attrs.dup)
29
+ entry = Rediline::Entry.new(attrs.dup, attrs[:queries])
30
30
  else
31
31
  attrs[:object] = self
32
32
  case attrs[:user]
@@ -38,7 +38,7 @@ module Rediline
38
38
  attrs[:user] = send(:user)
39
39
  end
40
40
  attrs.freeze
41
- entry = Rediline::Entry.new(attrs.dup)
41
+ entry = Rediline::Entry.new(attrs.dup, attrs[:queries])
42
42
  end
43
43
 
44
44
  entry.user.send(field_name).lists.each_pair do |k, v|
@@ -6,16 +6,24 @@ module Rediline
6
6
  def initialize(field_name, user, block)
7
7
  @field_name, @user, @block = field_name, user
8
8
  @lists = {}
9
+ @limit, @start_at = 10, 0
9
10
  instance_eval(&block)
10
11
  end
11
12
 
12
13
  def each(type)
13
14
  raise "you must provide a block" unless block_given?
14
- (0..count(type)-1).each do |i|
15
+ (@start_at..@limit).each do |i|
15
16
  data = Rediline.redis.lindex(key(type), i)
17
+ next if data.nil?
16
18
  yield Rediline::Entry.new(data)
17
19
  end
18
20
  end
21
+
22
+ def destroy
23
+ lists.each do |l|
24
+ Rediline.redis.del key(l)
25
+ end
26
+ end
19
27
 
20
28
  def to_a(type)
21
29
  result = Array.new
@@ -33,6 +41,16 @@ module Rediline
33
41
  @lists[name] = instance_eval(&block)
34
42
  end
35
43
 
44
+ def limit(count)
45
+ @limit = count
46
+ self
47
+ end
48
+
49
+ def start_at(count)
50
+ @start_at = count
51
+ self
52
+ end
53
+
36
54
  private
37
55
  def key(type)
38
56
  "#{field_name.to_s}:#{@user.class.to_s}.#{@user.id.to_s}:#{type}"
@@ -9,6 +9,11 @@ module Rediline
9
9
  define_method field_name.to_sym do
10
10
  Rediline::Timeline::User.new(field_name.to_sym, self, block)
11
11
  end
12
+
13
+ private
14
+ define_method "delete_rediline_#{field_name}" do
15
+ send(field_name).destroy
16
+ end
12
17
  end
13
18
  end
14
19
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rediline}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Damien MATHIEU"]
12
- s.date = %q{2010-09-23}
12
+ s.date = %q{2010-09-29}
13
13
  s.description = %q{Timeline library}
14
14
  s.email = %q{42@dmathieu.com}
15
15
  s.extra_rdoc_files = [
@@ -70,20 +70,20 @@ Gem::Specification.new do |s|
70
70
  s.add_runtime_dependency(%q<redis-namespace>, ["= 0.10.0"])
71
71
  s.add_runtime_dependency(%q<json>, [">= 0"])
72
72
  s.add_runtime_dependency(%q<i18n>, [">= 0"])
73
- s.add_runtime_dependency(%q<activesupport>, ["= 3.0.0"])
73
+ s.add_runtime_dependency(%q<activesupport>, [">= 2"])
74
74
  else
75
75
  s.add_dependency(%q<redis>, ["= 2.0.7"])
76
76
  s.add_dependency(%q<redis-namespace>, ["= 0.10.0"])
77
77
  s.add_dependency(%q<json>, [">= 0"])
78
78
  s.add_dependency(%q<i18n>, [">= 0"])
79
- s.add_dependency(%q<activesupport>, ["= 3.0.0"])
79
+ s.add_dependency(%q<activesupport>, [">= 2"])
80
80
  end
81
81
  else
82
82
  s.add_dependency(%q<redis>, ["= 2.0.7"])
83
83
  s.add_dependency(%q<redis-namespace>, ["= 0.10.0"])
84
84
  s.add_dependency(%q<json>, [">= 0"])
85
85
  s.add_dependency(%q<i18n>, [">= 0"])
86
- s.add_dependency(%q<activesupport>, ["= 3.0.0"])
86
+ s.add_dependency(%q<activesupport>, [">= 2"])
87
87
  end
88
88
  end
89
89
 
@@ -37,6 +37,13 @@ describe Rediline::Entry do
37
37
  entry.content[o].should be_nil
38
38
  end
39
39
  end
40
+
41
+ it 'should not store the queries parameter' do
42
+ c = valid_json
43
+ c[:queries] = {}
44
+ entry = Rediline::Entry.new c.to_json
45
+ entry.content[:queries].should be_nil
46
+ end
40
47
  end
41
48
 
42
49
  describe 'when initializing with a hash' do
@@ -76,6 +83,13 @@ describe Rediline::Entry do
76
83
  entry = Rediline::Entry.new c
77
84
  entry.second_object.should eql(42)
78
85
  end
86
+
87
+ it 'should not store the queries parameter' do
88
+ c = valid_hash
89
+ c[:queries] = {}
90
+ entry = Rediline::Entry.new c
91
+ entry.content[:queries].should be_nil
92
+ end
79
93
  end
80
94
 
81
95
  describe 'creation date' do
@@ -107,6 +121,19 @@ describe Rediline::Entry do
107
121
  end
108
122
  end
109
123
 
124
+ describe 'queries' do
125
+ it 'should allow us to instantiate with a queries object' do
126
+ lambda do
127
+ Rediline::Entry.new valid_hash, { :object => lambda {|o, id| o.object.find(id) }}
128
+ end
129
+ end
130
+
131
+ it 'should execute the specified query' do
132
+ entry = Rediline::Entry.new valid_hash, { :object => lambda {|o, id| TestingTimelineObject.new(7) }}
133
+ entry.object.id.should eql(7)
134
+ end
135
+ end
136
+
110
137
  def valid_hash
111
138
  {
112
139
  :object => TestingTimelineObject.new(42),
@@ -10,6 +10,11 @@ class TestingTimelineObject
10
10
  rediline :timeline,
11
11
  :user => lambda {|o| o.user },
12
12
  :verb => :destroyed,
13
+ :queries => {
14
+ :object => lambda {|o, id|
15
+ TestingTimelineObject.new(id+1)
16
+ }
17
+ },
13
18
  :when => :before_destroy
14
19
 
15
20
  attr_reader :id, :user
@@ -1,5 +1,8 @@
1
1
  class User
2
+ extend ActiveModel::Callbacks
3
+ define_model_callbacks :create, :destroy
2
4
  include Rediline::User
5
+
3
6
  rediline :timeline do
4
7
  list :egocentric do
5
8
  [user]
@@ -17,4 +20,15 @@ class User
17
20
  def self.find(id)
18
21
  self.new(id)
19
22
  end
23
+
24
+ def create
25
+ _run_create_callbacks do
26
+ # Your create action methods here
27
+ end
28
+ end
29
+ def destroy
30
+ _run_destroy_callbacks do
31
+ # Your destroy action methods here
32
+ end
33
+ end
20
34
  end
@@ -37,6 +37,12 @@ describe Rediline::Timeline::User do
37
37
  end
38
38
  end
39
39
 
40
+ it 'should not fail if there are not enough entries' do
41
+ @timeline.limit(@timeline.count(:egocentric) + 1).each(:egocentric) do |entry|
42
+ entry.should be_kind_of(Rediline::Entry)
43
+ end
44
+ end
45
+
40
46
  [:object, :user].each do |o|
41
47
  it "should not have any #{o} in it\'s values" do
42
48
  @timeline.each(:egocentric) do |entry|
@@ -46,6 +52,18 @@ describe Rediline::Timeline::User do
46
52
  end
47
53
  end
48
54
 
55
+ describe 'destroy' do
56
+ it 'should destroy all the user\'s lists keys' do
57
+ Rediline.redis.expects(:del).twice
58
+ @timeline.destroy
59
+ end
60
+
61
+ it 'should destroy the timelines when destroying the user' do
62
+ Rediline.redis.expects(:del).twice
63
+ User.new(1).destroy
64
+ end
65
+ end
66
+
49
67
  describe 'to_a' do
50
68
  it 'should return an array' do
51
69
  @timeline.to_a(:egocentric).should be_kind_of(Array)
@@ -68,4 +86,34 @@ describe Rediline::Timeline::User do
68
86
  @timeline.send(:key, :egocentric).should eql('timeline:User.1:egocentric')
69
87
  end
70
88
  end
89
+
90
+ describe 'limit' do
91
+ it 'should default the limit to 10' do
92
+ @timeline.instance_eval('@limit').should eql(10)
93
+ end
94
+
95
+ it 'should redefine the limit' do
96
+ @timeline.limit(20)
97
+ @timeline.instance_eval('@limit').should eql(20)
98
+ end
99
+
100
+ it 'should return self' do
101
+ @timeline.limit(30).should eql(@timeline)
102
+ end
103
+ end
104
+
105
+ describe 'start_at' do
106
+ it 'should default the start_at to 0' do
107
+ @timeline.instance_eval('@start_at').should eql(0)
108
+ end
109
+
110
+ it 'should redefine the start_at' do
111
+ @timeline.start_at(20)
112
+ @timeline.instance_eval('@start_at').should eql(20)
113
+ end
114
+
115
+ it 'should return self' do
116
+ @timeline.start_at(30).should eql(@timeline)
117
+ end
118
+ end
71
119
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Damien MATHIEU
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-23 00:00:00 +02:00
17
+ date: 2010-09-29 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -78,13 +78,11 @@ dependencies:
78
78
  requirement: &id005 !ruby/object:Gem::Requirement
79
79
  none: false
80
80
  requirements:
81
- - - "="
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  segments:
84
- - 3
85
- - 0
86
- - 0
87
- version: 3.0.0
84
+ - 2
85
+ version: "2"
88
86
  type: :runtime
89
87
  prerelease: false
90
88
  version_requirements: *id005
@@ -137,7 +135,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
135
  requirements:
138
136
  - - ">="
139
137
  - !ruby/object:Gem::Version
140
- hash: 1586793397385962776
138
+ hash: 355954079675066628
141
139
  segments:
142
140
  - 0
143
141
  version: "0"