redis_storage 0.2.6 → 0.2.7
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/README +21 -3
- data/lib/redis_storage.rb +32 -15
- data/lib/redis_storage/version.rb +1 -1
- data/spec/model_spec.rb +33 -7
- metadata +14 -14
data/README
CHANGED
@@ -4,6 +4,7 @@ RedisStorage
|
|
4
4
|
This is a little gem which provides a redis interface for models. It works out of the box with rails or can be used standalone.
|
5
5
|
|
6
6
|
Basically I just got sick rewriting the same logic over and over again for each model of my little sinatra apps so this evolved. Then I wanted to write a new rails app an thought having this in a gem would be really nice, and a generator would be awesome.
|
7
|
+
Now I will add new Feature as I need them. You also can let me know what to add.
|
7
8
|
|
8
9
|
Features
|
9
10
|
---
|
@@ -13,20 +14,21 @@ Features
|
|
13
14
|
* compatible with the default rails controller
|
14
15
|
* uses ActiveModel to provide things like validations
|
15
16
|
* provides a Rails 3 Generator
|
17
|
+
* indexing of choosen attributes and find_by
|
16
18
|
|
17
19
|
Roadmap aka. ToDo
|
18
20
|
---
|
19
21
|
|
22
|
+
* perhaps use some stuff from redis-scripting to make more methods atomic (like find_by or update_attributes)
|
20
23
|
* some wrappers for searching in a model(probably will need some indexes)
|
21
|
-
* add something to make it easy to add an index(but there will be the update problematic)
|
22
24
|
* perhaps some kind of dirty flag - or the ActiveModel::Dirty module, but that will make some things way more complicated
|
23
25
|
* more tests/specs are always good
|
24
26
|
|
25
27
|
Newest Stuff
|
26
28
|
---
|
27
29
|
|
28
|
-
*
|
29
|
-
*
|
30
|
+
* indexing for choosen attributes
|
31
|
+
* new find_by :attr
|
30
32
|
|
31
33
|
Installation
|
32
34
|
---
|
@@ -77,6 +79,22 @@ Minimal Example
|
|
77
79
|
attr_accessor *attrs
|
78
80
|
end
|
79
81
|
|
82
|
+
Indexing and find_by
|
83
|
+
---
|
84
|
+
|
85
|
+
If you want or need to find records based on a attribute you have to add it to the index_for array like this.
|
86
|
+
|
87
|
+
def self.index_for
|
88
|
+
[:some, :attributes, :to, :index]
|
89
|
+
end
|
90
|
+
|
91
|
+
The elements should be symbols and have to also be element of attrs.
|
92
|
+
After that you can use the following to get the the instance.
|
93
|
+
|
94
|
+
MyModel.find_by :key, "search"
|
95
|
+
|
96
|
+
Also I should mention that you should update record only via the update_attributes method, otherwise the indexes will become corrupt.
|
97
|
+
|
80
98
|
Rails 3 Integration
|
81
99
|
---
|
82
100
|
|
data/lib/redis_storage.rb
CHANGED
@@ -19,6 +19,9 @@ module RedisStorage
|
|
19
19
|
attr_accessor :id
|
20
20
|
attr_reader :errors
|
21
21
|
|
22
|
+
def self.index_for
|
23
|
+
[]
|
24
|
+
end
|
22
25
|
def self.build(params)
|
23
26
|
new params
|
24
27
|
end
|
@@ -31,25 +34,27 @@ module RedisStorage
|
|
31
34
|
|
32
35
|
def self.random
|
33
36
|
i = $db.srandmember(persisted_key)
|
34
|
-
|
37
|
+
load(i) unless i.nil?
|
35
38
|
end
|
36
39
|
def self.find(params=nil)
|
37
40
|
if params.nil?
|
38
41
|
all
|
39
42
|
else
|
40
|
-
|
43
|
+
load(params) #TODO perhaps make this at some point more generic
|
41
44
|
end
|
42
45
|
end
|
43
|
-
def self.
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
def self.find_by(key, value)
|
47
|
+
if key == :id
|
48
|
+
load "#{db_key}:#{value}"
|
49
|
+
elsif index_for.include? key
|
50
|
+
load($db.get("#{db_key}:#{key}:#{value.hash}"))
|
51
|
+
else
|
52
|
+
nil
|
53
|
+
end
|
47
54
|
end
|
48
55
|
|
49
56
|
def self.all
|
50
|
-
keys = $db.smembers(persisted_key)
|
51
|
-
"#{db_key}:#{i}"
|
52
|
-
end
|
57
|
+
keys = $db.smembers(persisted_key)
|
53
58
|
|
54
59
|
if keys.empty?
|
55
60
|
[]
|
@@ -64,10 +69,10 @@ module RedisStorage
|
|
64
69
|
$db.scard(persisted_key)
|
65
70
|
end
|
66
71
|
def self.first
|
67
|
-
|
72
|
+
load $db.smembers(persisted_key).sort.first
|
68
73
|
end
|
69
74
|
def self.last
|
70
|
-
|
75
|
+
load $db.smembers(persisted_key).sort.last
|
71
76
|
end
|
72
77
|
def serializable_hash
|
73
78
|
self.class.attrs.inject({:id => @id}) do |a,key|
|
@@ -80,19 +85,23 @@ module RedisStorage
|
|
80
85
|
end
|
81
86
|
|
82
87
|
def update_attributes(params)
|
88
|
+
delete!
|
83
89
|
params.each do |key, value|
|
84
90
|
send("#{key}=", value) unless key.to_sym == :id
|
85
91
|
end
|
86
92
|
save
|
87
93
|
end
|
88
94
|
def save
|
89
|
-
|
95
|
+
if @id.nil?
|
90
96
|
@id = $db.incr(self.class.next_id_key)
|
91
97
|
end
|
92
98
|
if valid?
|
93
99
|
$db.multi do
|
94
100
|
$db.set db_key, to_json
|
95
|
-
$db.sadd self.class.persisted_key,
|
101
|
+
$db.sadd self.class.persisted_key, db_key
|
102
|
+
for key in self.class.index_for do
|
103
|
+
$db.set "#{self.class.db_key}:#{key}:#{send(key).hash}", db_key
|
104
|
+
end
|
96
105
|
end
|
97
106
|
@id
|
98
107
|
else
|
@@ -107,7 +116,10 @@ module RedisStorage
|
|
107
116
|
if persisted?
|
108
117
|
$db.multi do
|
109
118
|
$db.del db_key
|
110
|
-
$db.srem self.class.persisted_key,
|
119
|
+
$db.srem self.class.persisted_key, db_key
|
120
|
+
for key in self.class.index_for do
|
121
|
+
$db.del "#{self.class.db_key}:#{key}:#{send(key).hash}"
|
122
|
+
end
|
111
123
|
end
|
112
124
|
true
|
113
125
|
else
|
@@ -119,7 +131,7 @@ module RedisStorage
|
|
119
131
|
if id.nil?
|
120
132
|
false
|
121
133
|
else
|
122
|
-
$db.sismember(self.class.persisted_key,
|
134
|
+
$db.sismember(self.class.persisted_key, db_key)
|
123
135
|
end
|
124
136
|
end
|
125
137
|
|
@@ -141,6 +153,11 @@ module RedisStorage
|
|
141
153
|
end
|
142
154
|
end
|
143
155
|
private
|
156
|
+
def self.load(key)
|
157
|
+
return nil if key.nil?
|
158
|
+
r = $db.get(key)
|
159
|
+
new(JSON.parse(r)) unless r.nil?
|
160
|
+
end
|
144
161
|
def self.next_id_key
|
145
162
|
"#{db_key}:next_id"
|
146
163
|
end
|
data/spec/model_spec.rb
CHANGED
@@ -4,6 +4,9 @@ class MockModel < RedisStorage::Model
|
|
4
4
|
[:body, :title]
|
5
5
|
end
|
6
6
|
attr_accessor *attrs
|
7
|
+
def self.index_for
|
8
|
+
[:title]
|
9
|
+
end
|
7
10
|
end
|
8
11
|
|
9
12
|
describe RedisStorage::Model do
|
@@ -57,19 +60,42 @@ describe RedisStorage::Model do
|
|
57
60
|
MockModel.expects(:all)
|
58
61
|
MockModel.find
|
59
62
|
end
|
60
|
-
it 'should push the given
|
61
|
-
MockModel.expects(:
|
63
|
+
it 'should push the given params from .find to .load' do
|
64
|
+
MockModel.expects(:load).with(3)
|
62
65
|
MockModel.find(3)
|
63
66
|
end
|
64
|
-
context '#
|
67
|
+
context '#find_by' do
|
68
|
+
it "should call load if called find_by :id" do
|
69
|
+
MockModel.expects(:load)
|
70
|
+
MockModel.find_by(:id,3)
|
71
|
+
end
|
65
72
|
1.upto(4) do |i|
|
66
|
-
it "should find record #{i} and create a new instance" do
|
67
|
-
record = MockModel.
|
73
|
+
it "should find record #{i} by id, load it and create a new instance" do
|
74
|
+
record = MockModel.find_by :id, i
|
68
75
|
record.id.should == i
|
69
76
|
record.body.should == h[i-1]['body']
|
70
77
|
record.title.should == h[i-1]['title']
|
71
78
|
end
|
72
79
|
end
|
80
|
+
it 'should find instances based on their title' do
|
81
|
+
model = MockModel.find_by :title, "second test"
|
82
|
+
model.title.should eq("second test")
|
83
|
+
model.body.should eq("Dolor Sit")
|
84
|
+
end
|
85
|
+
it 'should still find by title after updating the title' do
|
86
|
+
m = MockModel.first
|
87
|
+
m.update_attributes({'title' => "f**k that title"})
|
88
|
+
n = MockModel.find_by :title, "f**k that title"
|
89
|
+
n.title.should == "f**k that title"
|
90
|
+
n.id.should == m.id
|
91
|
+
end
|
92
|
+
it 'should no longer find by the old title after updating the title' do
|
93
|
+
m = MockModel.first
|
94
|
+
t = m.title
|
95
|
+
m.update_attributes({'title' => "f**k that title"})
|
96
|
+
n = MockModel.find_by :title, t
|
97
|
+
n.should be_nil
|
98
|
+
end
|
73
99
|
end
|
74
100
|
context '#all' do
|
75
101
|
it 'should return an empty array if there are no entries' do
|
@@ -136,7 +162,7 @@ describe RedisStorage::Model do
|
|
136
162
|
end
|
137
163
|
it 'should add the id to the persisted set in redis' do
|
138
164
|
id = model.save
|
139
|
-
$db.sismember("MockModel:persisted", id).should be_true
|
165
|
+
$db.sismember("MockModel:persisted", "MockModel:#{id}").should be_true
|
140
166
|
end
|
141
167
|
end
|
142
168
|
context '#update_attributes' do
|
@@ -166,7 +192,7 @@ describe RedisStorage::Model do
|
|
166
192
|
it 'should remove the id from the persisted set in redis' do
|
167
193
|
id=model.save
|
168
194
|
model.delete!
|
169
|
-
$db.sismember("MockModel:persisted", id).should be_false
|
195
|
+
$db.sismember("MockModel:persisted", "MockModel:#{id}").should be_false
|
170
196
|
end
|
171
197
|
end
|
172
198
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_storage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-06-
|
12
|
+
date: 2011-06-30 00:00:00.000000000 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: redis
|
17
|
-
requirement: &
|
17
|
+
requirement: &13617920 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 2.2.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *13617920
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: json
|
28
|
-
requirement: &
|
28
|
+
requirement: &13655520 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *13655520
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: activemodel
|
39
|
-
requirement: &
|
39
|
+
requirement: &13654980 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 3.0.0
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *13654980
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: rspec
|
50
|
-
requirement: &
|
50
|
+
requirement: &13654480 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: 2.0.0
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *13654480
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: mocha
|
61
|
-
requirement: &
|
61
|
+
requirement: &13654020 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,10 +66,10 @@ dependencies:
|
|
66
66
|
version: 0.9.10
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *13654020
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rails
|
72
|
-
requirement: &
|
72
|
+
requirement: &13653560 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
@@ -77,7 +77,7 @@ dependencies:
|
|
77
77
|
version: 3.0.0
|
78
78
|
type: :development
|
79
79
|
prerelease: false
|
80
|
-
version_requirements: *
|
80
|
+
version_requirements: *13653560
|
81
81
|
description: Provides a data backend for a Redis in Rails, will also provide a Rails
|
82
82
|
3 Generator
|
83
83
|
email:
|