redis_orm 0.5 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ v0.5.1 [27-07-2011]
2
+ * added support of uuid as an id/primary key
3
+ * added documentation on uuid support and connection to the redis server
4
+
1
5
  v0.5 [02-07-2011]
2
6
  * added support of *:conditions* hash in *:options* hash for has_many association in #find/#all methods
3
7
  * made keys order-independent in *:conditions* hash
data/Manifest CHANGED
@@ -26,4 +26,5 @@ test/options_test.rb
26
26
  test/polymorphic_test.rb
27
27
  test/redis.conf
28
28
  test/test_helper.rb
29
+ test/uuid_as_id_test.rb
29
30
  test/validations_test.rb
data/README.md CHANGED
@@ -27,6 +27,15 @@ class User < RedisOrm::Base
27
27
  end
28
28
  ```
29
29
 
30
+ ## Setting up a connection to the redis server
31
+
32
+ If you are using Rails you should initialize redis and set up global $redis variable in *config/initializers/redis.rb* file:
33
+
34
+ ```ruby
35
+ require 'redis'
36
+ $redis = Redis.new(:host => 'localhost', :port => 6379)
37
+ ```
38
+
30
39
  ## Defining a model and specifing properties
31
40
 
32
41
  To specify properties for your model you should use the following syntax:
@@ -61,7 +70,7 @@ Following options are available in property declaration:
61
70
 
62
71
  ## Searching records by the value
63
72
 
64
- Usually it's done via declaring an index and using dynamic finders later. For example:
73
+ Usually it's done via declaring an index and using *:conditions* hash or dynamic finders. For example:
65
74
 
66
75
  ```ruby
67
76
  class User < RedisOrm::Base
@@ -71,15 +80,21 @@ class User < RedisOrm::Base
71
80
  end
72
81
 
73
82
  User.create :name => "germaninthetown"
83
+
84
+ # via dynamic finders:
74
85
  User.find_by_name "germaninthetown" # => found 1 record
75
86
  User.find_all_by_name "germaninthetown" # => array with 1 record
87
+
88
+ # via *:conditions* hash:
89
+ User.find(:all, :conditions => {:name => "germaninthetown"}) # => array with 1 record
90
+ User.all(:conditions => {:name => "germaninthetown"}) # => array with 1 record
76
91
  ```
77
92
 
78
- Dynamic finders work mostly the way they do in ActiveRecord. The only difference is if you didn't specified index or compound index on the attributes you are searching on the exception will be raised.
93
+ Dynamic finders work mostly the way they work in ActiveRecord. The only difference is if you didn't specified index or compound index on the attributes you are searching on the exception will be raised. So you should make an initial analysis of model and determine properties that should be searchable.
79
94
 
80
95
  ## Options for #find/#all
81
96
 
82
- To extract all or part of the associated records you could use 4 options for now:
97
+ To extract all or part of the associated records you could use 4 options:
83
98
 
84
99
  * :limit
85
100
 
@@ -87,20 +102,20 @@ To extract all or part of the associated records you could use 4 options for now
87
102
 
88
103
  * :order
89
104
 
90
- Either :desc or :asc (default), since records are stored with Time.now.to_f scores, by default they could be fetched only in that (or reversed) order. To store them in different order you should *zadd* record's id to some other sorted list manually.
105
+ Either :desc or :asc (default), since records are stored with *Time.now.to_f* scores, by default they could be fetched only in that (or reversed) order. To store them in different order you should *zadd* record's id to some other sorted list manually.
91
106
 
92
107
  * :conditions
93
108
 
94
- Hash where keys must be equal to some property name (there must be index for this property too).
109
+ Hash where keys must be equal to the existing property name (there must be index for this property too).
95
110
 
96
111
  ```ruby
97
112
  # for example we associate 2 photos with the album
98
- @album.photos << @photo2
99
- @album.photos << @photo1
113
+ @album.photos << Photo.create(:image_type => "image/png", :image => "boobs.png")
114
+ @album.photos << Photo.create(:image_type => "image/jpeg", :image => "facepalm.jpg")
100
115
 
101
116
  @album.photos.all(:limit => 0, :offset => 0) # => []
102
117
  @album.photos.all(:limit => 1, :offset => 0).size # => 1
103
- @album.photos.all(:limit => 2, :offset => 0)
118
+ @album.photos.all(:limit => 2, :offset => 0) # [...]
104
119
  @album.photos.all(:limit => 1, :offset => 1, :conditions => {:image_type => "image/png"})
