redis_orm 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGELOG +8 -0
  2. data/Manifest +32 -0
  3. data/Rakefile +7 -15
  4. data/TODO +5 -0
  5. data/lib/redis_orm/associations/belongs_to.rb +37 -3
  6. data/lib/redis_orm/associations/has_one.rb +32 -0
  7. data/lib/redis_orm/redis_orm.rb +47 -9
  8. data/redis_orm.gemspec +4 -4
  9. data/test/association_indices_test.rb +51 -28
  10. data/test/associations_test.rb +0 -59
  11. data/test/atomicity_test.rb +0 -7
  12. data/test/basic_functionality_test.rb +12 -28
  13. data/test/callbacks_test.rb +0 -70
  14. data/test/changes_array_test.rb +0 -6
  15. data/test/classes/album.rb +6 -0
  16. data/test/classes/article.rb +7 -0
  17. data/test/classes/book.rb +6 -0
  18. data/test/classes/catalog_item.rb +5 -0
  19. data/test/classes/category.rb +7 -0
  20. data/test/classes/city.rb +7 -0
  21. data/test/classes/comment.rb +26 -0
  22. data/test/classes/country.rb +5 -0
  23. data/test/classes/custom_user.rb +8 -0
  24. data/test/classes/cutout.rb +20 -0
  25. data/test/classes/cutout_aggregator.rb +5 -0
  26. data/test/classes/default_user.rb +10 -0
  27. data/test/classes/dynamic_finder_user.rb +8 -0
  28. data/test/classes/empty_person.rb +2 -0
  29. data/test/classes/giftcard.rb +6 -0
  30. data/test/classes/jigsaw.rb +4 -0
  31. data/test/classes/location.rb +5 -0
  32. data/test/classes/message.rb +4 -0
  33. data/test/classes/note.rb +5 -0
  34. data/test/classes/omni_user.rb +8 -0
  35. data/test/classes/person.rb +6 -0
  36. data/test/classes/photo.rb +21 -0
  37. data/test/classes/profile.rb +8 -0
  38. data/test/classes/sortable_user.rb +11 -0
  39. data/test/classes/timestamp.rb +3 -0
  40. data/test/classes/user.rb +39 -0
  41. data/test/classes/uuid_default_user.rb +12 -0
  42. data/test/classes/uuid_timestamp.rb +5 -0
  43. data/test/classes/uuid_user.rb +13 -0
  44. data/test/dynamic_finders_test.rb +9 -26
  45. data/test/exceptions_test.rb +1 -21
  46. data/test/has_one_has_many_test.rb +0 -12
  47. data/test/indices_test.rb +0 -18
  48. data/test/modules/belongs_to_model_within_module.rb +6 -0
  49. data/test/modules/has_many_model_within_module.rb +11 -0
  50. data/test/options_test.rb +0 -37
  51. data/test/polymorphic_test.rb +0 -39
  52. data/test/sortable_test.rb +60 -74
  53. data/test/test_helper.rb +4 -0
  54. data/test/uuid_as_id_test.rb +38 -70
  55. data/test/validations_test.rb +0 -8
  56. metadata +45 -12
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ v0.6.2 [23-05-2011]
2
+ * adds an ability to specify indices on *has_one* assoc
3
+ * adds an ability to create indices on belongs_to association
4
+ * fixed error with updating indices in :belongs_to assoc with :as option;
5
+ * tests refactoring, now all tests are run with Rake::TestTask,
6
+ * moved all classes and modules from test cases to special folders
7
+ * fixed bug: :default values should be properly transformed to right classes (if :default values are wrong) so when comparing them to other/stored instances they'll be the same
8
+
1
9
  v0.6.1 [05-12-2011]
2
10
  * rewritten sortable functionality for attributes which values are strings
3
11
  * added Gemfile to the project, improved tests
data/Manifest CHANGED
@@ -4,6 +4,7 @@ LICENSE
4
4
  Manifest
5
5
  README.md
6
6
  Rakefile
