ricordami 0.0.1 → 0.0.2
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/CHANGELOG.md +5 -0
- data/README.md +57 -28
- data/examples/calls.rb +59 -14
- data/examples/person.rb +20 -0
- data/examples/singers.rb +6 -10
- data/examples/summary.rb +53 -0
- data/lib/ricordami/connection.rb +3 -3
- data/lib/ricordami/is_persisted.rb +19 -9
- data/lib/ricordami/version.rb +1 -1
- data/spec/ricordami/connection_spec.rb +3 -3
- data/spec/ricordami/is_persisted_spec.rb +4 -4
- data/spec/ricordami/model_spec.rb +3 -0
- data/spec/ricordami/unique_index_spec.rb +7 -7
- data/spec/ricordami/value_index_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- data/spec/support/db_manager.rb +2 -2
- metadata +14 -8
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -12,11 +12,12 @@ not ready for use yet.</div>
|
|
|
12
12
|
|
|
13
13
|
require "ricordami"
|
|
14
14
|
|
|
15
|
-
Ricordami::
|
|
15
|
+
Ricordami::configure do |config|
|
|
16
16
|
config.redis_host = "127.0.0.1"
|
|
17
17
|
config.redis_port = 6379
|
|
18
|
-
config.redis_db =
|
|
18
|
+
config.redis_db = 15
|
|
19
19
|
end
|
|
20
|
+
Ricordami.redis.flushdb
|
|
20
21
|
|
|
21
22
|
class Singer
|
|
22
23
|
include Ricordami::Model
|
|
@@ -36,8 +37,10 @@ not ready for use yet.</div>
|
|
|
36
37
|
|
|
37
38
|
model_can :be_queried, :have_relationships
|
|
38
39
|
|
|
39
|
-
attribute :title
|
|
40
|
-
attribute :year
|
|
40
|
+
attribute :title
|
|
41
|
+
attribute :year, :indexed => :value
|
|
42
|
+
|
|
43
|
+
index :unique => :title, :get_by => true
|
|
41
44
|
|
|
42
45
|
referenced_in :singer
|
|
43
46
|
end
|
|
@@ -45,7 +48,7 @@ not ready for use yet.</div>
|
|
|
45
48
|
serge = Singer.create :name => "Gainsbourg"
|
|
46
49
|
jetaime = serge.songs.create :title => "Je T'Aime Moi Non Plus", :year => "1967"
|
|
47
50
|
jetaime.year = "1968"
|
|
48
|
-
jetaime.changes # => {:year => ["1967", "1968"]}
|
|
51
|
+
p :changes, jetaime.changes # => {:year => ["1967", "1968"]}
|
|
49
52
|
jetaime.save
|
|
50
53
|
["La Javanaise", "Melody Nelson", "Love On The Beat"].each do |name|
|
|
51
54
|
serge.songs.create :title => name, :year => "1962"
|
|
@@ -53,8 +56,9 @@ not ready for use yet.</div>
|
|
|
53
56
|
Song.get_by_title("Melody Nelson").update_attributes(:year => "1971")
|
|
54
57
|
Song.get_by_title("Love On The Beat").update_attributes(:year => "1984")
|
|
55
58
|
|
|
56
|
-
Song.count # =>
|
|
57
|
-
|
|
59
|
+
p :count, Song.count # => 4
|
|
60
|
+
p :all, Song.all.map(&:title)
|
|
61
|
+
p :where, Song.where(:year => "1971").map(&:title) # => "Melody Nelson"
|
|
58
62
|
|
|
59
63
|
|
|
60
64
|
## How To Install? ##
|
|
@@ -94,13 +98,15 @@ source code:
|
|
|
94
98
|
Ricordami::Model.configure do |config|
|
|
95
99
|
config.redis_host = "redis.lab"
|
|
96
100
|
config.redis_port = 6379
|
|
101
|
+
config.redis_db = 0
|
|
97
102
|
config.thread_safe = true
|
|
98
103
|
end
|
|
99
104
|
|
|
100
105
|
Or using a hash:
|
|
101
106
|
|
|
102
107
|
Ricordami.configure do |config|
|
|
103
|
-
|
|
108
|
+
values = YAML.load(File.expand_path("../../config.yml"))
|
|
109
|
+
config.from_hash(values)
|
|
104
110
|
end
|
|
105
111
|
|
|
106
112
|
### Declare A Model ###
|
|
@@ -116,6 +122,24 @@ additional features using the class method **#model_can**.
|
|
|
116
122
|
:have_relationships
|
|
117
123
|
end
|
|
118
124
|
|
|
125
|
+
A model class has the following methods:
|
|
126
|
+
|
|
127
|
+
- *#get* - lookup an instance by id (i.e.: Singer.get(2))
|
|
128
|
+
- *#[]* - alias for *#get* (i.e.: Singer[2])
|
|
129
|
+
- *#all* - return all existing instances
|
|
130
|
+
- *#count* - return the number of existing instances
|
|
131
|
+
|
|
132
|
+
and a model instance the following expected instance methods:
|
|
133
|
+
|
|
134
|
+
- *#save*
|
|
135
|
+
- *#delete*
|
|
136
|
+
- *#update_attributes*
|
|
137
|
+
- *#reload*
|
|
138
|
+
|
|
139
|
+
Both class and instances have a shortcut access to the redis object
|
|
140
|
+
(that uses the *redis* gem).
|
|
141
|
+
|
|
142
|
+
|
|
119
143
|
### Declare Attributes ###
|
|
120
144
|
|
|
121
145
|
The model state is stored in attributes. Those attributes can be indexed
|
|
@@ -150,10 +174,10 @@ Example:
|
|
|
150
174
|
attribute :age, :type => :integer
|
|
151
175
|
end
|
|
152
176
|
|
|
153
|
-
zhanna = Person.create(:name => "Zhanna", :sex => "Female", :age => 29
|
|
154
|
-
zhanna.id
|
|
155
|
-
Person[
|
|
156
|
-
Person.
|
|
177
|
+
zhanna = Person.create(:name => "Zhanna", :sex => "Female", :age => 29)
|
|
178
|
+
p :id, zhanna.id # => "1"
|
|
179
|
+
p :[], Person["1"].name # => "Zhanna"
|
|
180
|
+
p :get, Person.get("1").name # => "Zhanna"
|
|
157
181
|
|
|
158
182
|
Methods:
|
|
159
183
|
|
|
@@ -256,12 +280,14 @@ Better go with an example to make it all clear:
|
|
|
256
280
|
osez = bashung.songs.build(:title => "Osez Josephine")
|
|
257
281
|
osez.save
|
|
258
282
|
gaby = bashung.songs.create(:title => "Vertiges de l'Amour")
|
|
259
|
-
bashung.songs.map(&:title) # => ["Osez Josephine", "Vertiges de l'Amour"]
|
|
260
|
-
gaby.singer_id == bashung.id # => true
|
|
283
|
+
p :songs, bashung.songs.map(&:title) # => ["Osez Josephine", "Vertiges de l'Amour"]
|
|
284
|
+
p :singer_id, gaby.singer_id == bashung.id # => true
|
|
261
285
|
|
|
262
286
|
padam = Song.create(:title => "Padam")
|
|
263
|
-
|
|
264
|
-
benjamin.
|
|
287
|
+
p :padam, padam
|
|
288
|
+
benjamin = padam.build_singer(:name => "Benjamin Biolay")
|
|
289
|
+
p :benjamin, benjamin
|
|
290
|
+
p :songs, benjamin.songs.map(&:title) # => "Padam"
|
|
265
291
|
|
|
266
292
|
The class methods **#references_many**, **#references_one** and
|
|
267
293
|
**#referenced_by** can take the following options:
|
|
@@ -335,27 +361,30 @@ of an operator among AT&T, Qwest and Level3.
|
|
|
335
361
|
attribute :dnis, :indexed => :value
|
|
336
362
|
attribute :call_type, :indexed => :value
|
|
337
363
|
attribute :network, :indexed => :value
|
|
338
|
-
attribute :seconds,
|
|
364
|
+
attribute :seconds, :type => :integer
|
|
339
365
|
|
|
340
|
-
referenced_in :tenant, :as owner
|
|
366
|
+
referenced_in :tenant, :as => :owner
|
|
341
367
|
|
|
342
368
|
validates_presence_of :call_type, :seconds, :owner_id
|
|
343
369
|
validates_inclusion_of :call_type, :in => ["pots", "voip"]
|
|
344
370
|
validates_inclusion_of :network, :in => ["att", "qwest", "level3"]
|
|
345
371
|
end
|
|
346
372
|
|
|
347
|
-
#
|
|
348
|
-
# the phone number 650 123 4567?
|
|
349
|
-
Call.where(:ani => "6501234567").inject(0) { |sum, call| sum + call.seconds }
|
|
373
|
+
# ...create tenant and calls...
|
|
350
374
|
|
|
351
|
-
#
|
|
352
|
-
Call.where(:
|
|
375
|
+
# What is the total number of seconds of the phone calls made from the phone number 650 123 4567?
|
|
376
|
+
seconds = Call.where(:ani => "6501234567").inject(0) { |sum, call| sum + call.seconds }
|
|
377
|
+
puts " => seconds = #{seconds}"
|
|
353
378
|
|
|
354
|
-
#
|
|
355
|
-
|
|
356
|
-
|
|
379
|
+
# What are the VoIP calls that didn't go through Level3 network?
|
|
380
|
+
calls = Call.where(:call_type => "voip").not(:network => "level3")
|
|
381
|
+
puts " => #{calls.inspect}"
|
|
382
|
+
|
|
383
|
+
# What are the calls for tenant "mycompany" that went through AT&T's network or originated from ANI 408 123 4567? but were not VoIP calls?
|
|
357
384
|
mycompany = Tenant.get_by_name("mycompany")
|
|
358
|
-
mycompany.calls.any(:ani => "4081234567", :network => "att").not(:call_type => "voip")
|
|
385
|
+
calls = mycompany.calls.any(:ani => "4081234567", :network => "att").not(:call_type => "voip")
|
|
386
|
+
puts " => #{calls.count} calls"
|
|
387
|
+
puts " => first page of 10: #{calls.paginate(:page => 1, :per_page => 10).inspect}"
|
|
359
388
|
|
|
360
389
|
|
|
361
390
|
## How To Run Specs ##
|
|
@@ -382,8 +411,8 @@ Ruby Enterprise:
|
|
|
382
411
|
$ rvm install ree-1.8.7-2011.03 # install if necessary
|
|
383
412
|
$ rvm use ree-1.8.7-2011.03
|
|
384
413
|
$ rvm gemset create ricordami
|
|
385
|
-
$ gem install bundler --no-ri --no-rdoc
|
|
386
414
|
$ rvm gemset use ricordami
|
|
415
|
+
$ gem install bundler --no-ri --no-rdoc
|
|
387
416
|
$ bundle
|
|
388
417
|
|
|
389
418
|
Rubinius:
|
data/examples/calls.rb
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
|
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
|
3
3
|
|
|
4
|
+
require "pp"
|
|
4
5
|
require "rubygems"
|
|
5
6
|
require "ricordami"
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
module ValueGenerator
|
|
9
|
+
extend self
|
|
10
|
+
|
|
11
|
+
CALL_TYPES = ["pots", "voip"]
|
|
12
|
+
NETWORKS = ["att", "qwest", "level3"]
|
|
13
|
+
|
|
14
|
+
def phone_number
|
|
15
|
+
"xxxxxxxxxx".split('').map { rand(10) }.join
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def call_type
|
|
19
|
+
CALL_TYPES[rand(CALL_TYPES.length)]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def networks
|
|
23
|
+
NETWORKS[rand(NETWORKS.length)]
|
|
24
|
+
end
|
|
11
25
|
end
|
|
12
|
-
|
|
26
|
+
|
|
27
|
+
Ricordami.redis.select(15)
|
|
28
|
+
Ricordami.redis.flushdb
|
|
13
29
|
|
|
14
30
|
class Tenant
|
|
15
31
|
include Ricordami::Model
|
|
@@ -41,18 +57,46 @@ class Call
|
|
|
41
57
|
validates_inclusion_of :network, :in => ["att", "qwest", "level3"]
|
|
42
58
|
end
|
|
43
59
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
tenants = %w(mycompany blah foo bar sowhat hereitgoesagain).map { |name| Tenant.create(:name => name) }
|
|
61
|
+
|
|
62
|
+
12.times do |i|
|
|
63
|
+
t = tenants[rand(tenants.length)]
|
|
64
|
+
t.calls.create(:ani => "6501234567",
|
|
65
|
+
:dnis => ValueGenerator.phone_number,
|
|
66
|
+
:call_type => ValueGenerator.call_type,
|
|
67
|
+
:network => ValueGenerator.networks,
|
|
68
|
+
:seconds => 10 * i)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
123.times do |i|
|
|
72
|
+
t = tenants[rand(tenants.length)]
|
|
73
|
+
t.calls.create(:ani => ValueGenerator.phone_number,
|
|
74
|
+
:dnis => ValueGenerator.phone_number,
|
|
75
|
+
:call_type => "voip",
|
|
76
|
+
:network => "level3",
|
|
77
|
+
:seconds => 10 + rand(3600))
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
t = tenants[rand(tenants.length)]
|
|
81
|
+
t.calls.create(:ani => "you-found@me", :dnis => "911", :call_type => "voip", :network => "qwest", :seconds => 42)
|
|
82
|
+
|
|
83
|
+
50.times do |i|
|
|
84
|
+
t = tenants.first
|
|
85
|
+
t.calls.create(:ani => "4081234567",
|
|
86
|
+
:dnis => ValueGenerator.phone_number,
|
|
87
|
+
:call_type => "pots",
|
|
88
|
+
:network => "att",
|
|
89
|
+
:seconds => 10 + rand(3600))
|
|
90
|
+
end
|
|
47
91
|
|
|
48
92
|
puts <<EOC
|
|
49
93
|
?? What is the total number of seconds of the phone calls made from the phone number 650 123 4567?
|
|
50
94
|
EOC
|
|
51
95
|
seconds = Call.where(:ani => "6501234567").inject(0) { |sum, call| sum + call.seconds }
|
|
52
|
-
puts " => seconds = #{seconds}"
|
|
96
|
+
puts " => seconds = #{seconds} (should be 780)"
|
|
53
97
|
|
|
54
|
-
puts "?? What are the VoIP calls that didn't go through Level3 network?"
|
|
55
|
-
calls = Call.where(:call_type => "voip").not(:network => "level3")
|
|
98
|
+
puts "?? What are the VoIP calls from ani 'you-found@me' that didn't go through Level3 network?"
|
|
99
|
+
calls = Call.where(:call_type => "voip", :ani => "you-found@me").not(:network => "level3").all
|
|
56
100
|
puts " => #{calls.inspect}"
|
|
57
101
|
|
|
58
102
|
puts <<EOC
|
|
@@ -60,5 +104,6 @@ puts <<EOC
|
|
|
60
104
|
EOC
|
|
61
105
|
mycompany = Tenant.get_by_name("mycompany")
|
|
62
106
|
calls = mycompany.calls.any(:ani => "4081234567", :network => "att").not(:call_type => "voip")
|
|
63
|
-
puts " => #{calls.count} calls"
|
|
64
|
-
puts " => first page of 10:
|
|
107
|
+
puts " => #{calls.count} calls (should be 50)"
|
|
108
|
+
puts " => first page of 10:"
|
|
109
|
+
pp calls.paginate(:page => 1, :per_page => 10)
|
data/examples/person.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
|
3
|
+
|
|
4
|
+
require "rubygems"
|
|
5
|
+
require "ricordami"
|
|
6
|
+
|
|
7
|
+
Ricordami.redis.select(15)
|
|
8
|
+
Ricordami.redis.flushdb
|
|
9
|
+
|
|
10
|
+
class Person
|
|
11
|
+
include Ricordami::Model
|
|
12
|
+
attribute :name, :default => "First name, Last name"
|
|
13
|
+
attribute :sex, :indexed => :value
|
|
14
|
+
attribute :age, :type => :integer
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
zhanna = Person.create(:name => "Zhanna", :sex => "Female", :age => 29)
|
|
18
|
+
p :id, zhanna.id # => "1"
|
|
19
|
+
p :[], Person[1].name # => "Zhanna"
|
|
20
|
+
p :get, Person.get(1).name # => "Zhanna"
|
data/examples/singers.rb
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
|
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
|
3
3
|
|
|
4
4
|
require "rubygems"
|
|
5
5
|
require "ricordami"
|
|
6
6
|
|
|
7
|
-
Ricordami.
|
|
8
|
-
|
|
9
|
-
config.redis_port = 6379
|
|
10
|
-
config.redis_db = 0
|
|
11
|
-
end
|
|
12
|
-
Ricordami.driver.flushdb
|
|
7
|
+
Ricordami.redis.select(15)
|
|
8
|
+
Ricordami.redis.flushdb
|
|
13
9
|
|
|
14
10
|
class Singer
|
|
15
11
|
include Ricordami::Model
|
|
@@ -32,11 +28,11 @@ bashung.songs # => []
|
|
|
32
28
|
osez = bashung.songs.build(:title => "Osez Josephine")
|
|
33
29
|
osez.save
|
|
34
30
|
gaby = bashung.songs.create(:title => "Vertiges de l'Amour")
|
|
35
|
-
p bashung.songs.map(&:title) # => ["Osez Josephine", "Vertiges de l'Amour"]
|
|
36
|
-
p gaby.singer_id == bashung.id # => true
|
|
31
|
+
p :songs, bashung.songs.map(&:title) # => ["Osez Josephine", "Vertiges de l'Amour"]
|
|
32
|
+
p :singer_id, gaby.singer_id == bashung.id # => true
|
|
37
33
|
|
|
38
34
|
padam = Song.create(:title => "Padam")
|
|
39
35
|
p :padam, padam
|
|
40
36
|
benjamin = padam.build_singer(:name => "Benjamin Biolay")
|
|
41
37
|
p :benjamin, benjamin
|
|
42
|
-
p benjamin.songs.map(&:title) # => "Padam"
|
|
38
|
+
p :songs, benjamin.songs.map(&:title) # => "Padam"
|
data/examples/summary.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
|
3
|
+
|
|
4
|
+
require "rubygems"
|
|
5
|
+
require "ricordami"
|
|
6
|
+
|
|
7
|
+
Ricordami::configure do |config|
|
|
8
|
+
config.redis_host = "127.0.0.1"
|
|
9
|
+
config.redis_port = 6379
|
|
10
|
+
config.redis_db = 15
|
|
11
|
+
end
|
|
12
|
+
Ricordami.redis.flushdb
|
|
13
|
+
|
|
14
|
+
class Singer
|
|
15
|
+
include Ricordami::Model
|
|
16
|
+
|
|
17
|
+
model_can :be_validated, :have_relationships
|
|
18
|
+
|
|
19
|
+
attribute :name
|
|
20
|
+
|
|
21
|
+
validates_presence_of :name
|
|
22
|
+
validates_uniqueness_of :name
|
|
23
|
+
|
|
24
|
+
references_many :songs
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Song
|
|
28
|
+
include Ricordami::Model
|
|
29
|
+
|
|
30
|
+
model_can :be_queried, :have_relationships
|
|
31
|
+
|
|
32
|
+
attribute :title
|
|
33
|
+
attribute :year, :indexed => :value
|
|
34
|
+
|
|
35
|
+
index :unique => :title, :get_by => true
|
|
36
|
+
|
|
37
|
+
referenced_in :singer
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
serge = Singer.create :name => "Gainsbourg"
|
|
41
|
+
jetaime = serge.songs.create :title => "Je T'Aime Moi Non Plus", :year => "1967"
|
|
42
|
+
jetaime.year = "1968"
|
|
43
|
+
p :changes, jetaime.changes # => {:year => ["1967", "1968"]}
|
|
44
|
+
jetaime.save
|
|
45
|
+
["La Javanaise", "Melody Nelson", "Love On The Beat"].each do |name|
|
|
46
|
+
serge.songs.create :title => name, :year => "1962"
|
|
47
|
+
end
|
|
48
|
+
Song.get_by_title("Melody Nelson").update_attributes(:year => "1971")
|
|
49
|
+
Song.get_by_title("Love On The Beat").update_attributes(:year => "1984")
|
|
50
|
+
|
|
51
|
+
p :count, Song.count # => 4
|
|
52
|
+
p :all, Song.all.map(&:title)
|
|
53
|
+
p :where, Song.where(:year => "1971").map(&:title) # => "Melody Nelson"
|
data/lib/ricordami/connection.rb
CHANGED
|
@@ -3,13 +3,13 @@ module Ricordami
|
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
5
|
module ClassMethods
|
|
6
|
-
def
|
|
7
|
-
@
|
|
6
|
+
def redis
|
|
7
|
+
@redis ||= create_redis
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
private
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def create_redis
|
|
13
13
|
c = self.configuration
|
|
14
14
|
Redis.new(:host => c.redis_host,
|
|
15
15
|
:port => c.redis_port,
|
|
@@ -29,7 +29,7 @@ module Ricordami
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def redis
|
|
32
|
-
@redis ||= Ricordami.
|
|
32
|
+
@redis ||= Ricordami.redis
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -55,12 +55,12 @@ module Ricordami
|
|
|
55
55
|
def save(opts = {})
|
|
56
56
|
raise ModelHasBeenDeleted.new("can't save a deleted model") if deleted?
|
|
57
57
|
set_initial_attribute_values if new_record?
|
|
58
|
-
redis.tap do |
|
|
58
|
+
redis.tap do |redis|
|
|
59
59
|
session = {}
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
redis.multi
|
|
61
|
+
redis.hmset(attributes_key_name, *attributes.to_a.flatten)
|
|
62
62
|
self.class.save_queue.each { |block| block.call(self, session) } if self.class.save_queue
|
|
63
|
-
|
|
63
|
+
redis.exec
|
|
64
64
|
end
|
|
65
65
|
@persisted = true
|
|
66
66
|
attributes_synced_with_db!
|
|
@@ -99,12 +99,12 @@ module Ricordami
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def execute_delete(db_commands)
|
|
102
|
-
redis.tap do |
|
|
103
|
-
|
|
102
|
+
redis.tap do |redis|
|
|
103
|
+
redis.multi
|
|
104
104
|
db_commands.each do |message, args|
|
|
105
|
-
|
|
105
|
+
redis.send(message, *args)
|
|
106
106
|
end
|
|
107
|
-
|
|
107
|
+
redis.exec
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
|
|
@@ -118,6 +118,16 @@ module Ricordami
|
|
|
118
118
|
def redis
|
|
119
119
|
self.class.redis
|
|
120
120
|
end
|
|
121
|
+
|
|
122
|
+
def to_s
|
|
123
|
+
[
|
|
124
|
+
"#<#{self.class}:0x#{object_id.to_s(16)}",
|
|
125
|
+
"persisted?(#{persisted?.inspect})",
|
|
126
|
+
"new_record?(#{new_record?.inspect})",
|
|
127
|
+
"deleted?(#{deleted?.inspect})",
|
|
128
|
+
"attributes=#{attributes.inspect}>"
|
|
129
|
+
].join(" ")
|
|
130
|
+
end
|
|
121
131
|
end
|
|
122
132
|
end
|
|
123
133
|
end
|
data/lib/ricordami/version.rb
CHANGED
|
@@ -17,9 +17,9 @@ describe Ricordami::Connection do
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it "has a connection to Redis" do
|
|
20
|
-
Mixer.
|
|
21
|
-
Mixer.
|
|
22
|
-
Mixer.
|
|
20
|
+
Mixer.redis.should be_a(Redis)
|
|
21
|
+
Mixer.redis.get("not_exist")
|
|
22
|
+
Mixer.redis.client.connection.should be_connected
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -17,8 +17,8 @@ describe Ricordami::IsPersisted do
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it "returns the redis driver instance with #redis" do
|
|
20
|
-
Tenant.redis.should == Ricordami.
|
|
21
|
-
Tenant.new.redis.should == Ricordami.
|
|
20
|
+
Tenant.redis.should == Ricordami.redis
|
|
21
|
+
Tenant.new.redis.should == Ricordami.redis
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
describe "#save & #create" do
|
|
@@ -26,7 +26,7 @@ describe Ricordami::IsPersisted do
|
|
|
26
26
|
it "persists a new model" do
|
|
27
27
|
Tenant.attribute :balance
|
|
28
28
|
persister_action.call
|
|
29
|
-
attributes = Ricordami.
|
|
29
|
+
attributes = Ricordami.redis.hgetall("Tenant:att:jojo")
|
|
30
30
|
attributes["id"].should == "jojo"
|
|
31
31
|
attributes["balance"].should == "-$99.98"
|
|
32
32
|
end
|
|
@@ -153,7 +153,7 @@ describe Ricordami::IsPersisted do
|
|
|
153
153
|
|
|
154
154
|
it "deletes the attributes from the DB" do
|
|
155
155
|
tenant.delete.should be_true
|
|
156
|
-
from_db = Ricordami.
|
|
156
|
+
from_db = Ricordami.redis.hgetall("Tenant:att:myid")
|
|
157
157
|
from_db.should be_empty
|
|
158
158
|
end
|
|
159
159
|
|
|
@@ -25,27 +25,27 @@ describe Ricordami::UniqueIndex do
|
|
|
25
25
|
|
|
26
26
|
it "adds a string to the index with #add" do
|
|
27
27
|
@index.add("ze-id", "allo")
|
|
28
|
-
Ricordami.
|
|
28
|
+
Ricordami.redis.smembers("DataSource:udx:id").should == ["allo"]
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
it "also indices the hash index with #add if fields is not :id and :get_by is true" do
|
|
32
32
|
DataSource.attribute :domain
|
|
33
33
|
other = subject.new(DataSource, [:name, :domain], :get_by => true)
|
|
34
34
|
other.add("ze-id", ["jobs", "apple.com"])
|
|
35
|
-
Ricordami.
|
|
36
|
-
Ricordami.
|
|
35
|
+
Ricordami.redis.smembers("DataSource:udx:name_domain").should == ["jobs_-::-_apple.com"]
|
|
36
|
+
Ricordami.redis.hget("DataSource:hsh:name_domain_to_id", "jobs_-::-_apple.com").should == "ze-id"
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
it "doesn't index the has index with #add if :get_by is false or fields is :id" do
|
|
40
40
|
one = subject.new(DataSource, :name)
|
|
41
41
|
one.add("ze-id", "jobs")
|
|
42
|
-
Ricordami.
|
|
42
|
+
Ricordami.redis.hexists("DataSource:hsh:name_to_id", "jobs").should be_false
|
|
43
43
|
two = subject.new(DataSource, :id, :get_by => true)
|
|
44
44
|
two.add("ze-id", "ze-id")
|
|
45
|
-
Ricordami.
|
|
45
|
+
Ricordami.redis.hexists("DataSource:hsh:id_to_id", "ze-id").should be_false
|
|
46
46
|
three = subject.new(DataSource, :name, :get_by => true)
|
|
47
47
|
three.add("ze-id", "jobs")
|
|
48
|
-
Ricordami.
|
|
48
|
+
Ricordami.redis.hexists("DataSource:hsh:name_to_id", "jobs").should be_true
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
it "returns the id from values with #id_for_values if :get_by is true" do
|
|
@@ -61,7 +61,7 @@ describe Ricordami::UniqueIndex do
|
|
|
61
61
|
it "removes a string from the index with #rem" do
|
|
62
62
|
@index.add("ze-id", "allo")
|
|
63
63
|
@index.rem("ze-id", "allo")
|
|
64
|
-
Ricordami.
|
|
64
|
+
Ricordami.redis.smembers("DataSource:udx:id").should == []
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
it "returns the redis command(s) to remove the value from the index when return_command is true" do
|
|
@@ -23,14 +23,14 @@ describe Ricordami::ValueIndex do
|
|
|
23
23
|
|
|
24
24
|
it "adds the id to the index value with #add" do
|
|
25
25
|
index.add("3", "VALUE")
|
|
26
|
-
Ricordami.
|
|
26
|
+
Ricordami.redis.smembers("Friend:idx:first_name:VkFMVUU=").should == ["3"]
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
it "removes the id from the index value with #rem" do
|
|
30
30
|
index.add("1", "VALUE")
|
|
31
31
|
index.add("2", "VALUE")
|
|
32
32
|
index.rem("1", "VALUE")
|
|
33
|
-
Ricordami.
|
|
33
|
+
Ricordami.redis.smembers("Friend:idx:first_name:VkFMVUU=").should == ["2"]
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
it "returns the redis command to remove the value from the index when return_command is true" do
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/db_manager.rb
CHANGED
|
@@ -6,12 +6,12 @@ module Support
|
|
|
6
6
|
def error.method_missing(meth, *args, &blk)
|
|
7
7
|
raise Errno::ECONNREFUSED
|
|
8
8
|
end
|
|
9
|
-
Ricordami.instance_eval { @
|
|
9
|
+
Ricordami.instance_eval { @redis = error }
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def switch_db_to_ok
|
|
13
13
|
return unless @_db_mode_error
|
|
14
|
-
Ricordami.instance_eval { @
|
|
14
|
+
Ricordami.instance_eval { @redis = nil }
|
|
15
15
|
@_db_mode_error = false
|
|
16
16
|
end
|
|
17
17
|
end
|
metadata
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: ricordami
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease:
|
|
5
|
-
version: 0.0.
|
|
5
|
+
version: 0.0.2
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Mathieu Lajugie
|
|
@@ -19,9 +19,9 @@ dependencies:
|
|
|
19
19
|
requirement: &id001 !ruby/object:Gem::Requirement
|
|
20
20
|
none: false
|
|
21
21
|
requirements:
|
|
22
|
-
- -
|
|
22
|
+
- - ~>
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
|
-
version:
|
|
24
|
+
version: 2.1.1
|
|
25
25
|
type: :runtime
|
|
26
26
|
version_requirements: *id001
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
@@ -30,9 +30,9 @@ dependencies:
|
|
|
30
30
|
requirement: &id002 !ruby/object:Gem::Requirement
|
|
31
31
|
none: false
|
|
32
32
|
requirements:
|
|
33
|
-
- -
|
|
33
|
+
- - ~>
|
|
34
34
|
- !ruby/object:Gem::Version
|
|
35
|
-
version:
|
|
35
|
+
version: 3.0.0
|
|
36
36
|
type: :runtime
|
|
37
37
|
version_requirements: *id002
|
|
38
38
|
- !ruby/object:Gem::Dependency
|
|
@@ -41,9 +41,9 @@ dependencies:
|
|
|
41
41
|
requirement: &id003 !ruby/object:Gem::Requirement
|
|
42
42
|
none: false
|
|
43
43
|
requirements:
|
|
44
|
-
- -
|
|
44
|
+
- - ~>
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version:
|
|
46
|
+
version: 3.0.0
|
|
47
47
|
type: :runtime
|
|
48
48
|
version_requirements: *id003
|
|
49
49
|
- !ruby/object:Gem::Dependency
|
|
@@ -123,7 +123,11 @@ dependencies:
|
|
|
123
123
|
version: "0"
|
|
124
124
|
type: :development
|
|
125
125
|
version_requirements: *id010
|
|
126
|
-
description:
|
|
126
|
+
description: |
|
|
127
|
+
Ricordami ("Remember me" in Italian) is an attempt at providing a simple
|
|
128
|
+
interface to build Ruby objects that can be validated, persisted and
|
|
129
|
+
queried in a Redis data structure server.
|
|
130
|
+
|
|
127
131
|
email:
|
|
128
132
|
- mathieu.l AT gmail.com
|
|
129
133
|
executables: []
|
|
@@ -139,7 +143,9 @@ files:
|
|
|
139
143
|
- README.md
|
|
140
144
|
- TODO.md
|
|
141
145
|
- examples/calls.rb
|
|
146
|
+
- examples/person.rb
|
|
142
147
|
- examples/singers.rb
|
|
148
|
+
- examples/summary.rb
|
|
143
149
|
- lib/ricordami.rb
|
|
144
150
|
- lib/ricordami/attribute.rb
|
|
145
151
|
- lib/ricordami/can_be_queried.rb
|