105
120
  @album.photos.find(:all, :order => "asc")
106
121
 
@@ -110,14 +125,50 @@ Photo.all(:order => "desc", :limit => 10, :offset => 50)
110
125
  Photo.all(:order => "desc", :offset => 10, :conditions => {:image_type => "image/jpeg"})
111
126
 
112
127
  Photo.find(:all, :conditions => {:image => "facepalm.jpg"}) # => [...]
113
- Photo.find(:first, :conditions => {:image => "boobs.png"}) # => @photo1
128
+ Photo.find(:first, :conditions => {:image => "boobs.png"}) # => [...]
129
+ ```
130
+
131
+ ## Using UUID instead of numeric id
132
+
133
+ You could use universally unique identifiers (UUIDs) instead of a monotone increasing sequence of numbers as id/primary key for your models.
134
+
135
+ Example of UUID: b57525b09a69012e8fbe001d61192f09.
136
+
137
+ To enable UUIDs you should invoke *use_uuid_as_id* class method:
138
+
139
+ ```ruby
140
+ class User < RedisOrm::Base
141
+ use_uuid_as_id
142
+
143
+ property :name, String
144
+
145
+ property :created_at, Time
146
+ end
147
+ ```
148
+
149
+ [UUID](https://rubygems.org/gems/uuid) gem is installed as a dependency.
150
+
151
+ An excerpt from https://github.com/assaf/uuid :
152
+
153
+ UUID (universally unique identifier) are guaranteed to be unique across time and space.
154
+
155
+ A UUID is 128 bit long, and consists of a 60-bit time value, a 16-bit sequence number and a 48-bit node identifier.
156
+
157
+ Note: when using a forking server (Unicorn, Resque, Pipemaster, etc) you don’t want your forked processes using the same sequence number. Make sure to increment the sequence number each time a worker forks.
158
+
159
+ For example, in config/unicorn.rb:
160
+
161
+ ```ruby
162
+ after_fork do |server, worker|
163
+ UUID.generator.next_sequence
164
+ end
114
165
  ```
115
166
 
116
167
  ## Indices
117
168
 
118
- Indices are used in a different way then they are used in relational databases. They are used to find record by they value rather then to quick access them.
169
+ Indices are used in a different way then they are used in relational databases. In redis_orm they are used to find record by they value rather then to quick access them.
119
170
 
120
- You could add index to any attribute of the model (it also could be compound):
171
+ You could add index to any attribute of the model (index also could be compound):
121
172
 
122
173
  ```ruby
123
174
  class User < RedisOrm::Base
@@ -129,13 +180,13 @@ class User < RedisOrm::Base
129
180
  end
130
181
  ```
131
182
 
132
- With index defined for the property (or properties) the id of the saved object is stored in the special sorted set, so it could be found later by the value. For example with defined User model from the above code:
183
+ With index defined for the property (or properties) the id of the saved object is stored in the sorted set with special name, so it could be found later by the value. For example with defined User model from the above code:
133
184
 
134
185
  ```ruby
135
186
  user = User.new :first_name => "Robert", :last_name => "Pirsig"
136
187
  user.save
137
188
 
138
- # 2 redis keys are created "user:first_name:Robert" and "user:first_name:Robert:last_name:Pirsig" so we could search things like this:
189
+ # 2 redis keys are created "user:first_name:Robert" and "user:first_name:Robert:last_name:Pirsig" so we could search records like this:
139
190
 
140
191
  User.find_by_first_name("Robert") # => user
141
192
  User.find_all_by_first_name("Robert") # => [user]
@@ -164,7 +215,7 @@ comment2 = Comment.create :body => "test #2", :moderated => true
164
215
 
165
216
  article.comments << [comment1, comment2]
166
217
 
167
- # here besides usual indices for each comment, 2 association indices are created so #find with *:conditions* on comments just works
218
+ # here besides usual indices for each comment, 2 association indices are created so #find with *:conditions* on comments should work
168
219
 
169
220
  article.comments.find(:all, :conditions => {:moderated => true})
170
221
  article.comments.find(:all, :conditions => {:moderated => false})
@@ -174,11 +225,11 @@ Index definition supports following options:
174
225
 
175
226
  * **:unique** Boolean default: false
176
227
 