7
+ TODO
7
8
  benchmarks/sortable_benchmark.rb
8
9
  lib/redis_orm.rb
9
10
  lib/redis_orm/active_model_behavior.rb
@@ -21,10 +22,41 @@ test/atomicity_test.rb
21
22
  test/basic_functionality_test.rb
22
23
  test/callbacks_test.rb
23
24
  test/changes_array_test.rb
25
+ test/classes/album.rb
26
+ test/classes/article.rb
27
+ test/classes/book.rb
28
+ test/classes/catalog_item.rb
29
+ test/classes/category.rb
30
+ test/classes/city.rb
31
+ test/classes/comment.rb
32
+ test/classes/country.rb
33
+ test/classes/custom_user.rb
34
+ test/classes/cutout.rb
35
+ test/classes/cutout_aggregator.rb
36
+ test/classes/default_user.rb
37
+ test/classes/dynamic_finder_user.rb
38
+ test/classes/empty_person.rb
39
+ test/classes/giftcard.rb
40
+ test/classes/jigsaw.rb
41
+ test/classes/location.rb
42
+ test/classes/message.rb
43
+ test/classes/note.rb
44
+ test/classes/omni_user.rb
45
+ test/classes/person.rb
46
+ test/classes/photo.rb
47
+ test/classes/profile.rb
48
+ test/classes/sortable_user.rb
49
+ test/classes/timestamp.rb
50
+ test/classes/user.rb
51
+ test/classes/uuid_default_user.rb
52
+ test/classes/uuid_timestamp.rb
53
+ test/classes/uuid_user.rb
24
54
  test/dynamic_finders_test.rb
25
55
  test/exceptions_test.rb
26
56
  test/has_one_has_many_test.rb
27
57
  test/indices_test.rb
58
+ test/modules/belongs_to_model_within_module.rb
59
+ test/modules/has_many_model_within_module.rb
28
60
  test/options_test.rb
29
61
  test/polymorphic_test.rb
30
62
  test/redis.conf
data/Rakefile CHANGED
@@ -1,10 +1,11 @@
1
- require 'psych'
2
1
  require 'rubygems'
3
2
  require 'rake'
3
+ require 'rake/testtask'
4
+
4
5
  #=begin
5
6
  require 'echoe'
6
7
 
7
- Echoe.new('redis_orm', '0.6.1') do |p|
8
+ Echoe.new('redis_orm', '0.6.2') do |p|
8
9
  p.description = "ORM for Redis (advanced key-value storage) with ActiveRecord API"
9
10
  p.url = "https://github.com/german/redis_orm"
10
11
  p.author = "Dmitrii Samoilov"
@@ -14,20 +15,11 @@ Echoe.new('redis_orm', '0.6.1') do |p|
14
15
  end
15
16
  #=end
16
17
 
17
- #require 'rake/testtask'
18
- #$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
18
+ task :default => :test
19
19
 
20
- =begin
21
- desc 'Test the redis_orm gem.'
20
+ desc 'Test the redis_orm functionality'
22
21
  Rake::TestTask.new(:test) do |t|
23
- #t.libs << 'lib'
24
- t.pattern = 'test/**/*_test.rb'
22
+ t.libs << 'lib'
23
+ t.test_files = FileList['test/*_test.rb']
25
24
  t.verbose = true
26
25
  end
27
- =end
28
-
29
- task :test do |t|
30
- Dir['test/**/*_test.rb'].each do |file|
31
- puts `ruby -I./lib #{file}`
32
- end
33
- end
data/TODO ADDED
@@ -0,0 +1,5 @@
1
+ * add rake task to create index keys to existing records after the index was added to the column, something like *rake redis_orm:update_index_on zip*
2
+ * add named_scopes
3
+ * Sinatra based admin interface to overview all redis_orm keys in redis
4
+ * ActiveRecord 3.x API
5
+ * refactoring ;)
@@ -16,6 +16,10 @@ module RedisOrm
16
16
 
17
17
  foreign_model_name = options[:as] ? options[:as].to_sym : foreign_model.to_sym
