toystore 0.5
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/.autotest +11 -0
- data/.bundle/config +2 -0
- data/.gitignore +6 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +49 -0
- data/LICENSE +9 -0
- data/LOGGING.rdoc +16 -0
- data/README.rdoc +13 -0
- data/Rakefile +7 -0
- data/examples/memcached.rb +20 -0
- data/examples/memory.rb +20 -0
- data/examples/models.rb +51 -0
- data/examples/redis.rb +20 -0
- data/lib/toy.rb +81 -0
- data/lib/toy/attribute.rb +73 -0
- data/lib/toy/attributes.rb +137 -0
- data/lib/toy/caching.rb +20 -0
- data/lib/toy/callbacks.rb +48 -0
- data/lib/toy/collection.rb +55 -0
- data/lib/toy/connection.rb +28 -0
- data/lib/toy/dirty.rb +47 -0
- data/lib/toy/dolly.rb +30 -0
- data/lib/toy/embedded_list.rb +45 -0
- data/lib/toy/embedded_lists.rb +68 -0
- data/lib/toy/equality.rb +19 -0
- data/lib/toy/exceptions.rb +29 -0
- data/lib/toy/extensions/array.rb +22 -0
- data/lib/toy/extensions/boolean.rb +43 -0
- data/lib/toy/extensions/date.rb +24 -0
- data/lib/toy/extensions/float.rb +13 -0
- data/lib/toy/extensions/hash.rb +17 -0
- data/lib/toy/extensions/integer.rb +22 -0
- data/lib/toy/extensions/nil_class.rb +17 -0
- data/lib/toy/extensions/object.rb +26 -0
- data/lib/toy/extensions/set.rb +23 -0
- data/lib/toy/extensions/string.rb +17 -0
- data/lib/toy/extensions/time.rb +29 -0
- data/lib/toy/identity.rb +26 -0
- data/lib/toy/identity/abstract_key_factory.rb +10 -0
- data/lib/toy/identity/uuid_key_factory.rb +9 -0
- data/lib/toy/identity_map.rb +109 -0
- data/lib/toy/index.rb +74 -0
- data/lib/toy/indices.rb +56 -0
- data/lib/toy/inspect.rb +12 -0
- data/lib/toy/list.rb +46 -0
- data/lib/toy/lists.rb +37 -0
- data/lib/toy/logger.rb +26 -0
- data/lib/toy/mass_assignment_security.rb +16 -0
- data/lib/toy/persistence.rb +138 -0
- data/lib/toy/plugins.rb +23 -0
- data/lib/toy/proxies/embedded_list.rb +74 -0
- data/lib/toy/proxies/list.rb +97 -0
- data/lib/toy/proxies/proxy.rb +59 -0
- data/lib/toy/querying.rb +57 -0
- data/lib/toy/reference.rb +134 -0
- data/lib/toy/references.rb +19 -0
- data/lib/toy/serialization.rb +81 -0
- data/lib/toy/store.rb +36 -0
- data/lib/toy/timestamps.rb +22 -0
- data/lib/toy/validations.rb +45 -0
- data/lib/toy/version.rb +3 -0
- data/lib/toystore.rb +1 -0
- data/spec/helper.rb +35 -0
- data/spec/spec.opts +3 -0
- data/spec/support/constants.rb +41 -0
- data/spec/support/identity_map_matcher.rb +20 -0
- data/spec/support/name_and_number_key_factory.rb +5 -0
- data/spec/toy/attribute_spec.rb +176 -0
- data/spec/toy/attributes_spec.rb +394 -0
- data/spec/toy/caching_spec.rb +62 -0
- data/spec/toy/callbacks_spec.rb +97 -0
- data/spec/toy/connection_spec.rb +47 -0
- data/spec/toy/dirty_spec.rb +99 -0
- data/spec/toy/dolly_spec.rb +76 -0
- data/spec/toy/embedded_list_spec.rb +607 -0
- data/spec/toy/embedded_lists_spec.rb +172 -0
- data/spec/toy/equality_spec.rb +46 -0
- data/spec/toy/exceptions_spec.rb +18 -0
- data/spec/toy/extensions/array_spec.rb +25 -0
- data/spec/toy/extensions/boolean_spec.rb +41 -0
- data/spec/toy/extensions/date_spec.rb +48 -0
- data/spec/toy/extensions/float_spec.rb +14 -0
- data/spec/toy/extensions/hash_spec.rb +21 -0
- data/spec/toy/extensions/integer_spec.rb +29 -0
- data/spec/toy/extensions/nil_class_spec.rb +14 -0
- data/spec/toy/extensions/set_spec.rb +27 -0
- data/spec/toy/extensions/string_spec.rb +28 -0
- data/spec/toy/extensions/time_spec.rb +94 -0
- data/spec/toy/identity/abstract_key_factory_spec.rb +7 -0
- data/spec/toy/identity/uuid_key_factory_spec.rb +7 -0
- data/spec/toy/identity_map_spec.rb +150 -0
- data/spec/toy/identity_spec.rb +52 -0
- data/spec/toy/index_spec.rb +230 -0
- data/spec/toy/indices_spec.rb +141 -0
- data/spec/toy/inspect_spec.rb +15 -0
- data/spec/toy/list_spec.rb +576 -0
- data/spec/toy/lists_spec.rb +95 -0
- data/spec/toy/logger_spec.rb +33 -0
- data/spec/toy/mass_assignment_security_spec.rb +116 -0
- data/spec/toy/persistence_spec.rb +312 -0
- data/spec/toy/plugins_spec.rb +39 -0
- data/spec/toy/querying_spec.rb +162 -0
- data/spec/toy/reference_spec.rb +400 -0
- data/spec/toy/references_spec.rb +86 -0
- data/spec/toy/serialization_spec.rb +354 -0
- data/spec/toy/store_spec.rb +41 -0
- data/spec/toy/timestamps_spec.rb +63 -0
- data/spec/toy/validations_spec.rb +171 -0
- data/spec/toy_spec.rb +26 -0
- data/specs.watchr +52 -0
- data/test/lint_test.rb +40 -0
- data/toystore.gemspec +24 -0
- metadata +290 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe "String.to_store" do
|
4
|
+
it "should convert value to_s" do
|
5
|
+
[21, '21'].each do |value|
|
6
|
+
String.to_store(value).should == '21'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be nil if nil" do
|
11
|
+
String.to_store(nil).should be_nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "String.from_store" do
|
16
|
+
it "should be string if value present" do
|
17
|
+
String.from_store('Scotch! Scotch! Scotch!').should == 'Scotch! Scotch! Scotch!'
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return nil if nil" do
|
21
|
+
String.from_store(nil).should be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return empty string if blank" do
|
25
|
+
String.from_store('').should == ''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe "Time.to_store without Time.zone" do
|
4
|
+
before :each do
|
5
|
+
Time.zone = nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be time to milliseconds if string" do
|
9
|
+
Time.to_store('2000-01-01 01:01:01.123456').to_f.should == Time.local(2000, 1, 1, 1, 1, 1, 0).utc.to_f
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be time in utc if time" do
|
13
|
+
Time.to_store(Time.local(2009, 8, 15, 0, 0, 0)).zone.should == 'UTC'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be nil if blank string" do
|
17
|
+
Time.to_store('').should be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not be nil if nil" do
|
21
|
+
Time.to_store(nil).should be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "Time.to_store with Time.zone" do
|
26
|
+
it "should be time to milliseconds if time" do
|
27
|
+
Time.zone = 'Hawaii'
|
28
|
+
Time.to_store(Time.zone.local(2009, 8, 15, 14, 0, 0, 123456)).to_f.should == Time.utc(2009, 8, 16, 0, 0, 0, 0).to_f
|
29
|
+
Time.zone = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be time to milliseconds if string" do
|
33
|
+
Time.zone = 'Hawaii'
|
34
|
+
Time.to_store('2009-08-15 14:00:00.123456').to_f.should == Time.utc(2009, 8, 16, 0, 0, 0, 0).to_f
|
35
|
+
Time.zone = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not round up times at the end of the month" do
|
39
|
+
Time.to_store(Time.now.end_of_month).to_i.should == Time.now.end_of_month.utc.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be nil if blank string" do
|
43
|
+
Time.zone = 'Hawaii'
|
44
|
+
Time.to_store('').should be_nil
|
45
|
+
Time.zone = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be nil if nil" do
|
49
|
+
Time.zone = 'Hawaii'
|
50
|
+
Time.to_store(nil).should be_nil
|
51
|
+
Time.zone = nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "Time.from_store without Time.zone" do
|
56
|
+
it "should be time in utc" do
|
57
|
+
time = Time.now
|
58
|
+
Time.from_store(time).should be_within(1).of(time.utc)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should be time if string" do
|
62
|
+
time = Time.now
|
63
|
+
Time.from_store(time.to_s).should be_within(1).of(time)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should be nil if nil" do
|
67
|
+
Time.from_store(nil).should be_nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "Time.from_store with Time.zone" do
|
72
|
+
before do
|
73
|
+
Time.zone = 'Hawaii'
|
74
|
+
end
|
75
|
+
|
76
|
+
after do
|
77
|
+
Time.zone = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should be time in Time.zone" do
|
81
|
+
time = Time.from_store(Time.utc(2009, 10, 1))
|
82
|
+
time.should == Time.zone.local(2009, 9, 30, 14)
|
83
|
+
time.is_a?(ActiveSupport::TimeWithZone).should be_true
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be time if string" do
|
87
|
+
time = Time.zone.now
|
88
|
+
Time.from_store(time.to_s).should be_within(1).of(time)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should be nil if nil" do
|
92
|
+
Time.from_store(nil).should be_nil
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Toy::IdentityMap do
|
4
|
+
uses_constants('User', 'Skill')
|
5
|
+
|
6
|
+
before do
|
7
|
+
Toy.identity_map.clear
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".identity_map" do
|
11
|
+
it "defaults to hash" do
|
12
|
+
User.identity_map.should == {}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "memoizes" do
|
16
|
+
User.identity_map.should equal(User.identity_map)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "adds to map on save" do
|
21
|
+
user = User.new
|
22
|
+
user.save!
|
23
|
+
user.should be_in_identity_map
|
24
|
+
end
|
25
|
+
|
26
|
+
it "adds to map on load" do
|
27
|
+
user = User.load({'id' => '1'})
|
28
|
+
user.should be_in_identity_map
|
29
|
+
end
|
30
|
+
|
31
|
+
it "removes from map on delete" do
|
32
|
+
user = User.create
|
33
|
+
user.should be_in_identity_map
|
34
|
+
user.delete
|
35
|
+
user.should_not be_in_identity_map
|
36
|
+
end
|
37
|
+
|
38
|
+
it "removes from map on destroy" do
|
39
|
+
user = User.create
|
40
|
+
user.should be_in_identity_map
|
41
|
+
user.destroy
|
42
|
+
user.should_not be_in_identity_map
|
43
|
+
end
|
44
|
+
|
45
|
+
describe ".get" do
|
46
|
+
it "adds to map if not in map" do
|
47
|
+
user = User.create
|
48
|
+
user.identity_map.clear
|
49
|
+
user.should_not be_in_identity_map
|
50
|
+
user = User.get(user.id)
|
51
|
+
user.should be_in_identity_map
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns from map if in map" do
|
55
|
+
user = User.create
|
56
|
+
user.should be_in_identity_map
|
57
|
+
User.get(user.id).should equal(user)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not query if in map" do
|
61
|
+
user = User.create
|
62
|
+
user.should be_in_identity_map
|
63
|
+
user.store.should_not_receive(:read)
|
64
|
+
User.get(user.id).should equal(user)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#reload" do
|
69
|
+
it "forces new query each time and skips the identity map" do
|
70
|
+
user = User.create
|
71
|
+
user.should be_in_identity_map
|
72
|
+
User.store.should_receive(:read).with(user.store_key).and_return({})
|
73
|
+
user.reload
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "identity map off" do
|
78
|
+
it "does not add to map on save" do
|
79
|
+
User.identity_map_off
|
80
|
+
user = User.new
|
81
|
+
user.save!
|
82
|
+
user.should_not be_in_identity_map
|
83
|
+
end
|
84
|
+
|
85
|
+
it "does not add to map on load" do
|
86
|
+
User.identity_map_off
|
87
|
+
user = User.load('id' => '1')
|
88
|
+
user.should_not be_in_identity_map
|
89
|
+
end
|
90
|
+
|
91
|
+
it "does not remove from map on delete" do
|
92
|
+
user = User.create
|
93
|
+
user.should be_in_identity_map
|
94
|
+
User.identity_map_off
|
95
|
+
user.delete
|
96
|
+
user.should be_in_identity_map
|
97
|
+
end
|
98
|
+
|
99
|
+
it "does not remove from map on destroy" do
|
100
|
+
user = User.create
|
101
|
+
user.should be_in_identity_map
|
102
|
+
User.identity_map_off
|
103
|
+
user.destroy
|
104
|
+
user.should be_in_identity_map
|
105
|
+
end
|
106
|
+
|
107
|
+
describe ".get" do
|
108
|
+
it "does not add to map if not in map" do
|
109
|
+
User.identity_map_off
|
110
|
+
user = User.create
|
111
|
+
user.should_not be_in_identity_map
|
112
|
+
user = User.get(user.id)
|
113
|
+
user.should_not be_in_identity_map
|
114
|
+
end
|
115
|
+
|
116
|
+
it "does not load from map if in map" do
|
117
|
+
user = User.create
|
118
|
+
user.should be_in_identity_map
|
119
|
+
User.identity_map_off
|
120
|
+
user.store.should_receive(:read).with(user.store_key).and_return(user.persisted_attributes)
|
121
|
+
User.get(user.id)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe ".without_identity_map" do
|
127
|
+
describe "with identity map off" do
|
128
|
+
it "turns identity map off, yields, and returns it to previous state" do
|
129
|
+
User.identity_map_off
|
130
|
+
User.should be_identity_map_off
|
131
|
+
User.without_identity_map do
|
132
|
+
user = User.create
|
133
|
+
user.should_not be_in_identity_map
|
134
|
+
end
|
135
|
+
User.should be_identity_map_off
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "with identity map on" do
|
140
|
+
it "turns identity map off, yields, and returns it to previous state" do
|
141
|
+
User.should be_identity_map_on
|
142
|
+
User.without_identity_map do
|
143
|
+
user = User.create
|
144
|
+
user.should_not be_in_identity_map
|
145
|
+
end
|
146
|
+
User.should be_identity_map_on
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Toy::Identity do
|
4
|
+
uses_constants('User', 'Piece')
|
5
|
+
|
6
|
+
describe "setting the key" do
|
7
|
+
it "should set key factory to UUIDKeyFactory" do
|
8
|
+
User.key(:uuid).should be_instance_of(Toy::Identity::UUIDKeyFactory)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should set key factory passed in factory" do
|
12
|
+
factory = Toy::Identity::UUIDKeyFactory
|
13
|
+
User.key(factory).should == factory
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should use Toy.key_factory by default" do
|
17
|
+
key_factory = mock
|
18
|
+
Toy.key_factory = key_factory
|
19
|
+
klass = Class.new { include Toy::Store }
|
20
|
+
|
21
|
+
key_factory.should_receive(:next_key).and_return('some_key')
|
22
|
+
klass.next_key
|
23
|
+
|
24
|
+
Toy.key_factory = nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".next_key" do
|
29
|
+
it "should call the next key on the key factory" do
|
30
|
+
factory = Toy::Identity::UUIDKeyFactory
|
31
|
+
factory.should_receive(:next_key).and_return('some_key')
|
32
|
+
User.key(factory)
|
33
|
+
User.next_key.should == 'some_key'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should raise an exception for nil key" do
|
37
|
+
factory = Toy::Identity::UUIDKeyFactory
|
38
|
+
factory.should_receive(:next_key).and_return(nil)
|
39
|
+
User.key(factory)
|
40
|
+
lambda { User.next_key }.should raise_error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "initializing the id" do
|
45
|
+
it "should pass use pass the new object" do
|
46
|
+
Piece.attribute(:name, String)
|
47
|
+
Piece.attribute(:number, Integer)
|
48
|
+
Piece.key(NameAndNumberKeyFactory.new)
|
49
|
+
Piece.new(:name => 'Rook', :number => 1).id.should == 'Rook-1'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Toy::Index do
|
4
|
+
uses_constants('User', 'Student', 'Friendship')
|
5
|
+
|
6
|
+
before do
|
7
|
+
User.attribute(:ssn, String)
|
8
|
+
@index = User.index(:ssn)
|
9
|
+
end
|
10
|
+
let(:index) { @index }
|
11
|
+
|
12
|
+
it "has a model" do
|
13
|
+
index.model.should == User
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has a name" do
|
17
|
+
index.name.should == :ssn
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises error if attribute does not exist" do
|
21
|
+
lambda {
|
22
|
+
User.index :student_id
|
23
|
+
}.should raise_error(ArgumentError, "No attribute student_id for index")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "has a sha1'd key for a value" do
|
27
|
+
index.key('some_value').should == 'User:ssn:8c818171573b03feeae08b0b4ffeb6999e3afc05'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "adds index to model" do
|
31
|
+
User.indices.keys.should include(:ssn)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#eql?" do
|
35
|
+
it "returns true if same class, model, and name" do
|
36
|
+
index.should eql(index)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns false if not same class" do
|
40
|
+
index.should_not eql({})
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns false if not same model" do
|
44
|
+
Student.attribute :ssn, String
|
45
|
+
index.should_not eql(Toy::Index.new(Student, :ssn))
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns false if not the same name" do
|
49
|
+
User.attribute :student_id, String
|
50
|
+
index.should_not eql(Toy::Index.new(User, :student_id))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "single key" do
|
55
|
+
describe "creating with index" do
|
56
|
+
before do
|
57
|
+
@user = User.create(:ssn => '555-00-1234')
|
58
|
+
end
|
59
|
+
let(:user) { @user }
|
60
|
+
|
61
|
+
it "creates key for indexed value" do
|
62
|
+
User.store.should be_key("User:ssn:f6edc9155d79e311ad2d4a6e1b54004f31497f4c")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "adds instance id to index array" do
|
66
|
+
User.get_index(:ssn, '555-00-1234').should == [user.id]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "creating second record for same index value" do
|
71
|
+
before do
|
72
|
+
@user1 = User.create(:ssn => '555-00-1234')
|
73
|
+
@user2 = User.create(:ssn => '555-00-1234')
|
74
|
+
end
|
75
|
+
|
76
|
+
it "adds both instances to index" do
|
77
|
+
User.get_index(:ssn, '555-00-1234').should == [@user1.id, @user2.id]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "destroying with index" do
|
82
|
+
before do
|
83
|
+
@user = User.create(:ssn => '555-00-1234')
|
84
|
+
@user.destroy
|
85
|
+
end
|
86
|
+
|
87
|
+
it "removes id from index" do
|
88
|
+
User.get_index(:ssn, '555-00-1234').should == []
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "updating record and changing indexed value" do
|
93
|
+
before do
|
94
|
+
@user = User.create(:ssn => '555-00-1234')
|
95
|
+
@user.update_attributes(:ssn => '555-00-4321')
|
96
|
+
end
|
97
|
+
|
98
|
+
it "removes from old index" do
|
99
|
+
User.get_index(:ssn, '555-00-1234').should == []
|
100
|
+
end
|
101
|
+
|
102
|
+
it "adds to new index" do
|
103
|
+
User.get_index(:ssn, '555-00-4321').should == [@user.id]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "updating record without changing indexed value" do
|
108
|
+
before do
|
109
|
+
@user = User.create(:ssn => '555-00-1234')
|
110
|
+
@user.update_attributes(:ssn => '555-00-1234')
|
111
|
+
end
|
112
|
+
|
113
|
+
it "leaves index alone" do
|
114
|
+
User.get_index(:ssn, '555-00-1234').should == [@user.id]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "first by index" do
|
119
|
+
it "should not find values that are not in index" do
|
120
|
+
User.first_by_ssn('does-not-exist').should be_nil
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should find indexed value" do
|
124
|
+
user = User.create(:ssn => '555-00-1234')
|
125
|
+
User.first_by_ssn('555-00-1234').should == user
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "first or new by index" do
|
130
|
+
it "initializes if not existing" do
|
131
|
+
user = User.first_or_new_by_ssn('does-not-exist')
|
132
|
+
user.ssn.should == 'does-not-exist'
|
133
|
+
user.should_not be_persisted
|
134
|
+
end
|
135
|
+
|
136
|
+
it "returns if existing" do
|
137
|
+
user = User.create(:ssn => '555-00-1234')
|
138
|
+
User.first_or_new_by_ssn('555-00-1234').should == user
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "first or create by index" do
|
143
|
+
it "creates if not existing" do
|
144
|
+
user = User.first_or_create_by_ssn('does-not-exist')
|
145
|
+
user.ssn.should == 'does-not-exist'
|
146
|
+
user.should be_persisted
|
147
|
+
end
|
148
|
+
|
149
|
+
it "returns if existing" do
|
150
|
+
user = User.create(:ssn => '555-00-1234')
|
151
|
+
User.first_or_create_by_ssn('555-00-1234').should == user
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "array key" do
|
157
|
+
before do
|
158
|
+
User.list :friendships
|
159
|
+
Friendship.list :users
|
160
|
+
Friendship.index :user_ids
|
161
|
+
@user1 = User.create(:ssn => '555-00-1234')
|
162
|
+
@user2 = User.create(:ssn => '555-00-9876')
|
163
|
+
@friendship = Friendship.create(:user_ids => [@user1.id, @user2.id])
|
164
|
+
end
|
165
|
+
let(:user1) { @user1 }
|
166
|
+
let(:user2) { @user2 }
|
167
|
+
let(:friendship) { @friendship }
|
168
|
+
|
169
|
+
describe "creating with index" do
|
170
|
+
it "creates key for indexed values sorted" do
|
171
|
+
sha_value = Digest::SHA1.hexdigest([user1.id, user2.id].sort.join(''))
|
172
|
+
Friendship.store.should be_key("Friendship:user_ids:#{sha_value}")
|
173
|
+
end
|
174
|
+
|
175
|
+
it "adds instance id to index array" do
|
176
|
+
Friendship.get_index(:user_ids, [user1.id, user2.id]).should == [friendship.id]
|
177
|
+
Friendship.get_index(:user_ids, [user2.id, user1.id]).should == [friendship.id]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "destroying with index" do
|
182
|
+
before do
|
183
|
+
friendship.destroy
|
184
|
+
end
|
185
|
+
|
186
|
+
it "removes id from index" do
|
187
|
+
Friendship.get_index(:user_ids, [user2.id, user1.id]).should == []
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "first by index" do
|
192
|
+
it "should not find values that are not in index" do
|
193
|
+
Friendship.first_by_user_ids([user1.id, 'does-not-exist']).should be_nil
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should find indexed value" do
|
197
|
+
Friendship.first_by_user_ids([user1.id, user2.id]).should == friendship
|
198
|
+
Friendship.first_by_user_ids([user2.id, user1.id]).should == friendship
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "first or new by index" do
|
203
|
+
it "initializes if not existing" do
|
204
|
+
new_friend = User.create(:ssn => '555-00-1928')
|
205
|
+
new_friendship = Friendship.first_or_new_by_user_ids([user1.id, new_friend.id])
|
206
|
+
new_friendship.user_ids.sort.should == [user1.id, new_friend.id].sort
|
207
|
+
new_friendship.should_not be_persisted
|
208
|
+
end
|
209
|
+
|
210
|
+
it "returns if existing" do
|
211
|
+
Friendship.first_or_new_by_user_ids([user1.id, user2.id]).should == friendship
|
212
|
+
Friendship.first_or_new_by_user_ids([user2.id, user1.id]).should == friendship
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "first or create by index" do
|
217
|
+
it "creates if not existing" do
|
218
|
+
new_friend = User.create(:ssn => '555-00-1928')
|
219
|
+
new_friendship = Friendship.first_or_create_by_user_ids([user1.id, new_friend.id])
|
220
|
+
new_friendship.user_ids.sort.should == [user1.id, new_friend.id].sort
|
221
|
+
new_friendship.should be_persisted
|
222
|
+
end
|
223
|
+
|
224
|
+
it "returns if existing" do
|
225
|
+
Friendship.first_or_create_by_user_ids([user1.id, user2.id]).should == friendship
|
226
|
+
Friendship.first_or_create_by_user_ids([user2.id, user1.id]).should == friendship
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|