177
- If true is specified then value is stored in ordinary key-value structure with index as the key, otherwise the values are added to sorted set with index as the key.
228
+ If true is specified then value is stored in ordinary key-value structure with index as the key, otherwise the values are added to sorted set with index as the key and *Time.now.to_f* as a score.
178
229
 
179
230
  * **:case_insensitive** Boolean default: false
180
231
 
181
- If true is specified then property values are saved downcased (and then are transformed to downcase form when searching with dynamic finders). Works for compound indices too.
232
+ If true is specified then property values are saved downcased (and then are transformed to downcase form when searching). Works for compound indices too.
182
233
 
183
234
  ## Associations
184
235
 
@@ -372,7 +423,7 @@ For more examples please check test/associations_test.rb and test/polymorphic_te
372
423
 
373
424
  ## Validation
374
425
 
375
- RedisOrm includes ActiveModel::Validations. So all well-known functions are already in. An example from test/validations_test.rb:
426
+ RedisOrm includes ActiveModel::Validations. So all well-known validation callbacks are already in. An excerpt from test/validations_test.rb:
376
427
 
377
428
  ```ruby
378
429
  class Photo < RedisOrm::Base
@@ -417,7 +468,7 @@ end
417
468
 
418
469
  When saving object standard ActiveModel's #valid? method is invoked at first. Then appropriate callbacks are run. Then new Hash in Redis is created with keys/values equal to the properties/values of the saving object.
419
470
 
420
- The object's id is stored in "model_name:ids" sorted set with Time.now.to_f as a score. So records are ordered by created_at time by default.
471
+ The object's id is stored in "model_name:ids" sorted set with Time.now.to_f as a score. So records are ordered by created_at time by default. Then record's indices are created/updated.
421
472
 
422
473
  ## Dirty
423
474
 
@@ -425,11 +476,11 @@ Redis_orm also provides dirty methods to check whether the property has changed
425
476
 
426
477
  ## File attachment management with paperclip and redis
427
478
 
428
- I wrote [3 simple steps](http://def-end.com/post/6669884103/file-attachment-management-with-paperclip-and-redis) you should follow to manage your file attachments with redis and paperclip.
479
+ [3 simple steps](http://def-end.com/post/6669884103/file-attachment-management-with-paperclip-and-redis) you should follow to manage your file attachments with redis and paperclip.
429
480
 
430
481
  ## Tests
431
482
 
432
- Though I'm a big fan of the Test::Unit all tests are based on RSpec. And the only reason I did it are *before(:all)* and *after(:all)* hooks. So I could spawn/kill redis-server's process (from test_helper.rb):
483
+ Though I'm a big fan of the Test::Unit all tests are based on RSpec. And the only reason I use RSpec is possibility to define *before(:all)* and *after(:all)* hooks. So I could spawn/kill redis-server's process (from test_helper.rb):
433
484
 
434
485
  ```ruby
435
486
  RSpec.configure do |config|
data/Rakefile CHANGED
@@ -4,12 +4,12 @@ require 'rake'
4
4
  #=begin
5
5
  require 'echoe'
6
6
 
7
- Echoe.new('redis_orm', '0.5') do |p|
7
+ Echoe.new('redis_orm', '0.5.1') do |p|
8
8
  p.description = "ORM for Redis (advanced key-value storage) with ActiveRecord API"
9
9
  p.url = "https://github.com/german/redis_orm"
10
10
  p.author = "Dmitrii Samoilov"
11
11
  p.email = "germaninthetown@gmail.com"
12
- p.dependencies = ["activesupport >=3.0.0", "activemodel >=3.0.0", "redis >=2.2.0"]
12
+ p.dependencies = ["activesupport >=3.0.0", "activemodel >=3.0.0", "redis >=2.2.0", "uuid >=2.3.2"]
13
13
  p.development_dependencies = ["rspec >=2.5.0"]
14
14
  end
15
15
  #=end
data/lib/redis_orm.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'active_model'
4
4
  require 'redis'
5
+ require 'uuid'
5
6
  require File.join(File.dirname(File.expand_path(__FILE__)), 'redis_orm', 'active_model_behavior')
6
7
 
7
8
  require File.join(File.dirname(File.expand_path(__FILE__)), 'redis_orm', 'associations', 'belongs_to')
@@ -41,8 +41,9 @@ module RedisOrm
41
41
  @@properties = Hash.new{|h,k| h[k] = []}
42
42
  @@indices = Hash.new{|h,k| h[k] = []} # compound indices are available too