18
18
 
19
+ if options[:index]
20
+ class_variable_get(:"@@indices")[model_name] << {:name => foreign_model_name, :options => {:reference => true}}
21
+ end
22
+
19
23
  define_method foreign_model_name do
20
24
  if options[:polymorphic]
21
25
  model_type = $redis.get("#{model_name}:#{id}:#{foreign_model_name}_type")
@@ -32,12 +36,13 @@ module RedisOrm
32
36
  end
33
37
  end
34
38
  end
35
-
39
+
36
40
  # look = Look.create :title => 'test'
37
41
  # look.user = User.find(1) => look:23:user => 1
38
42
  define_method "#{foreign_model_name}=" do |assoc_with_record|
39
43
  # we need to store this to clear old association later
40
44
  old_assoc = self.send(foreign_model_name)
45
+
41
46
  # find model even if it's in some module
42
47
  full_model_scope = RedisOrm::Base.descendants.detect{|desc| desc.to_s.split('::').include?(foreign_model.to_s.camelize) }
43
48
 
@@ -53,7 +58,36 @@ module RedisOrm
53
58
  raise TypeMismatchError
54
59
  end
55
60
  end
61
+
62
+ # handle indices for references
63
+ self.get_indices.select{|index| index[:options][:reference]}.each do |index|
64
+ # delete old reference that points to the old associated record
65
+ if !old_assoc.nil?
66
+ prepared_index = [self.model_name, index[:name], old_assoc.id].join(':')
67
+ prepared_index.downcase! if index[:options][:case_insensitive]
68
+
69
+ if index[:options][:unique]
70
+ $redis.del(prepared_index, id)
71
+ else
72
+ $redis.zrem(prepared_index, id)
73
+ end
74
+ end
75
+
76
+ # if new associated record is nil then skip to next index (since old associated record was already unreferenced)
77
+ next if assoc_with_record.nil?
78
+
79
+ prepared_index = [self.model_name, index[:name], assoc_with_record.id].join(':')
80
+
81
+ prepared_index.downcase! if index[:options][:case_insensitive]
82
+
83
+ if index[:options][:unique]
84
+ $redis.set(prepared_index, id)
85
+ else
86
+ $redis.zadd(prepared_index, Time.now.to_f, id)
87
+ end
88
+ end
56
89
 
90
+ # we should have an option to delete created earlier associasion (like 'node.owner = nil')
57
91
  if assoc_with_record.nil?
58
92
  # remove old assoc
59
93
  $redis.zrem("#{old_assoc.model_name}:#{old_assoc.id}:#{model_name.to_s.pluralize}", self.id) if old_assoc
@@ -61,7 +95,7 @@ module RedisOrm
61
95
  # check whether *assoc_with_record* object has *has_many* declaration and TODO it states *self.model_name* in plural and there is no record yet from the *assoc_with_record*'s side (in order not to provoke recursion)
62
96
  if class_associations[assoc_with_record.model_name].detect{|h| h[:type] == :has_many && h[:foreign_models] == model_name.pluralize.to_sym} && !$redis.zrank("#{assoc_with_record.model_name}:#{assoc_with_record.id}:#{model_name.pluralize}", self.id)
63
97
  # remove old assoc
64
- $redis.zrem("#{old_assoc.model_name}:#{old_assoc.id}:#{model_name.to_s.pluralize}", self.id) if old_assoc
98
+ $redis.zrem("#{old_assoc.model_name}:#{old_assoc.id}:#{model_name.to_s.pluralize}", self.id) if old_assoc
65
99
  assoc_with_record.send(model_name.pluralize.to_sym).send(:"<<", self)
66
100
 
67
101
  # check whether *assoc_with_record* object has *has_one* declaration and TODO it states *self.model_name* and there is no record yet from the *assoc_with_record*'s side (in order not to provoke recursion)
@@ -74,4 +108,4 @@ module RedisOrm
74
108
  end
75
109
  end
76
110
  end
