toystore 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/.autotest +11 -0
  2. data/.bundle/config +2 -0
  3. data/.gitignore +6 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +49 -0
  6. data/LICENSE +9 -0
  7. data/LOGGING.rdoc +16 -0
  8. data/README.rdoc +13 -0
  9. data/Rakefile +7 -0
  10. data/examples/memcached.rb +20 -0
  11. data/examples/memory.rb +20 -0
  12. data/examples/models.rb +51 -0
  13. data/examples/redis.rb +20 -0
  14. data/lib/toy.rb +81 -0
  15. data/lib/toy/attribute.rb +73 -0
  16. data/lib/toy/attributes.rb +137 -0
  17. data/lib/toy/caching.rb +20 -0
  18. data/lib/toy/callbacks.rb +48 -0
  19. data/lib/toy/collection.rb +55 -0
  20. data/lib/toy/connection.rb +28 -0
  21. data/lib/toy/dirty.rb +47 -0
  22. data/lib/toy/dolly.rb +30 -0
  23. data/lib/toy/embedded_list.rb +45 -0
  24. data/lib/toy/embedded_lists.rb +68 -0
  25. data/lib/toy/equality.rb +19 -0
  26. data/lib/toy/exceptions.rb +29 -0
  27. data/lib/toy/extensions/array.rb +22 -0
  28. data/lib/toy/extensions/boolean.rb +43 -0
  29. data/lib/toy/extensions/date.rb +24 -0
  30. data/lib/toy/extensions/float.rb +13 -0
  31. data/lib/toy/extensions/hash.rb +17 -0
  32. data/lib/toy/extensions/integer.rb +22 -0
  33. data/lib/toy/extensions/nil_class.rb +17 -0
  34. data/lib/toy/extensions/object.rb +26 -0
  35. data/lib/toy/extensions/set.rb +23 -0
  36. data/lib/toy/extensions/string.rb +17 -0
  37. data/lib/toy/extensions/time.rb +29 -0
  38. data/lib/toy/identity.rb +26 -0
  39. data/lib/toy/identity/abstract_key_factory.rb +10 -0
  40. data/lib/toy/identity/uuid_key_factory.rb +9 -0
  41. data/lib/toy/identity_map.rb +109 -0
  42. data/lib/toy/index.rb +74 -0
  43. data/lib/toy/indices.rb +56 -0
  44. data/lib/toy/inspect.rb +12 -0
  45. data/lib/toy/list.rb +46 -0
  46. data/lib/toy/lists.rb +37 -0
  47. data/lib/toy/logger.rb +26 -0
  48. data/lib/toy/mass_assignment_security.rb +16 -0
  49. data/lib/toy/persistence.rb +138 -0
  50. data/lib/toy/plugins.rb +23 -0
  51. data/lib/toy/proxies/embedded_list.rb +74 -0
  52. data/lib/toy/proxies/list.rb +97 -0
  53. data/lib/toy/proxies/proxy.rb +59 -0
  54. data/lib/toy/querying.rb +57 -0
  55. data/lib/toy/reference.rb +134 -0
  56. data/lib/toy/references.rb +19 -0
  57. data/lib/toy/serialization.rb +81 -0
  58. data/lib/toy/store.rb +36 -0
  59. data/lib/toy/timestamps.rb +22 -0
  60. data/lib/toy/validations.rb +45 -0
  61. data/lib/toy/version.rb +3 -0
  62. data/lib/toystore.rb +1 -0
  63. data/spec/helper.rb +35 -0
  64. data/spec/spec.opts +3 -0
  65. data/spec/support/constants.rb +41 -0
  66. data/spec/support/identity_map_matcher.rb +20 -0
  67. data/spec/support/name_and_number_key_factory.rb +5 -0
  68. data/spec/toy/attribute_spec.rb +176 -0
  69. data/spec/toy/attributes_spec.rb +394 -0
  70. data/spec/toy/caching_spec.rb +62 -0
  71. data/spec/toy/callbacks_spec.rb +97 -0
  72. data/spec/toy/connection_spec.rb +47 -0
  73. data/spec/toy/dirty_spec.rb +99 -0
  74. data/spec/toy/dolly_spec.rb +76 -0
  75. data/spec/toy/embedded_list_spec.rb +607 -0
  76. data/spec/toy/embedded_lists_spec.rb +172 -0
  77. data/spec/toy/equality_spec.rb +46 -0
  78. data/spec/toy/exceptions_spec.rb +18 -0
  79. data/spec/toy/extensions/array_spec.rb +25 -0
  80. data/spec/toy/extensions/boolean_spec.rb +41 -0
  81. data/spec/toy/extensions/date_spec.rb +48 -0
  82. data/spec/toy/extensions/float_spec.rb +14 -0
  83. data/spec/toy/extensions/hash_spec.rb +21 -0
  84. data/spec/toy/extensions/integer_spec.rb +29 -0
  85. data/spec/toy/extensions/nil_class_spec.rb +14 -0
  86. data/spec/toy/extensions/set_spec.rb +27 -0
  87. data/spec/toy/extensions/string_spec.rb +28 -0
  88. data/spec/toy/extensions/time_spec.rb +94 -0
  89. data/spec/toy/identity/abstract_key_factory_spec.rb +7 -0
  90. data/spec/toy/identity/uuid_key_factory_spec.rb +7 -0
  91. data/spec/toy/identity_map_spec.rb +150 -0
  92. data/spec/toy/identity_spec.rb +52 -0
  93. data/spec/toy/index_spec.rb +230 -0
  94. data/spec/toy/indices_spec.rb +141 -0
  95. data/spec/toy/inspect_spec.rb +15 -0
  96. data/spec/toy/list_spec.rb +576 -0
  97. data/spec/toy/lists_spec.rb +95 -0
  98. data/spec/toy/logger_spec.rb +33 -0
  99. data/spec/toy/mass_assignment_security_spec.rb +116 -0
  100. data/spec/toy/persistence_spec.rb +312 -0
  101. data/spec/toy/plugins_spec.rb +39 -0
  102. data/spec/toy/querying_spec.rb +162 -0
  103. data/spec/toy/reference_spec.rb +400 -0
  104. data/spec/toy/references_spec.rb +86 -0
  105. data/spec/toy/serialization_spec.rb +354 -0
  106. data/spec/toy/store_spec.rb +41 -0
  107. data/spec/toy/timestamps_spec.rb +63 -0
  108. data/spec/toy/validations_spec.rb +171 -0
  109. data/spec/toy_spec.rb +26 -0
  110. data/specs.watchr +52 -0
  111. data/test/lint_test.rb +40 -0
  112. data/toystore.gemspec +24 -0
  113. metadata +290 -0