43
43
  @@associations = Hash.new{|h,k| h[k] = []}
44
- @@callbacks = Hash.new{|h,k| h[k] = {}}
45
-
44
+ @@callbacks = Hash.new{|h,k| h[k] = {}}
45
+ @@use_uuid_as_id = {}
46
+
46
47
  class << self
47
48
 
48
49
  def inherited(from)
@@ -116,6 +117,11 @@ module RedisOrm
116
117
  end
117
118
  end
118
119
 
120
+ def use_uuid_as_id
121
+ @@use_uuid_as_id[model_name] = true
122
+ @@uuid = UUID.new
123
+ end
124
+
119
125
  def count
120
126
  $redis.zcard("#{model_name}:ids").to_i
121
127
  end
@@ -321,8 +327,10 @@ module RedisOrm
321
327
 
322
328
  def initialize(attributes = {}, id = nil, persisted = false)
323
329
  @persisted = persisted
324
-
325
- instance_variable_set(:"@id", id.to_i) if id
330
+
331
+ id = @@use_uuid_as_id[model_name] ? id : id.to_i
332
+
333
+ instance_variable_set(:"@id", id) if id
326
334
 
327
335
  # when object is created with empty attribute set @#{prop[:name]}_changes array properly
328
336
  @@properties[model_name].each do |prop|
@@ -349,6 +357,14 @@ module RedisOrm
349
357
  @persisted
350
358
  end
351
359
 
360
+ def get_next_id
361
+ if @@use_uuid_as_id[model_name]
362
+ @@uuid.generate(:compact)
363
+ else
364
+ $redis.incr("#{model_name}:id")
365
+ end
366
+ end
367
+
352
368
  def save
353
369
  return false if !valid?
354
370
 
@@ -428,10 +444,9 @@ module RedisOrm
428
444
  self.send(callback)
429
445
  end
430
446
 
431
- @id = $redis.incr("#{model_name}:id")
447
+ @id = get_next_id
432
448
  $redis.zadd "#{model_name}:ids", Time.now.to_f, @id
433
449
  @persisted = true
434
-
435
450
  self.created_at = Time.now if respond_to? :created_at
436
451
  end
437
452
 
@@ -463,7 +478,7 @@ module RedisOrm
463
478
  end
464
479
 
465
480
  # save new indices in order to sort by finders
466
- # city:name:Харьков => 1
481
+ # city:name:Chicago => 1
467
482
  @@indices[model_name].each do |index|
468
483
  prepared_index = construct_prepared_index(index) # instance method not class one!
469
484
 
data/redis_orm.gemspec CHANGED
@@ -2,22 +2,22 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{redis_orm}
5
- s.version = "0.5"
5
+ s.version = "0.5.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
- s.authors = [%q{Dmitrii Samoilov}]
9
- s.date = %q{2011-07-01}
8
+ s.authors = ["Dmitrii Samoilov"]
9
+ s.date = %q{2011-07-27}
10
10
  s.description = %q{ORM for Redis (advanced key-value storage) with ActiveRecord API}
11
11
  s.email = %q{germaninthetown@gmail.com}