77
- end
111
+ end
@@ -15,6 +15,10 @@ module RedisOrm
15
15
  foreign_model.to_sym
16
16
  end
17
17
 
18
+ if options[:index]
19
+ class_variable_get(:"@@indices")[model_name] << {:name => foreign_model_name, :options => {:reference => true}}
20
+ end
21
+
18
22
  define_method foreign_model_name do
19
23
  foreign_model.to_s.camelize.constantize.find($redis.get "#{model_name}:#{@id}:#{foreign_model_name}")
20
24
  end
@@ -32,6 +36,34 @@ module RedisOrm
32
36
  else
33
37
  raise TypeMismatchError
34
38
  end
39
+
40
+ # handle indices for references
41
+ self.get_indices.select{|index| index[:options][:reference]}.each do |index|
42
+ # delete old reference that points to the old associated record
43
+ if !old_assoc.nil?
44
+ prepared_index = [self.model_name, index[:name], old_assoc.id].join(':')
45
+ prepared_index.downcase! if index[:options][:case_insensitive]
46
+
47
+ if index[:options][:unique]
48
+ $redis.del(prepared_index, id)
49
+ else
50
+ $redis.zrem(prepared_index, id)
51
+ end
52
+ end
53
+
54
+ # if new associated record is nil then skip to next index (since old associated record was already unreferenced)
55
+ next if assoc_with_record.nil?
56
+
57
+ prepared_index = [self.model_name, index[:name], assoc_with_record.id].join(':')
58
+
59
+ prepared_index.downcase! if index[:options][:case_insensitive]
60
+
61
+ if index[:options][:unique]
62
+ $redis.set(prepared_index, id)
63
+ else
64
+ $redis.zadd(prepared_index, Time.now.to_f, id)
65
+ end
66
+ end
35
67
 
36
68
  if !options[:as]
37
69
  if assoc_with_record.nil?
@@ -75,7 +75,7 @@ module RedisOrm
75
75
  send(:define_method, property_name) do
76
76
  value = instance_variable_get(:"@#{property_name}")
77
77
 
78
- return value if value.nil? # we must return nil here so :default option will work when saving, otherwise it'll return "" or 0 or 0.0
78
+ return nil if value.nil? # we must return nil here so :default option will work when saving, otherwise it'll return "" or 0 or 0.0
79
79
 
80
80
  if Time == class_name
81
81
  value = begin
@@ -203,11 +203,22 @@ module RedisOrm
203
203
 
204
204
  prepared_index = if !options[:conditions].blank? && options[:conditions].is_a?(Hash)
205
205
  properties = options[:conditions].collect{|key, value| key}
206
+
207
+ # if some condition includes object => get only the id of this object
208
+ conds = options[:conditions].inject({}) do |sum, item|
209
+ key, value = item
210
+ if value.respond_to?(:model_name)
211
+ sum.merge!({key => value.id})
212
+ else
213
+ sum.merge!({key => value})
214
+ end
215
+ end
216
+
206
217
  index = find_indices(properties, :first => true)
207
218
 
208
219
  raise NotIndexFound if !index
209
220
 
210
- construct_prepared_index(index, options[:conditions])
221
+ construct_prepared_index(index, conds)
211
222
  else
212
223
  if options[:order] && options[:order].is_a?(Array)
213
224
  model_name
@@ -438,10 +449,15 @@ module RedisOrm
438
449
  instance_variable_set :"@#{prop[:name]}_changes", []
439
450
  end
440
451
  end
441
-
452
+
453
+ # get all names of properties to assign only those attributes from attributes hash whose key are in prop_names
454
+ # we're not using *self.respond_to?("#{key}=".to_sym)* since *belongs_to* and other assocs could create their own methods
455
+ # with *key=* name, that in turn will mess up indices
456
+ prop_names = @@properties[model_name].collect{|m| m[:name]}
457
+
442
458
  if attributes.is_a?(Hash) && !attributes.empty?
443
459
  attributes.each do |key, value|