@@ -0,0 +1,3 @@
1
+ module Toy
2
+ VERSION = "0.5"
3
+ end
@@ -0,0 +1 @@
1
+ require 'toy'
@@ -0,0 +1,35 @@
1
+ $:.unshift(File.expand_path('../../lib', __FILE__))
2
+
3
+ require 'pathname'
4
+ require 'logger'
5
+
6
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
+ lib_path = root_path.join('lib')
8
+ log_path = root_path.join('log')
9
+ log_path.mkpath
10
+
11
+ require 'rubygems'
12
+ require 'bundler'
13
+
14
+ Bundler.require(:default, :development)
15
+
16
+ require 'toy'
17
+ require 'adapter/memory'
18
+ require 'support/constants'
19
+ require 'support/identity_map_matcher'
20
+ require 'support/name_and_number_key_factory'
21
+
22
+ Logger.new(log_path.join('test.log')).tap do |log|
23
+ LogBuddy.init(:logger => log)
24
+ Toy.logger = log
25
+ end
26
+
27
+ Rspec.configure do |c|
28
+ c.include(Support::Constants)
29
+ c.include(IdentityMapMatcher)
30
+
31
+ c.before(:each) do
32
+ Toy.clear
33
+ Toy.reset
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --timeout
3
+ 20
@@ -0,0 +1,41 @@
1
+ module Support
2
+ module Constants
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def uses_constants(*constants)
9
+ before { create_constants(*constants) }
10
+ end
11
+ end
12
+
13
+ def create_constants(*constants)
14
+ constants.each { |constant| create_constant(constant) }
15
+ end
16
+
17
+ def remove_constants(*constants)
18
+ constants.each { |constant| remove_constant(constant) }
19
+ end
20
+
21
+ def create_constant(constant)
22
+ remove_constant(constant)
23
+ Kernel.const_set(constant, Model(constant))
24
+ end
25
+
26
+ def remove_constant(constant)
27
+ Kernel.send(:remove_const, constant) if Kernel.const_defined?(constant)
28
+ end
29
+
30
+ def Model(name=nil)
31
+ Class.new.tap do |model|
32
+ model.class_eval """
33
+ def self.name; '#{name}' end
34
+ def self.to_s; '#{name}' end
35
+ """ if name
36
+ model.send(:include, Toy::Store)
37
+ model.store(:memory, {})
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ module IdentityMapMatcher
2
+ class BeInIdentityMap
3
+ def matches?(obj)
4
+ @obj = obj
5
+ @obj.identity_map[@obj.store_key] == @obj
6
+ end
7
+
8
+ def failure_message
9
+ "expected #{@obj} to be in identity map, but it was not"
10
+ end
11
+
12
+ def negative_failure_message
13
+ "expected #{@obj} to not be in identity map, but it was"
14
+ end
15
+ end
16
+
17
+ def be_in_identity_map
18
+ BeInIdentityMap.new
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ class NameAndNumberKeyFactory < Toy::Identity::AbstractKeyFactory
2
+ def next_key(object)
3
+ "#{object.name}-#{object.number}" unless object.name.nil? || object.number.nil?
4
+ end
5
+ end
@@ -0,0 +1,176 @@
1
+ require 'helper'
2
+
3
+ describe Toy::Attribute do
4
+ uses_constants('User')
5
+
6
+ before do
7
+ @attribute = Toy::Attribute.new(User, :age, String)
8
+ end
9
+
10
+ let(:attribute) { @attribute }
11
+
12
+ it "has model" do
13
+ attribute.model.should == User
14
+ end
15
+
16
+ it "has name" do
17
+ attribute.name.should == :age
18
+ end
19
+
20
+ it "has type" do
21
+ attribute.type.should == String
22
+ end
23
+
24
+ it "can convert from_store using the attribute type" do
25
+ attribute.from_store(12).should == '12'
26
+ end
27
+
28
+ it "can convert to_store using the attribute type" do
29
+ attribute.to_store(12).should == '12'
30
+ end
31
+
32
+ it "raises error if option is passed that we do not know about" do
33
+ lambda {
34
+ Toy::Attribute.new(User, :age, String, :taco => 'bell')
35
+ }.should raise_error(ArgumentError)
36
+ end
37
+
38
+ describe "#virtual?" do
39
+ it "defaults to false" do
40
+ Toy::Attribute.new(User, :score, Integer).should_not be_virtual
41
+ end
42
+
43
+ it "returns true if :virtual => true" do
44
+ Toy::Attribute.new(User, :score, Integer, :virtual => true).should be_virtual
45
+ end
46
+
47
+ it "returns false if :virtual => false" do
48
+ Toy::Attribute.new(User, :score, Integer, :virtual => false).should_not be_virtual
49
+ end
50
+ end
51
+
52
+ describe "#persisted?" do
53
+ it "defaults to true" do
54
+ Toy::Attribute.new(User, :score, Integer).should be_persisted
55
+ end
56
+
57
+ it "returns false if :virtual => true" do
58
+ Toy::Attribute.new(User, :score, Integer, :virtual => true).should_not be_persisted
59
+ end
60
+
61
+ it "returns true if :virtual => false" do
62
+ Toy::Attribute.new(User, :score, Integer, :virtual => false).should be_persisted
63
+ end
64
+ end
65
+
66
+ describe "#default" do
67
+ it "defaults to nil" do
68
+ Toy::Attribute.new(User, :age, String).default.should be_nil
69
+ end
70
+
71
+ it "returns default if set" do
72
+ Toy::Attribute.new(User, :age, String, :default => 1).default.should == 1
73
+ end
74
+
75
+ it "returns store_default if set for type" do
76
+ Toy::Attribute.new(User, :skills, Array).default.should == []
77
+ end
78
+
79
+ it "returns default if set even if store_default is set" do
80
+ Toy::Attribute.new(User, :skills, Array, :default => [1]).default.should == [1]
81
+ end
82
+ end
83
+
84
+ describe "#default?" do
85
+ it "returns false if no default or store_default" do
86
+ Toy::Attribute.new(User, :age, String).default?.should be_false
87
+ end
88
+
89
+ it "returns true if default set" do
90
+ Toy::Attribute.new(User, :age, String, :default => 1).default?.should be_true
91
+ end
92
+
93
+ it "returns true if store_default set" do
94
+ Toy::Attribute.new(User, :skills, Array).default?.should be_true
95
+ end
96
+ end
97
+
98
+ describe "#store_key" do
99
+ it "returns abbr if abbreviated" do
100
+ Toy::Attribute.new(User, :age, String, :abbr => :a).store_key.should == 'a'
101
+ end
102
+
103
+ it "returns name if not abbreviated" do
104
+ Toy::Attribute.new(User, :age, String).store_key.should == 'age'
105
+ end
106
+ end
107
+
108
+ describe "attribute with default" do
109
+ before do
110
+ @attribute = Toy::Attribute.new(User, :brother_name, String, :default => 'Daryl')
111
+ end
112
+
113
+ it "returns default when reading a nil value" do
114
+ @attribute.from_store(nil).should == 'Daryl'
115
+ end
116
+
117
+ it "returns value when reading a non-nil value" do
118
+ @attribute.from_store('Larry').should == 'Larry'
119
+ end
120
+
121
+ it "returns default when writing a nil value" do
122
+ @attribute.to_store(nil).should == 'Daryl'
123
+ end
124
+
125
+ it "returns value when writing a non-nil value" do
126
+ @attribute.to_store('Larry').should == 'Larry'
127
+ end
128
+ end
129
+
130
+ describe "attribute with default that is proc" do
131
+ before do
132
+ default = proc { 'foo' }
133
+ @attribute = Toy::Attribute.new(User, :foo, String, :default => default)
134
+ end
135
+
136
+ it "returns default when reading a nil value" do
137
+ @attribute.from_store(nil).should == 'foo'
138
+ end
139
+
140
+ it "returns value when reading a non-nil value" do
141
+ @attribute.from_store('bar').should == 'bar'
142
+ end
143
+
144
+ it "returns default when writing a nil value" do
145
+ @attribute.to_store(nil).should == 'foo'
146
+ end
147
+
148
+ it "returns value when writing a non-nil value" do
149
+ @attribute.to_store('bar').should == 'bar'
150
+ end
151
+ end
152
+
153
+ describe "#abbr" do
154
+ it "returns abbr if present" do
155
+ Toy::Attribute.new(User, :twitter_access_token, String, :abbr => :tat).abbr.should == :tat
156
+ end
157
+
158
+ it "returns abbr as symbol if present as string" do
159
+ Toy::Attribute.new(User, :twitter_access_token, String, :abbr => 'tat').abbr.should == :tat
160
+ end
161
+
162
+ it "returns nil if not present" do
163
+ Toy::Attribute.new(User, :twitter_access_token, String).abbr.should be_nil
164
+ end
165
+ end
166
+
167
+ describe "#abbr?" do
168
+ it "returns true if abbreviation present" do
169
+ Toy::Attribute.new(User, :twitter_access_token, String, :abbr => :tat).abbr?.should be_true
170
+ end
171
+
172
+ it "returns false if abbreviation missing" do
173
+ Toy::Attribute.new(User, :twitter_access_token, String).abbr?.should be_false
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,394 @@
1
+ require 'helper'
2
+
3
+ describe Toy::Attributes do
4
+ uses_constants('User', 'Game', 'Move', 'Tile')
5
+
6
+ before do
7
+ Game.embedded_list(:moves)
8
+ Move.embedded_list(:tiles)
9
+ end
10
+
11
+ describe "including" do
12
+ it "adds id attribute" do
13
+ User.attributes.keys.should == ['id']
14
+ end
15
+ end
16
+
17
+ describe ".attributes" do
18
+ it "defaults to hash with id" do
19
+ User.attributes.keys.should == ['id']
20
+ end
21
+ end
22
+
23
+ describe "#persisted_attributes" do
24
+ before do
25
+ Game.embedded_list(:moves)
26
+ @over = Game.attribute(:over, Boolean)
27
+ @score = Game.attribute(:creator_score, Integer, :virtual => true)
28
+ @abbr = Game.attribute(:super_secret_hash, String, :abbr => :ssh)
29
+ @rewards = Game.attribute(:rewards, Set)
30
+ @game = Game.new({
31
+ :over => true,
32
+ :creator_score => 20,
33
+ :rewards => %w(twigs berries).to_set,
34
+ :ssh => 'h4x',
35
+ :moves => [Move.new, Move.new],
36
+ })
37
+ end
38
+
39
+ it "includes persisted attributes" do
40
+ @game.persisted_attributes.should have_key('over')
41
+ end
42
+
43
+ it "includes abbreviated names for abbreviated attributes" do
44
+ @game.persisted_attributes.should have_key('ssh')
45
+ end
46
+
47
+ it "does not include full names for abbreviated attributes" do
48
+ @game.persisted_attributes.should_not have_key('super_secret_hash')
49
+ end
50
+
51
+ it "includes embedded" do
52
+ @game.persisted_attributes.should have_key('moves')
53
+ end
54
+
55
+ it "does not include virtual attributes" do
56
+ @game.persisted_attributes.should_not have_key(:creator_score)
57
+ end
58
+
59
+ it "includes to_store values for attributes" do
60
+ @game.persisted_attributes['rewards'].should be_instance_of(Array)
61
+ @game.persisted_attributes['rewards'].should == @rewards.to_store(@game.rewards)
62
+ end
63
+ end
64
+
65
+ describe ".defaulted_attributes" do
66
+ before do
67
+ @name = User.attribute(:name, String)
68
+ @age = User.attribute(:age, Integer, :default => 10)
69
+ end
70
+
71
+ it "includes attributes with a default" do
72
+ User.defaulted_attributes.should include(@age)
73
+ end
74
+
75
+ it "excludes attributes without a default" do
76
+ User.defaulted_attributes.should_not include(@name)
77
+ end
78
+ end
79
+
80
+ describe ".attribute?" do
81
+ before do
82
+ User.attribute :age, Integer
83
+ end
84
+
85
+ it "returns true if attribute (symbol)" do
86
+ User.attribute?(:age).should be_true
87
+ end
88
+
89
+ it "returns true if attribute (string)" do
90
+ User.attribute?('age').should be_true
91
+ end
92
+
93
+ it "returns false if not attribute" do
94
+ User.attribute?(:foobar).should be_false
95
+ end
96
+ end
97
+
98
+ describe "#initialize" do
99
+ before do
100
+ User.attribute :name, String
101
+ User.attribute :age, Integer
102
+ end
103
+
104
+ it "writes id" do
105
+ id = User.new.id
106
+ id.should_not be_nil
107
+ id.size.should == 36
108
+ end
109
+
110
+ it "does not attempt to set id if already set" do
111
+ user = User.new(:id => 'frank')
112
+ user.id.should == 'frank'
113
+ end
114
+
115
+ it "sets attributes" do
116
+ instance = User.new(:name => 'John', :age => 28)
117
+ instance.name.should == 'John'
118
+ instance.age.should == 28
119
+ end
120
+
121
+ it "sets defaults" do
122
+ User.attribute(:awesome, Boolean, :default => true)
123
+ User.new.awesome.should be_true
124
+ end
125
+
126
+ it "does not fail with nil" do
127
+ User.new(nil).should be_instance_of(User)
128
+ end
129
+ end
130
+
131
+ describe "#initialize_from_database" do
132
+ before do
133
+ User.attribute(:age, Integer, :default => 20)
134
+ @user = User.allocate
135
+ end
136
+
137
+ it "sets new record to false" do
138
+ @user.initialize_from_database
139
+ @user.should_not be_new_record
140
+ end
141
+
142
+ it "sets attributes" do
143
+ @user.initialize_from_database('age' => 21)
144
+ end
145
+
146
+ it "sets defaults" do
147
+ @user.initialize_from_database
148
+ @user.age.should == 20
149
+ end
150
+
151
+ it "does not fail with nil" do
152
+ @user.initialize_from_database(nil).should == @user
153
+ end
154
+
155
+ it "returns self" do
156
+ @user.initialize_from_database.should == @user
157
+ end
158
+ end
159
+
160
+ describe "#attributes" do
161
+ it "defaults to hash with id" do
162
+ attrs = Model().new.attributes
163
+ attrs.keys.should == ['id']
164
+ end
165
+
166
+ it "includes all attributes that are not nil" do
167
+ User.attribute(:name, String)
168
+ User.attribute(:active, Boolean, :default => true)
169
+ user = User.new
170
+ user.attributes.should == {
171
+ 'id' => user.id,
172
+ 'active' => true,
173
+ }
174
+ end
175
+
176
+ it "does not include embedded documents" do
177
+ game = Game.new(:moves => [Move.new(:tiles => [Tile.new])])
178
+ game.attributes.should_not have_key('moves')
179
+ end
180
+ end
181
+
182
+ describe "#attributes=" do
183
+ it "sets attributes if present" do
184
+ User.attribute :age, Integer
185
+ record = User.new
186
+ record.attributes = {:age => 20}
187
+ record.age.should == 20
188
+ end
189
+
190
+ it "does nothing if nil" do
191
+ record = User.new
192
+ lambda { record.attributes = nil }.should_not raise_error
193
+ end
194
+
195
+ it "works with accessors that are not keys" do
196
+ User.class_eval { attr_accessor :foo }
197
+ record = User.new(:foo => 'oof')
198
+ record.foo.should == 'oof'
199
+ end
200
+
201
+ it "ignores keys that are not attributes and do not have accessors defined" do
202
+ lambda { User.new(:taco => 'bell') }.should_not raise_error
203
+ end
204
+ end
205
+
206
+ describe "reading an attribute" do
207
+ before do
208
+ User.attribute(:info, Hash)
209
+ @user = User.new(:info => {'name' => 'John'})
210
+ end
211
+
212
+ it "returns the same instance" do
213
+ @user.info.should equal(@user.info)
214
+ end
215
+ end
216
+
217
+ describe "declaring an attribute" do
218
+ before do
219
+ User.attribute :name, String
220
+ User.attribute :age, Integer
221
+ end
222
+
223
+ it "adds attribute to attributes" do
224
+ User.attributes['name'].should == Toy::Attribute.new(User, :name, String)
225
+ User.attributes[:name].should be_nil
226
+ User.attributes['age'].should == Toy::Attribute.new(User, :age, Integer)
227
+ User.attributes[:age].should be_nil
228
+ end
229
+
230
+ it "adds accessors" do
231
+ record = User.new
232
+ record.name = 'John'
233
+ record.name.should == 'John'
234
+ end
235
+
236
+ it "converts to attribute type" do
237
+ record = User.new
238
+ record.age = '12'
239
+ record.age.should == 12
240
+ end
241
+
242
+ it "adds query-ers" do
243
+ record = User.new
244
+ record.name?.should be_false
245
+ record.name = 'John'
246
+ record.name?.should be_true
247
+ end
248
+
249
+ it "knows if it responds to attribute method" do
250
+ record = User.new
251
+ record.should respond_to(:name)
252
+ record.should respond_to(:name=)
253
+ record.should respond_to(:name?)
254
+ end
255
+
256
+ it "know if it does not respond to method" do
257
+ record = User.new
258
+ record.should_not respond_to(:foobar)
259
+ end
260
+
261
+ it "aliases [] to read_attribute" do
262
+ record = User.new(:name => 'John')
263
+ record[:name].should == 'John'
264
+ end
265
+
266
+ it "aliases []= to write_attribute" do
267
+ record = User.new
268
+ record[:name] = 'John'
269
+ record.name.should == 'John'
270
+ end
271
+ end
272
+
273
+ describe "declaring an attribute with a default" do
274
+ before do
275
+ User.attribute :active, Boolean, :default => true
276
+ end
277
+
278
+ it "adds attribute to attributes" do
279
+ attribute = Toy::Attribute.new(User, :active, Boolean, {:default => true})
280
+ User.attributes['active'].should == attribute
281
+ end
282
+
283
+ it "defaults value when initialized" do
284
+ User.new.active.should be(true)
285
+ end
286
+
287
+ it "overrides default if present" do
288
+ User.new(:active => false).active.should be(false)
289
+ end
290
+ end
291
+
292
+ describe "declaring an attribute with an abbreviation" do
293
+ before do
294
+ User.attribute(:twitter_access_token, String, :abbr => 'tat')
295
+ end
296
+
297
+ it "aliases reading to abbreviation" do
298
+ user = User.new
299
+ user.twitter_access_token = '1234'
300
+ user.tat.should == '1234'
301
+ end
302
+
303
+ it "aliases writing to abbreviation" do
304
+ user = User.new
305
+ user.tat = '1234'
306
+ user.twitter_access_token.should == '1234'
307
+ end
308
+
309
+ it "persists to store using abbreviation" do
310
+ user = User.create(:twitter_access_token => '1234')
311
+ raw = user.store.read(user.store_key)
312
+ raw['tat'].should == '1234'
313
+ raw.should_not have_key('twitter_access_token')
314
+ end
315
+
316
+ it "loads from store correctly" do
317
+ user = User.create(:twitter_access_token => '1234')
318
+ user = User.get(user.id)
319
+ user.twitter_access_token.should == '1234'
320
+ user.tat.should == '1234'
321
+ end
322
+ end
323
+
324
+ describe "#reload" do
325
+ before do
326
+ User.attribute(:name, String)
327
+ @user = User.create(:name => 'John')
328
+ end
329
+ let(:user) { @user }
330
+
331
+ it "reloads record from the database" do
332
+ user.name = 'Steve'
333
+ user.reload
334
+ user.name.should == 'John'
335
+ end
336
+
337
+ it "is still persisted" do
338
+ user.should be_persisted
339
+ user.reload
340
+ user.should be_persisted
341
+ end
342
+
343
+ it "returns the record" do
344
+ user.name = 'Steve'
345
+ user.reload.should equal(user)
346
+ end
347
+
348
+ it "resets instance variables" do
349
+ user.instance_variable_set("@foo", true)
350
+ user.reload
351
+ user.instance_variable_get("@foo").should be_nil
352
+ end
353
+
354
+ it "resets lists" do
355
+ User.list(:games)
356
+ game = Game.create
357
+ user.update_attributes(:games => [game])
358
+ user.games = []
359
+ user.games.should == []
360
+ user.reload
361
+ user.games.should == [game]
362
+ end
363
+
364
+ it "resets references" do
365
+ Game.reference(:user)
366
+ game = Game.create(:user => user)
367
+ game.user = nil
368
+ game.user.should be_nil
369
+ game.reload
370
+ game.user.should == user
371
+ end
372
+
373
+ it "raises NotFound if does not exist" do
374
+ user.destroy
375
+ lambda { user.reload }.should raise_error(Toy::NotFound)
376
+ end
377
+
378
+ it "reloads defaults" do
379
+ User.attribute(:skills, Array)
380
+ @user.reload
381
+ @user.skills.should == []
382
+ end
383
+ end
384
+
385
+ describe "Initialization of array attributes" do
386
+ before do
387
+ User.attribute(:skills, Array)
388
+ end
389
+
390
+ it "initializes to empty array" do
391
+ User.new.skills.should == []
392
+ end
393
+ end
394
+ end