toystore 0.9.0 → 0.10.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 +2 -1
- data/.travis.yml +9 -0
- data/Changelog.md +10 -1
- data/Gemfile +14 -13
- data/README.md +213 -2
- data/examples/plain_old_object.rb +54 -0
- data/examples/plain_old_object_on_roids.rb +160 -0
- data/lib/toy.rb +3 -1
- data/lib/toy/association_serialization.rb +50 -0
- data/lib/toy/attribute.rb +17 -2
- data/lib/toy/equality.rb +5 -1
- data/lib/toy/identity/abstract_key_factory.rb +5 -0
- data/lib/toy/identity_map.rb +1 -2
- data/lib/toy/inheritance.rb +29 -0
- data/lib/toy/inspect.rb +17 -4
- data/lib/toy/object.rb +6 -0
- data/lib/toy/querying.rb +20 -3
- data/lib/toy/reference.rb +18 -4
- data/lib/toy/reloadable.rb +2 -2
- data/lib/toy/serialization.rb +1 -40
- data/lib/toy/store.rb +2 -2
- data/lib/toy/timestamps.rb +3 -1
- data/lib/toy/version.rb +2 -2
- data/spec/helper.rb +2 -3
- data/spec/support/constants.rb +15 -15
- data/spec/toy/association_serialization_spec.rb +103 -0
- data/spec/toy/attribute_spec.rb +17 -1
- data/spec/toy/equality_spec.rb +9 -2
- data/spec/toy/extensions/array_spec.rb +2 -2
- data/spec/toy/identity/uuid_key_factory_spec.rb +35 -3
- data/spec/toy/identity_map_spec.rb +4 -0
- data/spec/toy/inheritance_spec.rb +93 -0
- data/spec/toy/inspect_spec.rb +12 -4
- data/spec/toy/object_spec.rb +47 -0
- data/spec/toy/plugins_spec.rb +4 -4
- data/spec/toy/querying_spec.rb +71 -11
- data/spec/toy/reference_spec.rb +82 -72
- data/spec/toy/serialization_spec.rb +16 -111
- data/spec/toy/store_spec.rb +14 -28
- metadata +23 -13
- data/Gemfile.lock +0 -71
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Toy::AssociationSerialization do
|
4
|
+
uses_constants('User', 'Game', 'Move')
|
5
|
+
|
6
|
+
before do
|
7
|
+
User.attribute :name, String
|
8
|
+
User.attribute :age, Integer
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "serializing relationships" do
|
12
|
+
before do
|
13
|
+
User.list :games, :inverse_of => :user
|
14
|
+
Game.reference :user
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should include references" do
|
18
|
+
user = User.create(:name => 'John', :age => 28)
|
19
|
+
game = user.games.create
|
20
|
+
|
21
|
+
MultiJson.load(game.to_json(:include => [:user])).should == {
|
22
|
+
'game' => {
|
23
|
+
'id' => game.id,
|
24
|
+
'user_id' => user.id,
|
25
|
+
'user' => {
|
26
|
+
'name' => 'John',
|
27
|
+
'game_ids' => [game.id],
|
28
|
+
'id' => user.id,
|
29
|
+
'age' => 28,
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should include lists" do
|
36
|
+
user = User.create(:name => 'John', :age => 28)
|
37
|
+
game = user.games.create
|
38
|
+
MultiJson.load(user.to_json(:include => [:games])).should == {
|
39
|
+
'user' => {
|
40
|
+
'name' => 'John',
|
41
|
+
'game_ids' => [game.id],
|
42
|
+
'id' => user.id,
|
43
|
+
'age' => 28,
|
44
|
+
'games' => [{'id' => game.id, 'user_id' => user.id}],
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not cause circular reference JSON errors for references" do
|
50
|
+
user = User.create(:name => 'John', :age => 28)
|
51
|
+
game = user.games.create
|
52
|
+
|
53
|
+
MultiJson.load(ActiveSupport::JSON.encode(game.user)).should == {
|
54
|
+
'user' => {
|
55
|
+
'name' => 'John',
|
56
|
+
'game_ids' => [game.id],
|
57
|
+
'id' => user.id,
|
58
|
+
'age' => 28
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not cause circular reference JSON errors for references when called indirectly" do
|
64
|
+
user = User.create(:name => 'John', :age => 28)
|
65
|
+
game = user.games.create
|
66
|
+
|
67
|
+
MultiJson.load(ActiveSupport::JSON.encode([game.user])).should == [
|
68
|
+
'user' => {
|
69
|
+
'name' => 'John',
|
70
|
+
'game_ids' => [game.id],
|
71
|
+
'id' => user.id,
|
72
|
+
'age' => 28
|
73
|
+
}
|
74
|
+
]
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should not cause circular reference JSON errors for lists" do
|
78
|
+
user = User.create(:name => 'John', :age => 28)
|
79
|
+
game = user.games.create
|
80
|
+
|
81
|
+
MultiJson.load(ActiveSupport::JSON.encode(user.games)).should == [{
|
82
|
+
'game' => {
|
83
|
+
'id' => game.id,
|
84
|
+
'user_id' => user.id
|
85
|
+
}
|
86
|
+
}]
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should not cause circular reference JSON errors for lists when called indirectly" do
|
90
|
+
user = User.create(:name => 'John', :age => 28)
|
91
|
+
game = user.games.create
|
92
|
+
|
93
|
+
MultiJson.load(ActiveSupport::JSON.encode({:games => user.games})).should == {
|
94
|
+
'games' => [{
|
95
|
+
'game' => {
|
96
|
+
'id' => game.id,
|
97
|
+
'user_id' => user.id
|
98
|
+
}
|
99
|
+
}]
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/spec/toy/attribute_spec.rb
CHANGED
@@ -72,6 +72,22 @@ describe Toy::Attribute do
|
|
72
72
|
Toy::Attribute.new(User, :age, String, :default => 1).default.should == 1
|
73
73
|
end
|
74
74
|
|
75
|
+
it "allows defaulting to nil" do
|
76
|
+
Toy::Attribute.new(User, :age, String, :default => nil).default.should be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it "works with callable default" do
|
80
|
+
default = lambda { 'foo' }
|
81
|
+
attribute = Toy::Attribute.new(User, :age, String, :default => default)
|
82
|
+
attribute.default.should == 'foo'
|
83
|
+
end
|
84
|
+
|
85
|
+
it "passes model to callable default" do
|
86
|
+
default = lambda { |model| model.name.downcase }
|
87
|
+
attribute = Toy::Attribute.new(User, :age, String, :default => default)
|
88
|
+
attribute.default.should == 'user'
|
89
|
+
end
|
90
|
+
|
75
91
|
it "returns store_default if set for type" do
|
76
92
|
Toy::Attribute.new(User, :skills, Array).default.should == []
|
77
93
|
end
|
@@ -173,4 +189,4 @@ describe Toy::Attribute do
|
|
173
189
|
Toy::Attribute.new(User, :twitter_access_token, String).abbr?.should be_false
|
174
190
|
end
|
175
191
|
end
|
176
|
-
end
|
192
|
+
end
|
data/spec/toy/equality_spec.rb
CHANGED
@@ -17,7 +17,7 @@ describe Toy::Equality do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
describe "equal?" do
|
20
|
+
describe "#equal?" do
|
21
21
|
it "returns true if same object" do
|
22
22
|
user = User.new(:id => 1)
|
23
23
|
user.should equal(user)
|
@@ -29,4 +29,11 @@ describe Toy::Equality do
|
|
29
29
|
user.should_not equal(other_user)
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
|
+
describe "#hash" do
|
34
|
+
it "returns the hash of the id" do
|
35
|
+
user = User.new
|
36
|
+
user.hash.should eq(user.id.hash)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -4,7 +4,7 @@ describe "Array.to_store" do
|
|
4
4
|
it "should convert value to_a" do
|
5
5
|
Array.to_store([1, 2, 3, 4]).should == [1, 2, 3, 4]
|
6
6
|
Array.to_store('1').should == ['1']
|
7
|
-
Array.to_store({'1' => '2'
|
7
|
+
Array.to_store({'1' => '2'}).should == [['1', '2']]
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -22,4 +22,4 @@ describe "Array.store_default" do
|
|
22
22
|
it "returns emtpy array" do
|
23
23
|
Array.store_default.should == []
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
@@ -4,11 +4,43 @@ describe Toy::Identity::UUIDKeyFactory do
|
|
4
4
|
uses_constants('User')
|
5
5
|
|
6
6
|
it "should use String as key_type" do
|
7
|
-
|
7
|
+
subject.key_type.should be(String)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should use uuid for next_key" do
|
11
|
-
|
11
|
+
subject.next_key(nil).length.should == 36
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#eql?" do
|
15
|
+
it "returns true for same class and key type" do
|
16
|
+
subject.eql?(Toy::Identity::UUIDKeyFactory.new).should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns false for same class and different key type" do
|
20
|
+
other = Toy::Identity::UUIDKeyFactory.new
|
21
|
+
other.stub(:key_type).and_return(Integer)
|
22
|
+
subject.eql?(other).should be_false
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns false for different classes" do
|
26
|
+
subject.eql?(Object.new).should be_false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#==" do
|
31
|
+
it "returns true for same class and key type" do
|
32
|
+
subject.==(Toy::Identity::UUIDKeyFactory.new).should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns false for same class and different key type" do
|
36
|
+
other = Toy::Identity::UUIDKeyFactory.new
|
37
|
+
other.stub(:key_type).and_return(Integer)
|
38
|
+
subject.==(other).should be_false
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns false for different classes" do
|
42
|
+
subject.==(Object.new).should be_false
|
43
|
+
end
|
12
44
|
end
|
13
45
|
|
14
46
|
describe "Declaring key to be uuid" do
|
@@ -24,4 +56,4 @@ describe Toy::Identity::UUIDKeyFactory do
|
|
24
56
|
User.attributes['id'].type.should be(String)
|
25
57
|
end
|
26
58
|
end
|
27
|
-
end
|
59
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe 'Toy Inheritance' do
|
4
|
+
describe 'using Toy::Object' do
|
5
|
+
before do
|
6
|
+
class ::Parent
|
7
|
+
include Toy::Object
|
8
|
+
|
9
|
+
attribute :name, String
|
10
|
+
end
|
11
|
+
|
12
|
+
class ::Child < Parent; end
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
Object.send :remove_const, 'Parent' if defined?(::Parent)
|
17
|
+
Object.send :remove_const, 'Child' if defined?(::Child)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "duplicates attributes" do
|
21
|
+
Parent.attributes.each do |name, attribute|
|
22
|
+
Child.attributes.key?(name).should be_true
|
23
|
+
Child.attributes[name].should eq(Parent.attributes[name])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "does not add attributes to the parent" do
|
28
|
+
Child.attribute(:foo, String)
|
29
|
+
Parent.attributes.keys.should_not include(:foo)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "adds type attribute" do
|
33
|
+
Child.attribute?(:type).should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "sets type to class name" do
|
37
|
+
Child.new.type.should eq('Child')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "sets the key factory to same as parent" do
|
41
|
+
Child.key_factory.should eq(Parent.key_factory)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'using Toy::Store' do
|
46
|
+
before do
|
47
|
+
class ::Degree
|
48
|
+
include Toy::Store
|
49
|
+
end
|
50
|
+
|
51
|
+
class ::Parent
|
52
|
+
include Toy::Store
|
53
|
+
|
54
|
+
attribute :name, String
|
55
|
+
list :degrees, Degree
|
56
|
+
reference :degree, Degree
|
57
|
+
end
|
58
|
+
|
59
|
+
class ::Child < Parent
|
60
|
+
list :odd_degrees, Degree
|
61
|
+
reference :odd_degree, Degree
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
after do
|
66
|
+
Object.send :remove_const, 'Parent' if defined?(::Parent)
|
67
|
+
Object.send :remove_const, 'Child' if defined?(::Child)
|
68
|
+
Object.send :remove_const, 'Degree' if defined?(::Degree)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "duplicates lists" do
|
72
|
+
Child.lists.keys.should include(:degrees)
|
73
|
+
Child.lists.keys.should include(:odd_degrees)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "does not add lists to parent" do
|
77
|
+
Parent.lists.keys.should_not include(:odd_degrees)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "duplicates references" do
|
81
|
+
Child.references.keys.should include(:degree)
|
82
|
+
Child.references.keys.should include(:odd_degree)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "does not add references to parent" do
|
86
|
+
Parent.references.keys.should_not include(:odd_degree)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "sets the adapter to the same as the parent" do
|
90
|
+
Child.adapter.should eq(Parent.adapter)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/spec/toy/inspect_spec.rb
CHANGED
@@ -8,8 +8,16 @@ describe Toy::Attributes do
|
|
8
8
|
User.attribute(:age, Integer)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
describe ".inspect" do
|
12
|
+
it "prints out attribute names and types" do
|
13
|
+
User.inspect.should == %Q(User(id:String age:Integer name:String))
|
14
|
+
end
|
14
15
|
end
|
15
|
-
|
16
|
+
|
17
|
+
describe "#inspect" do
|
18
|
+
it "prints out object id and attributes sorted with values" do
|
19
|
+
user = User.new(:age => 28, :name => 'John')
|
20
|
+
user.inspect.should == %Q(#<User:#{user.object_id} id: "#{user.id}", age: 28, name: "John">)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Toy::Object do
|
4
|
+
uses_objects('User')
|
5
|
+
|
6
|
+
it "adds model naming" do
|
7
|
+
model_name = User.model_name
|
8
|
+
model_name.should == 'User'
|
9
|
+
model_name.singular.should == 'user'
|
10
|
+
model_name.plural.should == 'users'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "adds to_model" do
|
14
|
+
user = User.new
|
15
|
+
user.to_model.should == user
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#persisted?" do
|
19
|
+
it "returns false" do
|
20
|
+
User.new.persisted?.should be_false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#to_key" do
|
25
|
+
it "returns [id] if persisted" do
|
26
|
+
user = User.new
|
27
|
+
user.stub(:persisted?).and_return(true)
|
28
|
+
user.to_key.should == [user.id]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns nil if not persisted" do
|
32
|
+
User.new.to_key.should be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#to_param" do
|
37
|
+
it "returns key joined by - if to_key present" do
|
38
|
+
user = User.new
|
39
|
+
user.stub(:persisted?).and_return(true)
|
40
|
+
user.to_param.should == user.to_key.join('-')
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns nil if to_key nil" do
|
44
|
+
User.new.to_param.should be_nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/toy/plugins_spec.rb
CHANGED
@@ -31,9 +31,9 @@ describe Toy::Plugins do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "adds plugins to classes declared after plugin was called" do
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
klass = Class.new { include Toy::Store }
|
35
|
+
klass.foo.should == 'foo'
|
36
|
+
klass.new.bar.should == 'bar'
|
37
37
|
end
|
38
38
|
end
|
39
|
-
end
|
39
|
+
end
|
data/spec/toy/querying_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Toy::Querying do
|
4
|
-
uses_constants
|
4
|
+
uses_constants 'User', 'Game'
|
5
5
|
|
6
6
|
before do
|
7
7
|
User.attribute :name, String
|
@@ -87,20 +87,80 @@ describe Toy::Querying do
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
describe ".load
|
91
|
-
before
|
92
|
-
|
90
|
+
describe ".load" do
|
91
|
+
before do
|
92
|
+
class Admin < ::User; end
|
93
|
+
end
|
94
|
+
|
95
|
+
after do
|
96
|
+
Object.send :remove_const, 'Admin' if defined?(Admin)
|
97
|
+
end
|
98
|
+
|
99
|
+
context "without type, hash attrs" do
|
100
|
+
before do
|
101
|
+
@doc = User.load('1', :name => 'John')
|
102
|
+
end
|
103
|
+
|
104
|
+
it "returns instance" do
|
105
|
+
@doc.should be_instance_of(User)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "marks object as persisted" do
|
109
|
+
@doc.should be_persisted
|
110
|
+
end
|
111
|
+
|
112
|
+
it "decodes the object" do
|
113
|
+
@doc.name.should == 'John'
|
114
|
+
end
|
115
|
+
end
|
93
116
|
|
94
|
-
|
95
|
-
|
117
|
+
context "without type, nil attrs" do
|
118
|
+
before do
|
119
|
+
@doc = User.load('1', nil)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "returns instance" do
|
123
|
+
@doc.should be_instance_of(User)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "marks object as persisted" do
|
127
|
+
@doc.should be_persisted
|
128
|
+
end
|
129
|
+
|
130
|
+
it "decodes the object" do
|
131
|
+
@doc.name.should be_nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "with symbol type" do
|
136
|
+
before do
|
137
|
+
@doc = User.load('1', :type => 'Admin', :name => 'John')
|
138
|
+
end
|
139
|
+
|
140
|
+
it "returns instance of type" do
|
141
|
+
@doc.should be_instance_of(Admin)
|
142
|
+
end
|
96
143
|
end
|
97
144
|
|
98
|
-
|
99
|
-
|
145
|
+
context "with string type" do
|
146
|
+
before do
|
147
|
+
@doc = User.load('1', 'type' => 'Admin', :name => 'John')
|
148
|
+
end
|
149
|
+
|
150
|
+
it "returns instance of type" do
|
151
|
+
@doc.should be_instance_of(Admin)
|
152
|
+
end
|
100
153
|
end
|
101
154
|
|
102
|
-
|
103
|
-
|
155
|
+
context "for type that doesn't exist" do
|
156
|
+
before do
|
157
|
+
Object.send :remove_const, 'Admin' if defined?(::Admin)
|
158
|
+
@doc = User.load('1', 'type' => 'Admin', :name => 'John')
|
159
|
+
end
|
160
|
+
|
161
|
+
it "returns instance of loading class" do
|
162
|
+
@doc.should be_instance_of(User)
|
163
|
+
end
|
104
164
|
end
|
105
165
|
end
|
106
|
-
end
|
166
|
+
end
|