444
- self.send("#{key}=".to_sym, value) if self.respond_to?("#{key}=".to_sym)
460
+ self.send("#{key}=".to_sym, value) if prop_names.include?(key.to_sym)
445
461
  end
446
462
  end
447
463
  self
@@ -554,7 +570,9 @@ module RedisOrm
554
570
  if !@@associations[model_name].empty?
555
571
  @@associations[model_name].each do |assoc|
556
572
  if :belongs_to == assoc[:type]
557
- if !self.send(assoc[:foreign_model]).nil?
573
+ # if association has :as option use it, otherwise use standard :foreign_model
574
+ foreign_model_name = assoc[:options][:as] ? assoc[:options][:as].to_sym : assoc[:foreign_model].to_sym
575
+ if !self.send(foreign_model_name).nil?
558
576
  if index[:name].is_a?(Array)
559
577
  keys_to_delete = if index[:name].index(prop) == 0
560
578
  $redis.keys "#{assoc[:foreign_model]}:#{self.send(assoc[:foreign_model]).id}:#{model_name.to_s.pluralize}:#{prop[:name]}#{prev_prop_value}*"
@@ -601,9 +619,29 @@ module RedisOrm
601
619
 
602
620
  if prop_value.nil? && !prop[:options][:default].nil?
603
621
  prop_value = prop[:options][:default]
622
+
623
+ # cast prop_value to proper class if they are not in it
624
+ # for example 'property :wage, Float, :sortable => true, :default => 20_000' turn 20_000 to 20_000.0
625
+ if prop[:class] != prop_value.class.to_s
626
+ prop_value = case prop[:class]
627
+ when 'Time'
628
+ begin
629
+ value.to_s.to_time(:local)
630
+ rescue ArgumentError => e
631
+ nil
632
+ end
633
+ when 'Integer'
634
+ prop_value.to_i
635
+ when 'Float'
636
+ prop_value.to_f
637
+ when 'RedisOrm::Boolean'
638
+ (prop_value == "false" || prop_value == false) ? false : true
639
+ end
640
+ end
641
+
604
642
  # set instance variable in order to properly save indexes here
605
- self.instance_variable_set(:"@#{prop[:name]}", prop[:options][:default])
606
- instance_variable_set :"@#{prop[:name]}_changes", [prop[:options][:default]]
643
+ self.instance_variable_set(:"@#{prop[:name]}", prop_value)
644
+ instance_variable_set :"@#{prop[:name]}_changes", [prop_value]
607
645
  end
608
646
 
609
647
  $redis.hset("#{model_name}:#{id}", prop[:name].to_s, prop_value)
@@ -643,9 +681,9 @@ module RedisOrm
643
681
  end
644
682
  end
645
683
 
646
- # save new indices in order to sort by finders
684
+ # save new indices (not *reference* onces (for example not these *belongs_to :note, :index => true*)) in order to sort by finders
647
685
  # city:name:Chicago => 1
648
- @@indices[model_name].each do |index|
686
+ @@indices[model_name].reject{|index| index[:options][:reference]}.each do |index|
649
687
  prepared_index = construct_prepared_index(index) # instance method not class one!
650
688
 
651
689
  if index[:options][:unique]