12
- s.extra_rdoc_files = [%q{CHANGELOG}, %q{LICENSE}, %q{README.md}, %q{lib/redis_orm.rb}, %q{lib/redis_orm/active_model_behavior.rb}, %q{lib/redis_orm/associations/belongs_to.rb}, %q{lib/redis_orm/associations/has_many.rb}, %q{lib/redis_orm/associations/has_many_helper.rb}, %q{lib/redis_orm/associations/has_many_proxy.rb}, %q{lib/redis_orm/associations/has_one.rb}, %q{lib/redis_orm/redis_orm.rb}]
13
- s.files = [%q{CHANGELOG}, %q{LICENSE}, %q{Manifest}, %q{README.md}, %q{Rakefile}, %q{lib/redis_orm.rb}, %q{lib/redis_orm/active_model_behavior.rb}, %q{lib/redis_orm/associations/belongs_to.rb}, %q{lib/redis_orm/associations/has_many.rb}, %q{lib/redis_orm/associations/has_many_helper.rb}, %q{lib/redis_orm/associations/has_many_proxy.rb}, %q{lib/redis_orm/associations/has_one.rb}, %q{lib/redis_orm/redis_orm.rb}, %q{redis_orm.gemspec}, %q{test/association_indices_test.rb}, %q{test/associations_test.rb}, %q{test/atomicity_test.rb}, %q{test/basic_functionality_test.rb}, %q{test/callbacks_test.rb}, %q{test/changes_array_test.rb}, %q{test/dynamic_finders_test.rb}, %q{test/exceptions_test.rb}, %q{test/has_one_has_many_test.rb}, %q{test/indices_test.rb}, %q{test/options_test.rb}, %q{test/polymorphic_test.rb}, %q{test/redis.conf}, %q{test/test_helper.rb}, %q{test/validations_test.rb}]
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "lib/redis_orm.rb", "lib/redis_orm/active_model_behavior.rb", "lib/redis_orm/associations/belongs_to.rb", "lib/redis_orm/associations/has_many.rb", "lib/redis_orm/associations/has_many_helper.rb", "lib/redis_orm/associations/has_many_proxy.rb", "lib/redis_orm/associations/has_one.rb", "lib/redis_orm/redis_orm.rb"]
13
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.md", "Rakefile", "lib/redis_orm.rb", "lib/redis_orm/active_model_behavior.rb", "lib/redis_orm/associations/belongs_to.rb", "lib/redis_orm/associations/has_many.rb", "lib/redis_orm/associations/has_many_helper.rb", "lib/redis_orm/associations/has_many_proxy.rb", "lib/redis_orm/associations/has_one.rb", "lib/redis_orm/redis_orm.rb", "redis_orm.gemspec", "test/association_indices_test.rb", "test/associations_test.rb", "test/atomicity_test.rb", "test/basic_functionality_test.rb", "test/callbacks_test.rb", "test/changes_array_test.rb", "test/dynamic_finders_test.rb", "test/exceptions_test.rb", "test/has_one_has_many_test.rb", "test/indices_test.rb", "test/options_test.rb", "test/polymorphic_test.rb", "test/redis.conf", "test/test_helper.rb", "test/uuid_as_id_test.rb", "test/validations_test.rb"]
14
14
  s.homepage = %q{https://github.com/german/redis_orm}
15
- s.rdoc_options = [%q{--line-numbers}, %q{--inline-source}, %q{--title}, %q{Redis_orm}, %q{--main}, %q{README.md}]
16
- s.require_paths = [%q{lib}]
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Redis_orm", "--main", "README.md"]
16
+ s.require_paths = ["lib"]
17
17
  s.rubyforge_project = %q{redis_orm}
18
- s.rubygems_version = %q{1.8.5}
18
+ s.rubygems_version = %q{1.6.2}
19
19
  s.summary = %q{ORM for Redis (advanced key-value storage) with ActiveRecord API}
20
- s.test_files = [%q{test/options_test.rb}, %q{test/dynamic_finders_test.rb}, %q{test/associations_test.rb}, %q{test/validations_test.rb}, %q{test/test_helper.rb}, %q{test/polymorphic_test.rb}, %q{test/atomicity_test.rb}, %q{test/exceptions_test.rb}, %q{test/association_indices_test.rb}, %q{test/has_one_has_many_test.rb}, %q{test/indices_test.rb}, %q{test/changes_array_test.rb}, %q{test/callbacks_test.rb}, %q{test/basic_functionality_test.rb}]
20
+ s.test_files = ["test/options_test.rb", "test/dynamic_finders_test.rb", "test/associations_test.rb", "test/validations_test.rb", "test/test_helper.rb", "test/polymorphic_test.rb", "test/uuid_as_id_test.rb", "test/atomicity_test.rb", "test/exceptions_test.rb", "test/association_indices_test.rb", "test/has_one_has_many_test.rb", "test/indices_test.rb", "test/changes_array_test.rb", "test/callbacks_test.rb", "test/basic_functionality_test.rb"]
21
21
 
22
22
  if s.respond_to? :specification_version then
23
23
  s.specification_version = 3
@@ -26,17 +26,20 @@ Gem::Specification.new do |s|
26
26
  s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0"])
27
27
  s.add_runtime_dependency(%q<activemodel>, [">= 3.0.0"])
28
28
  s.add_runtime_dependency(%q<redis>, [">= 2.2.0"])
29
+ s.add_runtime_dependency(%q<uuid>, [">= 2.3.2"])
29
30
  s.add_development_dependency(%q<rspec>, [">= 2.5.0"])
30
31
  else
31
32
  s.add_dependency(%q<activesupport>, [">= 3.0.0"])
32
33
  s.add_dependency(%q<activemodel>, [">= 3.0.0"])
33
34
  s.add_dependency(%q<redis>, [">= 2.2.0"])
35
+ s.add_dependency(%q<uuid>, [">= 2.3.2"])
34
36
  s.add_dependency(%q<rspec>, [">= 2.5.0"])
35
37
  end
36
38
  else
37
39
  s.add_dependency(%q<activesupport>, [">= 3.0.0"])
38
40
  s.add_dependency(%q<activemodel>, [">= 3.0.0"])
39
41
  s.add_dependency(%q<redis>, [">= 2.2.0"])
42
+ s.add_dependency(%q<uuid>, [">= 2.3.2"])
40
43
  s.add_dependency(%q<rspec>, [">= 2.5.0"])
41
44
  end
42
45
  end
@@ -6,6 +6,7 @@ class Article < RedisOrm::Base
6
6
  end
7
7
 
8
8
  describe "check atomicity" do
9
+ =begin
9
10
  it "should properly increment property's value" do
10
11
  @article = Article.new :title => "Simple test atomicity with multiple threads", :karma => 1
11
12
  @article.save
@@ -14,6 +15,7 @@ describe "check atomicity" do
14
15
 
15
16
  50.times do |i|
16
17
  @threads << Thread.new(i) do
18
+ sleep(0.2)
17
19
  @article.update_attribute :karma, (@article.karma + 1)
18
20
  end
19
21
  end
@@ -22,4 +24,41 @@ describe "check atomicity" do
22
24
 
23
25
  Article.first.karma.should == 51
24
26
  end
27
+ =end
28
+ it "should properly increment property's value" do
29
+ threads = []
30
+
31
+ 50.times do |i|
32
+ id = i
33
+ threads << Thread.new(i) do
34
+ if id % 2 == 0
35
+ art = Article.create :title => "article ##{id}", :karma => id
36
+ puts "article.last.id - #{art.id}, article.last.karma - #{art.karma}"
37
+ else
38
+ puts "id - #{id}, (id / 2) + 1 - #{(id / 2) + 1}"
39
+ Article.find((id / 2) + 1).destroy
40
+ end
41
+ end
42
+ end
43
+
44
+ threads.each{|thread| thread.join}
45
+ Article.count.should == 0
46
+ end
47
+ =begin
48
+ it "should properly increment/decrement property's value" do
49
+ article = Article.create :title => "article #1", :karma => 10
50
+ threads = []
51
+
52
+ 10.times do
53
+ threads << Thread.new{ article.update_attribute(:karma, (article.karma + 2)) }
54
+ end
55
+
56
+ 15.times do
57
+ threads << Thread.new{ article.update_attribute(:karma, (article.karma - 1)) }
58
+ end
59
+
60
+ threads.each{|thread| thread.join}
61
+ article.karma.should == 15
62
+ end
63
+ =end
25
64
  end
@@ -0,0 +1,210 @@
1
+ require File.dirname(File.expand_path(__FILE__)) + '/test_helper.rb'
2
+
3
+ class User < RedisOrm::Base
4
+ use_uuid_as_id
5
+
6
+ property :name, String
7
+ property :age, Integer
8
+ property :wage, Float
9
+ property :male, RedisOrm::Boolean
10
+
11
+ property :created_at, Time
12
+ property :modified_at, Time
13
+
14
+ has_many :users, :as => :friends
15
+ end
16
+
17
+ class DefaultUser < RedisOrm::Base
18
+ use_uuid_as_id
19
+
20
+ property :name, String, :default => "german"
21
+ property :age, Integer, :default => 26
22
+ property :wage, Float, :default => 256.25
23
+ property :male, RedisOrm::Boolean, :default => true
24
+ property :admin, RedisOrm::Boolean, :default => false
25
+
26
+ property :created_at, Time
27
+ property :modified_at, Time
28
+ end
29
+
30
+ class TimeStamp < RedisOrm::Base
31
+ use_uuid_as_id
32
+ timestamps
33
+ end
34
+
35
+ describe "check basic functionality" do
36
+ it "test_simple_creation" do
37
+ User.count.should == 0
38
+
39
+ user = User.new :name => "german"
40
+ user.save
41
+
42
+ user.should be
43
+ user.id.should be
44
+
45
+ user.id.should_not == 1
46
+ user.id.length.should == 32 # b57525b09a69012e8fbe001d61192f09 for example
47
+
48
+ user.name.should == "german"
49
+
50
+ User.count.should == 1
51
+ User.first.name.should == "german"
52
+ end
53
+
54
+ it "should test different ways to update a record" do
55
+ User.count.should == 0
56
+
57
+ user = User.new :name => "german"
58
+ user.should be
59
+ user.save
60
+
61
+ user.name.should == "german"
62
+
63
+ user.name = "nobody"
64
+ user.save
65
+
66
+ User.count.should == 1
67
+ User.first.name.should == "nobody"
68
+
69
+ u = User.first
70
+ u.should be
71
+ u.id.should_not == 1
72
+ u.id.length.should == 32
73
+ u.update_attribute :name, "root"
74
+ User.first.name.should == "root"
75
+
76
+ u = User.first
77
+ u.should be
78
+ u.update_attributes :name => "german"
79
+ User.first.name.should == "german"
80
+ end
81
+
82
+ it "test_deletion" do
83
+ User.count.should == 0
84
+
85
+ user = User.new :name => "german"
86
+ user.save
87
+ user.should be
88
+
89
+ user.name.should == "german"
90
+
91
+ User.count.should == 1
92
+ id = user.id
93
+
94
+ user.destroy
95
+ User.count.should == 0
96
+ $redis.zrank("user:ids", id).should == nil
97
+ $redis.hgetall("user:#{id}").should == {}
98
+ end
99
+
100
+ it "should return first and last objects" do
101
+ User.count.should == 0
102
+ User.first.should == nil
103
+ User.last.should == nil
104
+
105
+ user1 = User.new :name => "german"
106
+ user1.save
107
+ user1.should be
108
+ user1.name.should == "german"
109
+ user1.id.should_not == 1
110
+ user1.id.length.should == 32 # b57525b09a69012e8fbe001d61192f09 for example
111
+
112
+ user2 = User.new :name => "nobody"
113
+ user2.save
114
+ user2.should be
115
+ user2.name.should == "nobody"
116
+ user2.id.should_not == 2
117
+ user2.id.length.should == 32
118
+
119
+ User.count.should == 2
120
+
121
+ User.first.should be
122
+ User.last.should be
123
+
124
+ User.first.id.should == user1.id
125
+ User.last.id.should == user2.id
126
+ end
127
+
128
+ it "should return values with correct classes" do
129
+ user = User.new
130
+ user.name = "german"
131
+ user.age = 26
132
+ user.wage = 124.34
133
+ user.male = true
134
+ user.save
135
+
136
+ user.should be
137
+
138
+ u = User.first
139
+
140
+ u.created_at.class.should == Time
141
+ u.modified_at.class.should == Time
142
+ u.wage.class.should == Float
143
+ u.male.class.to_s.should match(/TrueClass|FalseClass/)
144
+ u.age.class.to_s.should match(/Integer|Fixnum/)
145
+ u.id.should_not == 1
146
+ u.id.length.should == 32
147
+
148
+ u.name.should == "german"
149
+ u.wage.should == 124.34
150
+ u.age.should == 26
151
+ u.male.should == true
152
+ end
153
+
154
+ it "should return correct saved defaults" do
155
+ DefaultUser.count.should == 0
156
+ DefaultUser.create
157
+ DefaultUser.count.should == 1
158
+
159
+ u = DefaultUser.first
160
+
161
+ u.created_at.class.should == Time
162
+ u.modified_at.class.should == Time
163
+ u.wage.class.should == Float
164
+ u.male.class.to_s.should match(/TrueClass|FalseClass/)
165
+ u.admin.class.to_s.should match(/TrueClass|FalseClass/)
166
+ u.age.class.to_s.should match(/Integer|Fixnum/)
167
+
168
+ u.name.should == "german"
169
+ u.male.should == true
170
+ u.age.should == 26
171
+ u.wage.should == 256.25
172
+ u.admin.should == false
173
+ u.id.should_not == 1
174
+ u.id.length.should == 32
175
+
176
+ du = DefaultUser.new
177
+ du.name = "germaninthetown"
178
+ du.save
179
+
180
+ du_saved = DefaultUser.last
181
+ du_saved.name.should == "germaninthetown"
182
+ du_saved.admin.should == false
183
+ du.id.should_not == 2
184
+ du.id.should_not == u.id
185
+ du.id.length.should == 32
186
+ end
187
+
188
+ it "should expand timestamps declaration properly" do
189
+ t = TimeStamp.new
190
+ t.save
191
+
192
+ t.created_at.should be
193
+ t.modified_at.should be
194
+ t.created_at.day.should == Time.now.day
195
+ t.modified_at.day.should == Time.now.day
196
+ end
197
+
198
+ # from associations_test.rb
199
+ it "should maintain correct self referencing link" do
200
+ me = User.create :name => "german", :age => 26, :wage => 10.0, :male => true
201
+ friend1 = User.create :name => "friend1", :age => 26, :wage => 7.0, :male => true
202
+ friend2 = User.create :name => "friend2", :age => 25, :wage => 5.0, :male => true
203
+
204
+ me.friends << [friend1, friend2]
205
+
206
+ me.friends.count.should == 2
207
+ friend1.friends.count.should == 0
208
+ friend2.friends.count.should == 0
209
+ end
210
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_orm
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: 0.5.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-01 00:00:00.000000000Z
12
+ date: 2011-07-27 00:00:00.000000000 +03:00
13
+ default_executable:
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: activesupport
16
- requirement: &84648260 !ruby/object:Gem::Requirement
17
+ requirement: &87829630 !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
20
  - - ! '>='
@@ -21,10 +22,10 @@ dependencies:
21
22
  version: 3.0.0
22
23
  type: :runtime
23
24
  prerelease: false
24
- version_requirements: *84648260
25
+ version_requirements: *87829630
25
26
  - !ruby/object:Gem::Dependency
26
27
  name: activemodel
27
- requirement: &84647900 !ruby/object:Gem::Requirement
28
+ requirement: &87829290 !ruby/object:Gem::Requirement
28
29
  none: false
29
30
  requirements:
30
31
  - - ! '>='
@@ -32,10 +33,10 @@ dependencies:
32
33
  version: 3.0.0
33
34
  type: :runtime
34
35
  prerelease: false
35
- version_requirements: *84647900
36
+ version_requirements: *87829290
36
37
  - !ruby/object:Gem::Dependency
37
38
  name: redis
38
- requirement: &84647510 !ruby/object:Gem::Requirement
39
+ requirement: &87828950 !ruby/object:Gem::Requirement
39
40
  none: false
40
41
  requirements:
41
42
  - - ! '>='
@@ -43,10 +44,21 @@ dependencies:
43
44
  version: 2.2.0
44
45
  type: :runtime
45
46
  prerelease: false
46
- version_requirements: *84647510
47
+ version_requirements: *87828950
48
+ - !ruby/object:Gem::Dependency
49
+ name: uuid
50
+ requirement: &87828600 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: 2.3.2
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: *87828600
47
59
  - !ruby/object:Gem::Dependency
48
60
  name: rspec
49
- requirement: &84647120 !ruby/object:Gem::Requirement
61
+ requirement: &87828250 !ruby/object:Gem::Requirement
50
62
  none: false
51
63
  requirements:
52
64
  - - ! '>='
@@ -54,7 +66,7 @@ dependencies:
54
66
  version: 2.5.0
55
67
  type: :development
56
68
  prerelease: false
57
- version_requirements: *84647120
69
+ version_requirements: *87828250
58
70
  description: ORM for Redis (advanced key-value storage) with ActiveRecord API
59
71
  email: germaninthetown@gmail.com
60
72
  executables: []
@@ -100,7 +112,9 @@ files:
100
112
  - test/polymorphic_test.rb
101
113
  - test/redis.conf
102
114
  - test/test_helper.rb
115
+ - test/uuid_as_id_test.rb
103
116
  - test/validations_test.rb
117
+ has_rdoc: true
104
118
  homepage: https://github.com/german/redis_orm
105
119
  licenses: []
106
120
  post_install_message:
@@ -127,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
141
  version: '1.2'
128
142
  requirements: []
129
143
  rubyforge_project: redis_orm
130
- rubygems_version: 1.8.5
144
+ rubygems_version: 1.6.2
131
145
  signing_key:
132
146
  specification_version: 3
133
147
  summary: ORM for Redis (advanced key-value storage) with ActiveRecord API
@@ -138,6 +152,7 @@ test_files:
138
152
  - test/validations_test.rb
139
153
  - test/test_helper.rb
140
154
  - test/polymorphic_test.rb
155
+ - test/uuid_as_id_test.rb
141
156
  - test/atomicity_test.rb
142
157
  - test/exceptions_test.rb
143
158
  - test/association_indices_test.rb