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.
- data/CHANGELOG +8 -0
- data/Manifest +32 -0
- data/Rakefile +7 -15
- data/TODO +5 -0
- data/lib/redis_orm/associations/belongs_to.rb +37 -3
- data/lib/redis_orm/associations/has_one.rb +32 -0
- data/lib/redis_orm/redis_orm.rb +47 -9
- data/redis_orm.gemspec +4 -4
- data/test/association_indices_test.rb +51 -28
- data/test/associations_test.rb +0 -59
- data/test/atomicity_test.rb +0 -7
- data/test/basic_functionality_test.rb +12 -28
- data/test/callbacks_test.rb +0 -70
- data/test/changes_array_test.rb +0 -6
- data/test/classes/album.rb +6 -0
- data/test/classes/article.rb +7 -0
- data/test/classes/book.rb +6 -0
- data/test/classes/catalog_item.rb +5 -0
- data/test/classes/category.rb +7 -0
- data/test/classes/city.rb +7 -0
- data/test/classes/comment.rb +26 -0
- data/test/classes/country.rb +5 -0
- data/test/classes/custom_user.rb +8 -0
- data/test/classes/cutout.rb +20 -0
- data/test/classes/cutout_aggregator.rb +5 -0
- data/test/classes/default_user.rb +10 -0
- data/test/classes/dynamic_finder_user.rb +8 -0
- data/test/classes/empty_person.rb +2 -0
- data/test/classes/giftcard.rb +6 -0
- data/test/classes/jigsaw.rb +4 -0
- data/test/classes/location.rb +5 -0
- data/test/classes/message.rb +4 -0
- data/test/classes/note.rb +5 -0
- data/test/classes/omni_user.rb +8 -0
- data/test/classes/person.rb +6 -0
- data/test/classes/photo.rb +21 -0
- data/test/classes/profile.rb +8 -0
- data/test/classes/sortable_user.rb +11 -0
- data/test/classes/timestamp.rb +3 -0
- data/test/classes/user.rb +39 -0
- data/test/classes/uuid_default_user.rb +12 -0
- data/test/classes/uuid_timestamp.rb +5 -0
- data/test/classes/uuid_user.rb +13 -0
- data/test/dynamic_finders_test.rb +9 -26
- data/test/exceptions_test.rb +1 -21
- data/test/has_one_has_many_test.rb +0 -12
- data/test/indices_test.rb +0 -18
- data/test/modules/belongs_to_model_within_module.rb +6 -0
- data/test/modules/has_many_model_within_module.rb +11 -0
- data/test/options_test.rb +0 -37
- data/test/polymorphic_test.rb +0 -39
- data/test/sortable_test.rb +60 -74
- data/test/test_helper.rb +4 -0
- data/test/uuid_as_id_test.rb +38 -70
- data/test/validations_test.rb +0 -8
- 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.
|
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
|
-
|
18
|
-
#$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
|
18
|
+
task :default => :test
|
19
19
|
|
20
|
-
|
21
|
-
desc 'Test the redis_orm gem.'
|
20
|
+
desc 'Test the redis_orm functionality'
|
22
21
|
Rake::TestTask.new(:test) do |t|
|
23
|
-
|
24
|
-
t.
|
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?
|
data/lib/redis_orm/redis_orm.rb
CHANGED
@@ -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
|
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,
|
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
|
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
|
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]}",
|
606
|
-
instance_variable_set :"@#{prop[:name]}_changes", [
|
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.
|
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{
|
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
|
-
|
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
|
data/test/associations_test.rb
CHANGED
@@ -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"
|