data/redis_orm.gemspec CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{redis_orm}
5
- s.version = "0.6.1"
5
+ s.version = "0.6.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = [%q{Dmitrii Samoilov}]
9
- s.date = %q{2011-12-05}
9
+ s.date = %q{2012-05-23}
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}, %q{lib/redis_orm/utils.rb}]
13
- s.files = [%q{CHANGELOG}, %q{Gemfile}, %q{LICENSE}, %q{Manifest}, %q{README.md}, %q{Rakefile}, %q{benchmarks/sortable_benchmark.rb}, %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{lib/redis_orm/utils.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/sortable_test.rb}, %q{test/test_helper.rb}, %q{test/uuid_as_id_test.rb}, %q{test/validations_test.rb}]
12
+ s.extra_rdoc_files = [%q{CHANGELOG}, %q{LICENSE}, %q{README.md}, %q{TODO}, %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{lib/redis_orm/utils.rb}]
13
+ s.files = [%q{CHANGELOG}, %q{Gemfile}, %q{LICENSE}, %q{Manifest}, %q{README.md}, %q{Rakefile}, %q{TODO}, %q{benchmarks/sortable_benchmark.rb}, %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{lib/redis_orm/utils.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/classes/album.rb}, %q{test/classes/article.rb}, %q{test/classes/book.rb}, %q{test/classes/catalog_item.rb}, %q{test/classes/category.rb}, %q{test/classes/city.rb}, %q{test/classes/comment.rb}, %q{test/classes/country.rb}, %q{test/classes/custom_user.rb}, %q{test/classes/cutout.rb}, %q{test/classes/cutout_aggregator.rb}, %q{test/classes/default_user.rb}, %q{test/classes/dynamic_finder_user.rb}, %q{test/classes/empty_person.rb}, %q{test/classes/giftcard.rb}, %q{test/classes/jigsaw.rb}, %q{test/classes/location.rb}, %q{test/classes/message.rb}, %q{test/classes/note.rb}, %q{test/classes/omni_user.rb}, %q{test/classes/person.rb}, %q{test/classes/photo.rb}, %q{test/classes/profile.rb}, %q{test/classes/sortable_user.rb}, %q{test/classes/timestamp.rb}, %q{test/classes/user.rb}, %q{test/classes/uuid_default_user.rb}, %q{test/classes/uuid_timestamp.rb}, %q{test/classes/uuid_user.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/modules/belongs_to_model_within_module.rb}, %q{test/modules/has_many_model_within_module.rb}, %q{test/options_test.rb}, %q{test/polymorphic_test.rb}, %q{test/redis.conf}, %q{test/sortable_test.rb}, %q{test/test_helper.rb}, %q{test/uuid_as_id_test.rb}, %q{test/validations_test.rb}]
14
14
  s.homepage = %q{https://github.com/german/redis_orm}
15
15
  s.rdoc_options = [%q{--line-numbers}, %q{--inline-source}, %q{--title}, %q{Redis_orm}, %q{--main}, %q{README.md}]
16
16
  s.require_paths = [%q{lib}]
@@ -1,32 +1,5 @@
1
1
  require File.dirname(File.expand_path(__FILE__)) + '/test_helper.rb'
2
2
 
3
- class Article < RedisOrm::Base
4
- property :title, String
5
- has_many :comments
6
- end
7
-
8
- class Comment < RedisOrm::Base
9
- property :body, String
10
-
11
- property :moderated, RedisOrm::Boolean, :default => false
12
- index :moderated
13
-
14
- belongs_to :article
15
- end
16
-
17
- class User < RedisOrm::Base
18
- property :name, String
19
- index :name
20
-
21
- property :moderator, RedisOrm::Boolean, :default => false
22
- property :moderated_area, String, :default => "messages"
23
-
24
- index :moderator
25
- index [:moderator, :moderated_area]
26
-
27
- has_many :users, :as => :friends
28
- end
29
-
30
3
  describe "check indices for associations" do
31
4
  before(:each) do
32
5
  @article = Article.new :title => "DHH drops OpenID on 37signals"
@@ -142,4 +115,54 @@ describe "check indices for associations" do
142
115
  me.friends.find(:all, :conditions => {:moderated_area => "all", :moderator => true}).size.should == 1
143
116
  me.friends.find(:all, :conditions => {:moderated_area => "all", :moderator => true})[0].id.should == friend2.id
144
117
  end
145
- end
118
+
119
+ # TODO check that index assoc shouldn't be created while no assoc_record is provided
120
+
121
+ it "should return first model if it exists, when conditions contain associated object" do
122
+ user = User.create :name => "Dmitrii Samoilov", :age => 99, :wage => 35_000, :first_name => "Dmitrii", :last_name => "Samoilov"
123
+ note = Note.create :body => "a test to test"
124
+ note2 = Note.create :body => "aero"
125
+
126
+ note.owner = user
127
+
128
+ User.count.should == 1
129
+ Note.count.should == 2
130
+ $redis.zcard("note:owner:1").should == 1
131
+ note.owner.should == user
132
+ Note.find(:all, :conditions => {:owner => user}).should == [note]
133
+ Note.find(:first, :conditions => {:owner => user}).should == note
134
+
135
+ note.owner = nil
136
+ Note.find(:all, :conditions => {:owner => user}).should == []
137
+ Note.find(:first, :conditions => {:owner => user}).should == nil
138
+ $redis.zcard("note:owner:1").should == 0
139
+ end
140
+
141
+ it "should return first model if it exists when conditions contain associated object (belongs_to assoc established when creating object)" do
142
+ user = User.create :name => "Dmitrii Samoilov", :age => 99, :wage => 35_000, :first_name => "Dmitrii", :last_name => "Samoilov"
143
+ note = Note.create :body => "a test to test", :owner => user
144
+ Note.create :body => "aero" # just test what would *find* return if 2 exemplars of Note are created
145
+
146
+ User.count.should == 1
147
+ Note.count.should == 2
148
+
149
+ note.owner.should == user
150
+
151
+ Note.find(:all, :conditions => {:owner => user}).should == [note]
152
+ Note.find(:first, :conditions => {:owner => user}).should == note
153
+ end
154
+
155
+ it "should return first model if it exists when conditions contain associated object (has_one assoc established when creating object)" do
156
+ profile = Profile.create :title => "a test to test", :name => "german"
157
+ user = User.create :name => "Dmitrii Samoilov", :age => 99, :wage => 35_000, :first_name => "Dmitrii", :last_name => "Samoilov", :profile => profile
158
+ User.create :name => "Warren Buffet", :age => 399, :wage => 12_235_000, :first_name => "Warren", :last_name => "Buffet"
159
+
160
+ User.count.should == 2
161
+ Profile.count.should == 1
162
+
163
+ profile.user.should == user
164
+
165
+ User.find(:all, :conditions => {:profile => profile}).should == [user]
166
+ User.find(:first, :conditions => {:profile => profile}).should == user
167
+ end
168
+ end
@@ -1,64 +1,5 @@
1
1
  require File.dirname(File.expand_path(__FILE__)) + '/test_helper.rb'
2
2
 
3
- class Article < RedisOrm::Base
4
- property :title, String
5
- has_many :comments
6
- has_many :categories
7
- end
8
-
9
- class Comment < RedisOrm::Base
10
- property :body, String
11
-
12
- belongs_to :article
13
- has_many :comments, :as => :replies
14
- belongs_to :comment, :as => :reply_to
15
- end
16
-
17
- module BelongsToModelWithinModule
18
- class Reply < RedisOrm::Base
19
- property :body, String, :default => "test"
20
- belongs_to :article, :as => :essay
21
- end
22
- end
23
-
24
- module HasManyModelWithinModule
25
- class SpecialComment < RedisOrm::Base
26
- property :body, String, :default => "test"
27
- belongs_to :brochure, :as => :book
28
- end
29
-
30
- class Brochure < RedisOrm::Base
31
- property :title, String
32
- has_many :special_comments
33
- end
34
- end
35
-
36
- class Profile < RedisOrm::Base
37
- property :title, String
38
- has_one :city
39
- end
40
-
41
- class City < RedisOrm::Base
42
- property :name, String
43
- has_many :profiles
44
- end
45
-
46
- class Category < RedisOrm::Base
47
- property :name, String
48
- has_many :articles
49
- end
50
-
51
- class User < RedisOrm::Base
52
- property :name, String
53
- index :name
54
- has_many :users, :as => :friends
55
- end
56
-
57
- class Message < RedisOrm::Base
58
- property :text, String
59
- has_one :message, :as => :replay_to
60
- end
61
-
62
3
  describe "check associations" do
63
4
  before(:each) do
64
5
  @article = Article.new :title => "DHH drops OpenID on 37signals"