toystore 0.8.3 → 0.9.0
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/.gitignore +1 -2
- data/Changelog.md +9 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +71 -0
- data/Guardfile +15 -0
- data/README.md +28 -0
- data/examples/attributes_abbreviation.rb +1 -2
- data/examples/attributes_virtual.rb +1 -2
- data/examples/identity_map.rb +7 -12
- data/examples/memcached.rb +1 -1
- data/examples/memory.rb +1 -1
- data/examples/mongo.rb +1 -1
- data/examples/redis.rb +1 -1
- data/examples/riak.rb +1 -1
- data/lib/toy.rb +40 -39
- data/lib/toy/attribute.rb +1 -6
- data/lib/toy/attributes.rb +61 -90
- data/lib/toy/caching.rb +11 -13
- data/lib/toy/callbacks.rb +12 -31
- data/lib/toy/cloneable.rb +20 -0
- data/lib/toy/collection.rb +8 -7
- data/lib/toy/dirty.rb +17 -36
- data/lib/toy/dirty_store.rb +32 -0
- data/lib/toy/equality.rb +2 -0
- data/lib/toy/extensions/boolean.rb +22 -18
- data/lib/toy/identity_map.rb +39 -62
- data/lib/toy/list.rb +23 -22
- data/lib/toy/logger.rb +2 -17
- data/lib/toy/mass_assignment_security.rb +3 -5
- data/lib/toy/middleware/identity_map.rb +23 -4
- data/lib/toy/object.rb +16 -0
- data/lib/toy/persistence.rb +72 -62
- data/lib/toy/proxies/list.rb +19 -18
- data/lib/toy/proxies/proxy.rb +7 -6
- data/lib/toy/querying.rb +2 -4
- data/lib/toy/reference.rb +28 -26
- data/lib/toy/reloadable.rb +17 -0
- data/lib/toy/serialization.rb +25 -25
- data/lib/toy/store.rb +3 -11
- data/lib/toy/validations.rb +9 -28
- data/lib/toy/version.rb +1 -1
- data/perf/reads.rb +7 -9
- data/perf/writes.rb +6 -8
- data/spec/helper.rb +3 -1
- data/spec/support/constants.rb +1 -4
- data/spec/support/identity_map_matcher.rb +5 -5
- data/spec/support/objects.rb +38 -0
- data/spec/toy/attribute_spec.rb +1 -1
- data/spec/toy/attributes_spec.rb +1 -153
- data/spec/toy/callbacks_spec.rb +1 -45
- data/spec/toy/cloneable_spec.rb +47 -0
- data/spec/toy/dirty_spec.rb +12 -44
- data/spec/toy/dirty_store_spec.rb +47 -0
- data/spec/toy/equality_spec.rb +5 -19
- data/spec/toy/extensions/boolean_spec.rb +2 -0
- data/spec/toy/identity/uuid_key_factory_spec.rb +2 -2
- data/spec/toy/identity_map_spec.rb +45 -37
- data/spec/toy/identity_spec.rb +1 -1
- data/spec/toy/inspect_spec.rb +1 -1
- data/spec/toy/lists_spec.rb +20 -5
- data/spec/toy/logger_spec.rb +1 -29
- data/spec/toy/mass_assignment_security_spec.rb +16 -5
- data/spec/toy/middleware/identity_map_spec.rb +68 -2
- data/spec/toy/persistence_spec.rb +88 -30
- data/spec/toy/reference_spec.rb +0 -1
- data/spec/toy/references_spec.rb +20 -0
- data/spec/toy/reloadable_spec.rb +81 -0
- data/spec/toy/serialization_spec.rb +1 -110
- data/spec/toy/validations_spec.rb +0 -21
- data/spec/toy_spec.rb +4 -5
- data/test/lint_test.rb +1 -1
- metadata +21 -26
- data/.autotest +0 -11
- data/LOGGING.rdoc +0 -12
- data/README.rdoc +0 -27
- data/examples/models.rb +0 -51
- data/lib/toy/dolly.rb +0 -30
- data/lib/toy/embedded_list.rb +0 -45
- data/lib/toy/embedded_lists.rb +0 -68
- data/lib/toy/index.rb +0 -74
- data/lib/toy/indices.rb +0 -56
- data/lib/toy/proxies/embedded_list.rb +0 -79
- data/spec/toy/dolly_spec.rb +0 -76
- data/spec/toy/embedded_list_spec.rb +0 -607
- data/spec/toy/embedded_lists_spec.rb +0 -172
- data/spec/toy/index_spec.rb +0 -230
- data/spec/toy/indices_spec.rb +0 -141
- data/specs.watchr +0 -52
data/spec/toy/callbacks_spec.rb
CHANGED
@@ -24,7 +24,7 @@ module CallbackHelper
|
|
24
24
|
end
|
25
25
|
|
26
26
|
describe Toy::Callbacks do
|
27
|
-
uses_constants('Game'
|
27
|
+
uses_constants('Game')
|
28
28
|
|
29
29
|
context "regular" do
|
30
30
|
before do
|
@@ -50,48 +50,4 @@ describe Toy::Callbacks do
|
|
50
50
|
doc.history.should == [:before_destroy, :after_destroy]
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
54
|
-
context "embedded" do
|
55
|
-
before do
|
56
|
-
Game.embedded_list(:moves)
|
57
|
-
Move.send(:include, CallbackHelper)
|
58
|
-
|
59
|
-
@move = Move.new
|
60
|
-
@game = Game.create(:moves => [@move])
|
61
|
-
end
|
62
|
-
|
63
|
-
it "runs callbacks for save of parent" do
|
64
|
-
@move.history.should == [:before_save, :before_create, :after_create, :after_save]
|
65
|
-
end
|
66
|
-
|
67
|
-
it "runs callbacks for update of parent" do
|
68
|
-
@move.clear_history
|
69
|
-
@game.save
|
70
|
-
@move.history.should == [:before_save, :before_update, :after_update, :after_save]
|
71
|
-
end
|
72
|
-
|
73
|
-
it "runs callbacks for destroy of parent" do
|
74
|
-
@move.clear_history
|
75
|
-
@game.destroy
|
76
|
-
@move.history.should == [:before_destroy, :after_destroy]
|
77
|
-
end
|
78
|
-
|
79
|
-
it "does not attempt to run callback defined on parent that is not defined on embedded" do
|
80
|
-
Game.define_callbacks :win
|
81
|
-
@move.clear_history
|
82
|
-
|
83
|
-
lambda do
|
84
|
-
@game.run_callbacks(:win)
|
85
|
-
@move.history.should be_empty
|
86
|
-
end.should_not raise_error
|
87
|
-
end
|
88
|
-
|
89
|
-
it "runs create callback when saving new embbeded doc on existing parent" do
|
90
|
-
@game.save
|
91
|
-
move = Move.new
|
92
|
-
@game.moves << move
|
93
|
-
@game.save
|
94
|
-
move.history.should == [:before_save, :before_create, :after_create, :after_save]
|
95
|
-
end
|
96
|
-
end
|
97
53
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Toy::Cloneable do
|
4
|
+
uses_objects('User')
|
5
|
+
|
6
|
+
before do
|
7
|
+
User.attribute(:name, String)
|
8
|
+
User.attribute(:skills, Array)
|
9
|
+
|
10
|
+
@user = User.new({
|
11
|
+
:name => 'John',
|
12
|
+
:skills => ['looking awesome', 'growing beards'],
|
13
|
+
})
|
14
|
+
end
|
15
|
+
let(:user) { @user }
|
16
|
+
|
17
|
+
describe "#clone" do
|
18
|
+
it "clones the @attributes hash" do
|
19
|
+
user.clone.instance_variable_get("@attributes").should_not equal(user.instance_variable_get("@attributes"))
|
20
|
+
end
|
21
|
+
|
22
|
+
it "copies the attributes" do
|
23
|
+
user.clone.tap do |clone|
|
24
|
+
clone.name.should == user.name
|
25
|
+
clone.skills.should == user.skills
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "clones duplicable attributes" do
|
30
|
+
user.clone.skills.should_not equal(user.skills)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "regenerates id" do
|
34
|
+
user.clone.tap do |clone|
|
35
|
+
clone.id.should_not be_nil
|
36
|
+
clone.id.should_not == user.id
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "nullifies defined instance variables" do
|
41
|
+
user.instance_variable_set("@foo", true)
|
42
|
+
user.clone.tap do |clone|
|
43
|
+
clone.instance_variable_get("@foo").should be_nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/toy/dirty_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Toy::Dirty do
|
4
|
-
|
4
|
+
uses_objects('User')
|
5
5
|
|
6
6
|
before do
|
7
7
|
User.attribute(:name, String)
|
@@ -29,49 +29,11 @@ describe Toy::Dirty do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
it "knows when attribute did not change" do
|
32
|
-
user = User.
|
33
|
-
user.name =
|
32
|
+
user = User.new
|
33
|
+
user.name = nil
|
34
34
|
user.should_not be_changed
|
35
35
|
end
|
36
36
|
|
37
|
-
describe "#save" do
|
38
|
-
before { @user = User.create(:name => 'Geoffrey') }
|
39
|
-
let(:user) { @user }
|
40
|
-
|
41
|
-
it "clears changes" do
|
42
|
-
user.name = 'John'
|
43
|
-
user.should be_changed
|
44
|
-
user.save
|
45
|
-
user.should_not be_changed
|
46
|
-
end
|
47
|
-
|
48
|
-
it "sets previous changes" do
|
49
|
-
user.previous_changes.should == {'name' => [nil, 'Geoffrey']}
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
it "does not have changes when loaded from database" do
|
54
|
-
user = User.create
|
55
|
-
loaded = User.get(user.id)
|
56
|
-
loaded.should_not be_changed
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "#reload" do
|
60
|
-
before { @user = User.create(:name => 'John') }
|
61
|
-
let(:user) { @user }
|
62
|
-
|
63
|
-
it "clears changes" do
|
64
|
-
user.name = 'Steve'
|
65
|
-
user.reload
|
66
|
-
user.should_not be_changed
|
67
|
-
end
|
68
|
-
|
69
|
-
it "clears previously changed" do
|
70
|
-
user.reload
|
71
|
-
user.previous_changes.should be_empty
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
37
|
it "has attribute changed? method" do
|
76
38
|
user = User.new
|
77
39
|
user.should_not be_name_changed
|
@@ -80,20 +42,26 @@ describe Toy::Dirty do
|
|
80
42
|
end
|
81
43
|
|
82
44
|
it "has attribute was method" do
|
83
|
-
user = User.
|
45
|
+
user = User.new(:name => 'John')
|
84
46
|
user.name = 'Steve'
|
85
47
|
user.name_was.should == 'John'
|
86
48
|
end
|
87
49
|
|
88
50
|
it "has attribute change method" do
|
89
|
-
user = User.
|
51
|
+
user = User.new(:name => 'John')
|
90
52
|
user.name = 'Steve'
|
91
53
|
user.name_change.should == ['John', 'Steve']
|
92
54
|
end
|
93
55
|
|
94
56
|
it "has attribute will change! method" do
|
95
|
-
user = User.
|
57
|
+
user = User.new
|
96
58
|
user.name_will_change!
|
97
59
|
user.should be_changed
|
98
60
|
end
|
61
|
+
|
62
|
+
describe "#clone" do
|
63
|
+
it "has no changes" do
|
64
|
+
User.new.clone.should_not be_changed
|
65
|
+
end
|
66
|
+
end
|
99
67
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Toy::DirtyStore do
|
4
|
+
uses_constants('User')
|
5
|
+
|
6
|
+
before do
|
7
|
+
User.attribute(:name, String)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "does not have changes when loaded from database" do
|
11
|
+
user = User.create
|
12
|
+
loaded = User.get(user.id)
|
13
|
+
loaded.should_not be_changed
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#reload" do
|
17
|
+
before { @user = User.create(:name => 'John') }
|
18
|
+
let(:user) { @user }
|
19
|
+
|
20
|
+
it "clears changes" do
|
21
|
+
user.name = 'Steve'
|
22
|
+
user.reload
|
23
|
+
user.should_not be_changed
|
24
|
+
end
|
25
|
+
|
26
|
+
it "clears previously changed" do
|
27
|
+
user.reload
|
28
|
+
user.previous_changes.should be_empty
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#save" do
|
33
|
+
before { @user = User.create(:name => 'Geoffrey') }
|
34
|
+
let(:user) { @user }
|
35
|
+
|
36
|
+
it "clears changes" do
|
37
|
+
user.name = 'John'
|
38
|
+
user.should be_changed
|
39
|
+
user.save
|
40
|
+
user.should_not be_changed
|
41
|
+
end
|
42
|
+
|
43
|
+
it "sets previous changes" do
|
44
|
+
user.previous_changes.should == {'name' => [nil, 'Geoffrey']}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/toy/equality_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Toy::Equality do
|
4
|
-
|
4
|
+
uses_objects('User', 'Person')
|
5
5
|
|
6
6
|
describe "#eql?" do
|
7
7
|
it "returns true if same class and id" do
|
@@ -15,32 +15,18 @@ describe Toy::Equality do
|
|
15
15
|
it "returns false if different id" do
|
16
16
|
User.new(:id => 1).should_not eql(User.new(:id => 2))
|
17
17
|
end
|
18
|
-
|
19
|
-
it "returns true if reference and target is same class and id" do
|
20
|
-
Game.reference(:user)
|
21
|
-
user = User.create
|
22
|
-
game = Game.create(:user => user)
|
23
|
-
user.should eql(game.user)
|
24
|
-
end
|
25
18
|
end
|
26
19
|
|
27
20
|
describe "equal?" do
|
28
21
|
it "returns true if same object" do
|
29
|
-
user = User.
|
22
|
+
user = User.new(:id => 1)
|
30
23
|
user.should equal(user)
|
31
24
|
end
|
32
25
|
|
33
|
-
it "returns true if same object through proxy" do
|
34
|
-
Game.reference(:user)
|
35
|
-
user = User.create
|
36
|
-
game = Game.create(:user => user)
|
37
|
-
|
38
|
-
user.should equal(game.user)
|
39
|
-
game.user.should equal(user)
|
40
|
-
end
|
41
|
-
|
42
26
|
it "returns false if not same object" do
|
43
|
-
|
27
|
+
user = User.new
|
28
|
+
other_user = User.new
|
29
|
+
user.should_not equal(other_user)
|
44
30
|
end
|
45
31
|
end
|
46
32
|
end
|
@@ -13,11 +13,13 @@ describe "Boolean.to_store" do
|
|
13
13
|
Boolean.to_store('true').should be_true
|
14
14
|
Boolean.to_store('t').should be_true
|
15
15
|
Boolean.to_store('1').should be_true
|
16
|
+
Boolean.to_store('on').should be_true
|
16
17
|
Boolean.to_store(1).should be_true
|
17
18
|
|
18
19
|
Boolean.to_store('false').should be_false
|
19
20
|
Boolean.to_store('f').should be_false
|
20
21
|
Boolean.to_store('0').should be_false
|
22
|
+
Boolean.to_store('off').should be_false
|
21
23
|
Boolean.to_store(0).should be_false
|
22
24
|
end
|
23
25
|
|
@@ -3,11 +3,11 @@ require 'helper'
|
|
3
3
|
describe Toy::Identity::UUIDKeyFactory do
|
4
4
|
uses_constants('User')
|
5
5
|
|
6
|
-
it "should use String as
|
6
|
+
it "should use String as key_type" do
|
7
7
|
Toy::Identity::UUIDKeyFactory.new.key_type.should be(String)
|
8
8
|
end
|
9
9
|
|
10
|
-
it "should use uuid for
|
10
|
+
it "should use uuid for next_key" do
|
11
11
|
Toy::Identity::UUIDKeyFactory.new.next_key(nil).length.should == 36
|
12
12
|
end
|
13
13
|
|
@@ -4,17 +4,12 @@ describe Toy::IdentityMap do
|
|
4
4
|
uses_constants('User', 'Skill')
|
5
5
|
|
6
6
|
before do
|
7
|
-
Toy.
|
7
|
+
Toy::IdentityMap.enabled = true
|
8
|
+
Toy::IdentityMap.clear
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
User.identity_map.should == {}
|
13
|
-
end
|
14
|
-
|
15
|
-
it "memoizes" do
|
16
|
-
User.identity_map.should equal(User.identity_map)
|
17
|
-
end
|
11
|
+
after do
|
12
|
+
Toy::IdentityMap.enabled = false
|
18
13
|
end
|
19
14
|
|
20
15
|
it "adds to map on save" do
|
@@ -45,7 +40,7 @@ describe Toy::IdentityMap do
|
|
45
40
|
describe ".get" do
|
46
41
|
it "adds to map if not in map" do
|
47
42
|
user = User.create
|
48
|
-
|
43
|
+
Toy::IdentityMap.clear
|
49
44
|
user.should_not be_in_identity_map
|
50
45
|
user = User.get(user.id)
|
51
46
|
user.should be_in_identity_map
|
@@ -60,7 +55,7 @@ describe Toy::IdentityMap do
|
|
60
55
|
it "does not query if in map" do
|
61
56
|
user = User.create
|
62
57
|
user.should be_in_identity_map
|
63
|
-
user.
|
58
|
+
user.adapter.should_not_receive(:read)
|
64
59
|
User.get(user.id).should equal(user)
|
65
60
|
end
|
66
61
|
end
|
@@ -69,21 +64,21 @@ describe Toy::IdentityMap do
|
|
69
64
|
it "forces new query each time and skips the identity map" do
|
70
65
|
user = User.create
|
71
66
|
user.should be_in_identity_map
|
72
|
-
User.
|
67
|
+
User.adapter.should_receive(:read).with(user.id).and_return({})
|
73
68
|
user.reload
|
74
69
|
end
|
75
70
|
end
|
76
71
|
|
77
72
|
describe "identity map off" do
|
78
73
|
it "does not add to map on save" do
|
79
|
-
|
74
|
+
Toy::IdentityMap.enabled = false
|
80
75
|
user = User.new
|
81
76
|
user.save!
|
82
77
|
user.should_not be_in_identity_map
|
83
78
|
end
|
84
79
|
|
85
80
|
it "does not add to map on load" do
|
86
|
-
|
81
|
+
Toy::IdentityMap.enabled = false
|
87
82
|
user = User.load('1', 'name' => 'John')
|
88
83
|
user.should_not be_in_identity_map
|
89
84
|
end
|
@@ -91,7 +86,7 @@ describe Toy::IdentityMap do
|
|
91
86
|
it "does not remove from map on delete" do
|
92
87
|
user = User.create
|
93
88
|
user.should be_in_identity_map
|
94
|
-
|
89
|
+
Toy::IdentityMap.enabled = false
|
95
90
|
user.delete
|
96
91
|
user.should be_in_identity_map
|
97
92
|
end
|
@@ -99,14 +94,14 @@ describe Toy::IdentityMap do
|
|
99
94
|
it "does not remove from map on destroy" do
|
100
95
|
user = User.create
|
101
96
|
user.should be_in_identity_map
|
102
|
-
|
97
|
+
Toy::IdentityMap.enabled = false
|
103
98
|
user.destroy
|
104
99
|
user.should be_in_identity_map
|
105
100
|
end
|
106
101
|
|
107
102
|
describe ".get" do
|
108
103
|
it "does not add to map if not in map" do
|
109
|
-
|
104
|
+
Toy::IdentityMap.enabled = false
|
110
105
|
user = User.create
|
111
106
|
user.should_not be_in_identity_map
|
112
107
|
user = User.get(user.id)
|
@@ -116,35 +111,48 @@ describe Toy::IdentityMap do
|
|
116
111
|
it "does not load from map if in map" do
|
117
112
|
user = User.create
|
118
113
|
user.should be_in_identity_map
|
119
|
-
|
120
|
-
user.
|
114
|
+
Toy::IdentityMap.enabled = false
|
115
|
+
user.adapter.should_receive(:read).with(user.id).and_return(user.persisted_attributes)
|
121
116
|
User.get(user.id)
|
122
117
|
end
|
123
118
|
end
|
124
119
|
end
|
125
120
|
|
126
|
-
describe ".
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
User.
|
121
|
+
describe ".without" do
|
122
|
+
before do
|
123
|
+
@user = User.create
|
124
|
+
Toy::IdentityMap.clear
|
125
|
+
end
|
126
|
+
let(:user) { @user }
|
127
|
+
|
128
|
+
it "skips the map" do
|
129
|
+
Toy::IdentityMap.without do
|
130
|
+
User.get(user.id).should_not equal(user.id)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe ".use" do
|
136
|
+
before do
|
137
|
+
@user = User.create
|
138
|
+
Toy::IdentityMap.clear
|
139
|
+
end
|
140
|
+
let(:user) { @user }
|
141
|
+
|
142
|
+
it "uses the map" do
|
143
|
+
Toy::IdentityMap.enabled = false
|
144
|
+
Toy::IdentityMap.use do
|
145
|
+
User.get(user.id).should equal(User.get(user.id))
|
136
146
|
end
|
137
147
|
end
|
138
148
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
user.should_not be_in_identity_map
|
145
|
-
end
|
146
|
-
User.should be_identity_map_on
|
149
|
+
it "clears the map" do
|
150
|
+
Toy::IdentityMap.enabled = false
|
151
|
+
Toy::IdentityMap.repository['hello'] = 'world'
|
152
|
+
Toy::IdentityMap.use do
|
153
|
+
User.get(user.id)
|
147
154
|
end
|
155
|
+
Toy::IdentityMap.repository.should be_empty
|
148
156
|
end
|
149
157
|
end
|
150
158
|
end
|