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/lib/toy/serialization.rb
CHANGED
@@ -14,8 +14,7 @@ module Toy
|
|
14
14
|
options[:only] = Array.wrap(options[:only]).map(&:to_sym)
|
15
15
|
options[:except] = Array.wrap(options[:except]).map(&:to_sym)
|
16
16
|
|
17
|
-
serializable_stuff = serializable_attributes.map(&:to_sym)
|
18
|
-
self.class.embedded_lists.keys.map(&:to_sym)
|
17
|
+
serializable_stuff = serializable_attributes.map(&:to_sym)
|
19
18
|
|
20
19
|
if options[:only].any?
|
21
20
|
serializable_stuff &= options[:only]
|
@@ -48,35 +47,36 @@ module Toy
|
|
48
47
|
end
|
49
48
|
|
50
49
|
private
|
51
|
-
# Add associations specified via the <tt>:includes</tt> option.
|
52
|
-
# Expects a block that takes as arguments:
|
53
|
-
# +association+ - name of the association
|
54
|
-
# +records+ - the association record(s) to be serialized
|
55
|
-
# +opts+ - options for the association records
|
56
|
-
def serializable_add_includes(options = {})
|
57
|
-
return unless include_associations = options.delete(:include)
|
58
50
|
|
59
|
-
|
60
|
-
|
51
|
+
# Add associations specified via the <tt>:includes</tt> option.
|
52
|
+
# Expects a block that takes as arguments:
|
53
|
+
# +association+ - name of the association
|
54
|
+
# +records+ - the association record(s) to be serialized
|
55
|
+
# +opts+ - options for the association records
|
56
|
+
def serializable_add_includes(options = {})
|
57
|
+
return unless include_associations = options.delete(:include)
|
61
58
|
|
62
|
-
|
63
|
-
|
59
|
+
base_only_or_except = { :except => options[:except],
|
60
|
+
:only => options[:only] }
|
64
61
|
|
65
|
-
|
66
|
-
|
67
|
-
send(association).to_a
|
68
|
-
elsif self.class.reference?(association) || self.class.parent_reference?(association)
|
69
|
-
send(association)
|
70
|
-
end
|
62
|
+
include_has_options = include_associations.is_a?(Hash)
|
63
|
+
associations = include_has_options ? include_associations.keys : Array.wrap(include_associations)
|
71
64
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
65
|
+
for association in associations
|
66
|
+
records = if self.class.list?(association)
|
67
|
+
send(association).to_a
|
68
|
+
elsif self.class.reference?(association) || self.class.parent_reference?(association)
|
69
|
+
send(association)
|
77
70
|
end
|
78
71
|
|
79
|
-
|
72
|
+
unless records.nil?
|
73
|
+
association_options = include_has_options ? include_associations[association] : base_only_or_except
|
74
|
+
opts = options.merge(association_options)
|
75
|
+
yield(association, records, opts)
|
76
|
+
end
|
80
77
|
end
|
78
|
+
|
79
|
+
options[:include] = include_associations
|
80
|
+
end
|
81
81
|
end
|
82
82
|
end
|
data/lib/toy/store.rb
CHANGED
@@ -4,17 +4,12 @@ module Toy
|
|
4
4
|
extend Plugins
|
5
5
|
|
6
6
|
included do
|
7
|
-
|
8
|
-
include ActiveModel::Conversion
|
9
|
-
include Attributes
|
10
|
-
include Identity
|
7
|
+
include Toy::Object
|
11
8
|
include Persistence
|
12
9
|
include MassAssignmentSecurity
|
13
|
-
include
|
14
|
-
include Dirty
|
15
|
-
include Equality
|
16
|
-
include Inspect
|
10
|
+
include DirtyStore
|
17
11
|
include Querying
|
12
|
+
include Reloadable
|
18
13
|
|
19
14
|
include Callbacks
|
20
15
|
include Validations
|
@@ -22,10 +17,7 @@ module Toy
|
|
22
17
|
include Timestamps
|
23
18
|
|
24
19
|
include Lists
|
25
|
-
include EmbeddedLists
|
26
20
|
include References
|
27
|
-
include Indices
|
28
|
-
include Logger
|
29
21
|
|
30
22
|
include IdentityMap
|
31
23
|
include Caching
|
data/lib/toy/validations.rb
CHANGED
@@ -9,41 +9,22 @@ module Toy
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
|
-
def validates_embedded(*names)
|
13
|
-
validates_each(*names) do |record, name, value|
|
14
|
-
invalid = value.compact.select { |obj| !obj.valid? }
|
15
|
-
if invalid.any?
|
16
|
-
record.errors.add(name, 'is invalid')
|
17
|
-
|
18
|
-
if logger && logger.debug?
|
19
|
-
invalid_messages = []
|
20
|
-
invalid.each do |obj|
|
21
|
-
invalid_messages << [obj.attributes, obj.errors.full_messages]
|
22
|
-
end
|
23
|
-
log_operation(:iem, self.name, store, record.id, invalid_messages)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
12
|
def create!(attrs={})
|
30
13
|
new(attrs).tap { |doc| doc.save! }
|
31
14
|
end
|
32
15
|
end
|
33
16
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
17
|
+
def valid?
|
18
|
+
run_callbacks(:validation) { super }
|
19
|
+
end
|
38
20
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
21
|
+
def save(options={})
|
22
|
+
options.assert_valid_keys(:validate)
|
23
|
+
!options.fetch(:validate, true) || valid? ? super : false
|
24
|
+
end
|
43
25
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
26
|
+
def save!
|
27
|
+
save || raise(RecordInvalid.new(self))
|
47
28
|
end
|
48
29
|
end
|
49
30
|
end
|
data/lib/toy/version.rb
CHANGED
data/perf/reads.rb
CHANGED
@@ -12,8 +12,6 @@ Toy.logger = ::Logger.new(STDOUT).tap { |log| log.level = ::Logger::INFO }
|
|
12
12
|
|
13
13
|
class User
|
14
14
|
include Toy::Store
|
15
|
-
identity_map_off
|
16
|
-
store(:memory, {})
|
17
15
|
attribute :name, String
|
18
16
|
end
|
19
17
|
|
@@ -21,20 +19,20 @@ user = User.create(:name => 'John')
|
|
21
19
|
id = user.id
|
22
20
|
times = 10_000
|
23
21
|
|
24
|
-
|
25
|
-
times.times { User.
|
22
|
+
adapter_result = Benchmark.realtime {
|
23
|
+
times.times { User.adapter.decode(User.adapter.client[User.adapter.key_for(id)]) }
|
26
24
|
}
|
27
25
|
|
28
|
-
|
26
|
+
toystore_result = Benchmark.realtime {
|
29
27
|
times.times { User.get(id) }
|
30
28
|
}
|
31
29
|
|
32
|
-
puts 'Client',
|
33
|
-
puts 'Toystore',
|
34
|
-
puts 'Ratio',
|
30
|
+
puts 'Client', adapter_result
|
31
|
+
puts 'Toystore', toystore_result
|
32
|
+
puts 'Ratio', toystore_result / adapter_result
|
35
33
|
|
36
34
|
# PerfTools::CpuProfiler.start('prof_client') do
|
37
|
-
# times.times{ User.
|
35
|
+
# times.times{ User.adapter.decode(User.adapter.client[User.adapter.key_for(id)]) }
|
38
36
|
# end
|
39
37
|
|
40
38
|
# PerfTools::CpuProfiler.start('prof_reads') do
|
data/perf/writes.rb
CHANGED
@@ -12,8 +12,6 @@ Toy.logger = ::Logger.new(STDOUT).tap { |log| log.level = ::Logger::INFO }
|
|
12
12
|
|
13
13
|
class User
|
14
14
|
include Toy::Store
|
15
|
-
identity_map_off
|
16
|
-
store(:memory, {})
|
17
15
|
end
|
18
16
|
|
19
17
|
times = 10_000
|
@@ -21,13 +19,13 @@ user = User.new
|
|
21
19
|
id = user.id
|
22
20
|
attrs = user.persisted_attributes
|
23
21
|
|
24
|
-
|
25
|
-
times.times { User.
|
22
|
+
adapter_result = Benchmark.realtime {
|
23
|
+
times.times { User.adapter.write(id, attrs) }
|
26
24
|
}
|
27
|
-
|
25
|
+
toystore_result = Benchmark.realtime {
|
28
26
|
times.times { User.create }
|
29
27
|
}
|
30
28
|
|
31
|
-
puts 'Client',
|
32
|
-
puts 'Toystore',
|
33
|
-
puts 'Ratio',
|
29
|
+
puts 'Client', adapter_result
|
30
|
+
puts 'Toystore', toystore_result
|
31
|
+
puts 'Ratio', toystore_result / adapter_result
|
data/spec/helper.rb
CHANGED
@@ -14,8 +14,8 @@ require 'bundler'
|
|
14
14
|
Bundler.require(:default, :development)
|
15
15
|
|
16
16
|
require 'toy'
|
17
|
-
require 'adapter/memory'
|
18
17
|
require 'support/constants'
|
18
|
+
require 'support/objects'
|
19
19
|
require 'support/identity_map_matcher'
|
20
20
|
require 'support/name_and_number_key_factory'
|
21
21
|
|
@@ -26,9 +26,11 @@ end
|
|
26
26
|
|
27
27
|
RSpec.configure do |c|
|
28
28
|
c.include(Support::Constants)
|
29
|
+
c.include(Support::Objects)
|
29
30
|
c.include(IdentityMapMatcher)
|
30
31
|
|
31
32
|
c.before(:each) do
|
33
|
+
Toy::IdentityMap.enabled = false
|
32
34
|
Toy.clear
|
33
35
|
Toy.reset
|
34
36
|
Toy.key_factory = nil
|
data/spec/support/constants.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Support
|
2
2
|
module Constants
|
3
|
-
|
4
|
-
base.extend(ClassMethods)
|
5
|
-
end
|
3
|
+
extend ActiveSupport::Concern
|
6
4
|
|
7
5
|
module ClassMethods
|
8
6
|
def uses_constants(*constants)
|
@@ -34,7 +32,6 @@ module Support
|
|
34
32
|
def self.to_s; '#{name}' end
|
35
33
|
""" if name
|
36
34
|
model.send(:include, Toy::Store)
|
37
|
-
model.store(:memory, {})
|
38
35
|
end
|
39
36
|
end
|
40
37
|
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module IdentityMapMatcher
|
2
2
|
class BeInIdentityMap
|
3
|
-
def matches?(
|
4
|
-
@
|
5
|
-
|
3
|
+
def matches?(object)
|
4
|
+
@object = object
|
5
|
+
Toy::IdentityMap.include?(@object)
|
6
6
|
end
|
7
7
|
|
8
8
|
def failure_message
|
9
|
-
"expected #{@
|
9
|
+
"expected #{@object} to be in identity map, but it was not"
|
10
10
|
end
|
11
11
|
|
12
12
|
def negative_failure_message
|
13
|
-
"expected #{@
|
13
|
+
"expected #{@object} to not be in identity map, but it was"
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Support
|
2
|
+
module Objects
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def uses_objects(*objects)
|
7
|
+
before { create_objects(*objects) }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_objects(*objects)
|
12
|
+
objects.each { |object| create_object(object) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove_objects(*objects)
|
16
|
+
objects.each { |object| remove_object(object) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_object(object)
|
20
|
+
remove_object(object)
|
21
|
+
Kernel.const_set(object, Object(object))
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_object(object)
|
25
|
+
Kernel.send(:remove_const, object) if Kernel.const_defined?(object)
|
26
|
+
end
|
27
|
+
|
28
|
+
def Object(name=nil)
|
29
|
+
Class.new.tap do |object|
|
30
|
+
object.class_eval """
|
31
|
+
def self.name; '#{name}' end
|
32
|
+
def self.to_s; '#{name}' end
|
33
|
+
""" if name
|
34
|
+
object.send(:include, Toy::Object)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/toy/attribute_spec.rb
CHANGED
data/spec/toy/attributes_spec.rb
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Toy::Attributes do
|
4
|
-
|
5
|
-
|
6
|
-
before do
|
7
|
-
Game.embedded_list(:moves)
|
8
|
-
Move.embedded_list(:tiles)
|
9
|
-
end
|
4
|
+
uses_objects('User', 'Game')
|
10
5
|
|
11
6
|
describe "including" do
|
12
7
|
it "adds id attribute" do
|
@@ -22,7 +17,6 @@ describe Toy::Attributes do
|
|
22
17
|
|
23
18
|
describe "#persisted_attributes" do
|
24
19
|
before do
|
25
|
-
Game.embedded_list(:moves)
|
26
20
|
@over = Game.attribute(:over, Boolean)
|
27
21
|
@score = Game.attribute(:creator_score, Integer, :virtual => true)
|
28
22
|
@abbr = Game.attribute(:super_secret_hash, String, :abbr => :ssh)
|
@@ -32,7 +26,6 @@ describe Toy::Attributes do
|
|
32
26
|
:creator_score => 20,
|
33
27
|
:rewards => %w(twigs berries).to_set,
|
34
28
|
:ssh => 'h4x',
|
35
|
-
:moves => [Move.new, Move.new],
|
36
29
|
})
|
37
30
|
end
|
38
31
|
|
@@ -48,14 +41,6 @@ describe Toy::Attributes do
|
|
48
41
|
@game.persisted_attributes.should_not have_key('super_secret_hash')
|
49
42
|
end
|
50
43
|
|
51
|
-
it "includes embedded" do
|
52
|
-
@game.persisted_attributes.should have_key('moves')
|
53
|
-
end
|
54
|
-
|
55
|
-
it "includes ids of embedded" do
|
56
|
-
@game.persisted_attributes['moves'][0].should have_key('id')
|
57
|
-
end
|
58
|
-
|
59
44
|
it "does not include virtual attributes" do
|
60
45
|
@game.persisted_attributes.should_not have_key(:creator_score)
|
61
46
|
end
|
@@ -130,48 +115,6 @@ describe Toy::Attributes do
|
|
130
115
|
it "does not fail with nil" do
|
131
116
|
User.new(nil).should be_instance_of(User)
|
132
117
|
end
|
133
|
-
|
134
|
-
it "does guard attributes=" do
|
135
|
-
attrs = {'age' => 21}
|
136
|
-
user = User.allocate
|
137
|
-
user.should_receive(:attributes=).with(attrs, true)
|
138
|
-
user.send(:initialize, attrs)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
describe "#initialize_from_database" do
|
143
|
-
before do
|
144
|
-
User.attribute(:age, Integer, :default => 20)
|
145
|
-
@user = User.allocate
|
146
|
-
end
|
147
|
-
|
148
|
-
it "sets new record to false" do
|
149
|
-
@user.initialize_from_database
|
150
|
-
@user.should_not be_new_record
|
151
|
-
end
|
152
|
-
|
153
|
-
it "sets attributes" do
|
154
|
-
@user.initialize_from_database('age' => 21)
|
155
|
-
end
|
156
|
-
|
157
|
-
it "sets defaults" do
|
158
|
-
@user.initialize_from_database
|
159
|
-
@user.age.should == 20
|
160
|
-
end
|
161
|
-
|
162
|
-
it "does not fail with nil" do
|
163
|
-
@user.initialize_from_database(nil).should == @user
|
164
|
-
end
|
165
|
-
|
166
|
-
it "returns self" do
|
167
|
-
@user.initialize_from_database.should == @user
|
168
|
-
end
|
169
|
-
|
170
|
-
it "does not guard attributes=" do
|
171
|
-
attrs = {'age' => 21}
|
172
|
-
@user.should_receive(:attributes=).with(attrs, false)
|
173
|
-
@user.initialize_from_database(attrs)
|
174
|
-
end
|
175
118
|
end
|
176
119
|
|
177
120
|
describe "#attributes" do
|
@@ -189,11 +132,6 @@ describe Toy::Attributes do
|
|
189
132
|
'active' => true,
|
190
133
|
}
|
191
134
|
end
|
192
|
-
|
193
|
-
it "does not include embedded documents" do
|
194
|
-
game = Game.new(:moves => [Move.new(:tiles => [Tile.new])])
|
195
|
-
game.attributes.should_not have_key('moves')
|
196
|
-
end
|
197
135
|
end
|
198
136
|
|
199
137
|
describe "#attributes=" do
|
@@ -322,96 +260,6 @@ describe Toy::Attributes do
|
|
322
260
|
user.tat = '1234'
|
323
261
|
user.twitter_access_token.should == '1234'
|
324
262
|
end
|
325
|
-
|
326
|
-
it "persists to store using abbreviation" do
|
327
|
-
user = User.create(:twitter_access_token => '1234')
|
328
|
-
raw = user.store.read(user.id)
|
329
|
-
raw['tat'].should == '1234'
|
330
|
-
raw.should_not have_key('twitter_access_token')
|
331
|
-
end
|
332
|
-
|
333
|
-
it "loads from store correctly" do
|
334
|
-
user = User.create(:twitter_access_token => '1234')
|
335
|
-
user = User.get(user.id)
|
336
|
-
user.twitter_access_token.should == '1234'
|
337
|
-
user.tat.should == '1234'
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
describe "#reload" do
|
342
|
-
before do
|
343
|
-
User.attribute(:name, String)
|
344
|
-
@user = User.create(:name => 'John')
|
345
|
-
end
|
346
|
-
let(:user) { @user }
|
347
|
-
|
348
|
-
it "reloads id from database" do
|
349
|
-
id = user.id
|
350
|
-
user.reload
|
351
|
-
user.id.should == id
|
352
|
-
end
|
353
|
-
|
354
|
-
it "reloads record from the database" do
|
355
|
-
user.name = 'Steve'
|
356
|
-
user.reload
|
357
|
-
user.name.should == 'John'
|
358
|
-
end
|
359
|
-
|
360
|
-
it "is still persisted" do
|
361
|
-
user.should be_persisted
|
362
|
-
user.reload
|
363
|
-
user.should be_persisted
|
364
|
-
end
|
365
|
-
|
366
|
-
it "returns the record" do
|
367
|
-
user.name = 'Steve'
|
368
|
-
user.reload.should equal(user)
|
369
|
-
end
|
370
|
-
|
371
|
-
it "resets instance variables" do
|
372
|
-
user.instance_variable_set("@foo", true)
|
373
|
-
user.reload
|
374
|
-
user.instance_variable_get("@foo").should be_nil
|
375
|
-
end
|
376
|
-
|
377
|
-
it "resets lists" do
|
378
|
-
User.list(:games)
|
379
|
-
game = Game.create
|
380
|
-
user.update_attributes(:games => [game])
|
381
|
-
user.games = []
|
382
|
-
user.games.should == []
|
383
|
-
user.reload
|
384
|
-
user.games.should == [game]
|
385
|
-
end
|
386
|
-
|
387
|
-
it "resets references" do
|
388
|
-
Game.reference(:user)
|
389
|
-
game = Game.create(:user => user)
|
390
|
-
game.user = nil
|
391
|
-
game.user.should be_nil
|
392
|
-
game.reload
|
393
|
-
game.user.should == user
|
394
|
-
end
|
395
|
-
|
396
|
-
it "raises NotFound if does not exist" do
|
397
|
-
user.destroy
|
398
|
-
lambda { user.reload }.should raise_error(Toy::NotFound)
|
399
|
-
end
|
400
|
-
|
401
|
-
it "reloads defaults" do
|
402
|
-
User.attribute(:skills, Array)
|
403
|
-
@user.reload
|
404
|
-
@user.skills.should == []
|
405
|
-
end
|
406
|
-
|
407
|
-
it "reloads attributes protected from mass assignment" do
|
408
|
-
User.attribute(:admin, Boolean)
|
409
|
-
User.attr_accessible(:name)
|
410
|
-
user = User.new(:name => 'John')
|
411
|
-
user.admin = true
|
412
|
-
user.save
|
413
|
-
user.reload.admin.should be_true
|
414
|
-
end
|
415
263
|
end
|
416
264
|
|
417
265
|
describe "Initialization of array attributes" do
|