redis_orm 0.6.1 → 0.6.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.
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"