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.
- 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"
|