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,11 @@
1
+ require 'autotest/growl'
2
+
3
+ Autotest.add_hook(:initialize) {|at|
4
+ at.add_exception %r{^\.git} # ignore Version Control System
5
+ at.add_exception %r{^./tmp} # ignore temp files, lest autotest will run again, and again...
6
+ # at.clear_mappings # take out the default (test/test*rb)
7
+ at.add_mapping(%r{^lib/.*\.rb$}) {|f, _|
8
+ Dir['spec/**/*.rb']
9
+ }
10
+ nil
11
+ }
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+ testing/
3
+ .rvmrc
4
+ log
5
+ tmp
6
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ group(:development) do
5
+ gem 'rake', '~> 0.8.7'
6
+ gem 'rspec', '~> 2.3'
7
+ gem 'timecop', '~> 0.3.5'
8
+ gem 'tzinfo', '~> 0.3.23'
9
+ gem 'log_buddy', '~> 0.5.0'
10
+ end
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ toystore (0.5)
5
+ activemodel (~> 3.0.3)
6
+ activesupport (~> 3.0.3)
7
+ adapter (~> 0.5.1)
8
+ simple_uuid (~> 0.1.1)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ activemodel (3.0.3)
14
+ activesupport (= 3.0.3)
15
+ builder (~> 2.1.2)
16
+ i18n (~> 0.4)
17
+ activesupport (3.0.3)
18
+ adapter (0.5.1)
19
+ builder (2.1.2)
20
+ diff-lcs (1.1.2)
21
+ i18n (0.5.0)
22
+ log_buddy (0.5.0)
23
+ rake (0.8.7)
24
+ rspec (2.4.0)
25
+ rspec-core (~> 2.4.0)
26
+ rspec-expectations (~> 2.4.0)
27
+ rspec-mocks (~> 2.4.0)
28
+ rspec-core (2.4.0)
29
+ rspec-expectations (2.4.0)
30
+ diff-lcs (~> 1.1.2)
31
+ rspec-mocks (2.4.0)
32
+ simple_uuid (0.1.1)
33
+ timecop (0.3.5)
34
+ tzinfo (0.3.23)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ activemodel (~> 3.0.3)
41
+ activesupport (~> 3.0.3)
42
+ adapter (~> 0.5.1)
43
+ log_buddy (~> 0.5.0)
44
+ rake (~> 0.8.7)
45
+ rspec (~> 2.3)
46
+ simple_uuid (~> 0.1.1)
47
+ timecop (~> 0.3.5)
48
+ toystore!
49
+ tzinfo (~> 0.3.23)
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (c) 2011, Zynga Inc.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
7
+ * Neither the name of Zynga Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
8
+
9
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,16 @@
1
+ What the 3 letter codes mean when they show up in logging:
2
+
3
+ SET: write to store
4
+ GET: read from store
5
+ DEL: delete from store
6
+ KEY: check if key exists in store
7
+
8
+ IMG: read from identity map
9
+ IMS: write to identity map
10
+ IMD: delete from identity map
11
+
12
+ RTG: get cache read
13
+ RTS: get cache set
14
+ WTS: cache write set
15
+
16
+ IEM: invalid embedded document
@@ -0,0 +1,13 @@
1
+ = Toystore
2
+
3
+ An object mapper for anything that can read, write and delete data.
4
+
5
+ See examples/models.rb for potential direction. The idea is that any key-value store (via adapters) that supports read, write, delete will work (memcache, membase, redis, couch, toyko. Potentially even RESTFUL services or sqlite with a single key-value table?)
6
+
7
+ == Note on Patches/Pull Requests
8
+
9
+ * Fork the project.
10
+ * Make your feature addition or bug fix.
11
+ * Add tests for it. This is important so we don't break it in a future version unintentionally.
12
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine, but bump version in a commit by itself so we can ignore when we pull)
13
+ * Send us a pull request. Bonus points for topic branches.
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task :default => :spec
@@ -0,0 +1,20 @@
1
+ require 'pp'
2
+ require 'rubygems'
3
+ require 'toystore'
4
+ require 'adapter/memcached'
5
+
6
+ class GameList
7
+ include Toy::Store
8
+ store :memcached, Memcached.new
9
+
10
+ attribute :source, Hash
11
+ end
12
+
13
+ list = GameList.create(:source => {'foo' => 'bar'})
14
+
15
+ pp list
16
+ pp GameList.get(list.id)
17
+
18
+ list.destroy
19
+
20
+ pp GameList.get(list.id)
@@ -0,0 +1,20 @@
1
+ require 'pp'
2
+ require 'rubygems'
3
+ require 'toystore'
4
+ require 'adapter/memory'
5
+
6
+ class User
7
+ include Toy::Store
8
+ store :memory, {}
9
+
10
+ attribute :name, String
11
+ end
12
+
13
+ user = User.create(:name => 'John')
14
+
15
+ pp user
16
+ pp User.get(user.id)
17
+
18
+ user.destroy
19
+
20
+ pp User.get(user.id)
@@ -0,0 +1,51 @@
1
+ require 'pathname'
2
+
3
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
4
+ lib_path = root_path.join('lib')
5
+ $:.unshift(lib_path)
6
+
7
+ require 'toy'
8
+ require 'adapter/memory'
9
+
10
+ class Address
11
+ include Toy::Store
12
+ store :memory, {}
13
+
14
+ attribute :city, String
15
+ attribute :state, String
16
+ attribute :zip, String
17
+
18
+ index :zip
19
+ end
20
+
21
+ class PhoneNumber
22
+ include Toy::Store
23
+
24
+ attribute :area_code, String
25
+ attribute :number, String
26
+ end
27
+
28
+ class Company
29
+ include Toy::Store
30
+ store :memory, {}
31
+
32
+ attribute :name, String
33
+ end
34
+
35
+ class User
36
+ include Toy::Store
37
+ store :memory, {}
38
+
39
+ attribute :name, String
40
+ attribute :age, Integer
41
+ attribute :admin, Boolean, :default => false
42
+ attribute :ssn, String
43
+ timestamps
44
+
45
+ index :ssn
46
+
47
+ list :addresses, :dependendent => true
48
+ reference :employer, Company
49
+
50
+ # validations and callbacks are available too
51
+ end
@@ -0,0 +1,20 @@
1
+ require 'pp'
2
+ require 'rubygems'
3
+ require 'toystore'
4
+ require 'adapter/redis'
5
+
6
+ class User
7
+ include Toy::Store
8
+ store :redis, Redis.new
9
+
10
+ attribute :name, String
11
+ end
12
+
13
+ user = User.create(:name => 'John')
14
+
15
+ pp user
16
+ pp User.get(user.id)
17
+
18
+ user.destroy
19
+
20
+ pp User.get(user.id)
@@ -0,0 +1,81 @@
1
+ require 'set'
2
+ require 'pathname'
3
+ require 'forwardable'
4
+ require 'digest/sha1'
5
+
6
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
+
8
+ require 'adapter'
9
+ require 'simple_uuid'
10
+ require 'active_model'
11
+ require 'active_support/json'
12
+ require 'active_support/core_ext/object'
13
+ require 'active_support/core_ext/hash/indifferent_access'
14
+ require 'active_support/core_ext/hash/keys'
15
+ require 'active_support/core_ext/class/inheritable_attributes'
16
+ require 'active_support/core_ext/string/conversions'
17
+ require 'active_support/core_ext/string/inflections'
18
+
19
+ extensions_path = root_path.join('lib', 'toy', 'extensions')
20
+ Dir[extensions_path + '**/*.rb'].each { |file| require(file) }
21
+
22
+ module Toy
23
+ extend self
24
+
25
+ # Resets all tracking of things in memory. Useful for running
26
+ # before each request in development mode with Rails and such.
27
+ def reset
28
+ identity_map.clear
29
+ plugins.clear
30
+ models.clear
31
+ end
32
+
33
+ # Clears all the stores for all the models. Useful in specs/tests/etc.
34
+ # Do not use in production, harty harr harr.
35
+ #
36
+ # Note: that if your models are auto-loaded like in Rails, you will need
37
+ # to make sure they are loaded in order to clear them or ToyStore will
38
+ # not be aware of their existence.
39
+ def clear
40
+ models.each do |model|
41
+ model.store.clear if model.has_store?
42
+ model.cache.clear if model.has_cache?
43
+ model.identity_map.clear if model.identity_map_on?
44
+ end
45
+ end
46
+ end
47
+
48
+ require 'toy/exceptions'
49
+ require 'toy/connection'
50
+ require 'toy/attribute'
51
+ require 'toy/attributes'
52
+ require 'toy/callbacks'
53
+ require 'toy/dirty'
54
+ require 'toy/dolly'
55
+ require 'toy/equality'
56
+ require 'toy/inspect'
57
+ require 'toy/persistence'
58
+ require 'toy/mass_assignment_security'
59
+ require 'toy/plugins'
60
+ require 'toy/store'
61
+ require 'toy/serialization'
62
+ require 'toy/timestamps'
63
+ require 'toy/validations'
64
+ require 'toy/querying'
65
+ require 'toy/identity_map'
66
+
67
+ require 'toy/collection'
68
+ require 'toy/embedded_list'
69
+ require 'toy/embedded_lists'
70
+ require 'toy/list'
71
+ require 'toy/lists'
72
+ require 'toy/reference'
73
+ require 'toy/references'
74
+
75
+ require 'toy/index'
76
+ require 'toy/indices'
77
+ require 'toy/identity/abstract_key_factory'
78
+ require 'toy/identity/uuid_key_factory'
79
+ require 'toy/identity'
80
+ require 'toy/caching'
81
+ require 'toy/logger'
@@ -0,0 +1,73 @@
1
+ module Toy
2
+ class Attribute
3
+ attr_reader :model, :name, :type, :options
4
+
5
+ def initialize(model, name, type, options={})
6
+ options.assert_valid_keys(:default, :embedded_list, :virtual, :abbr)
7
+
8
+ @model, @name, @type, @options = model, name.to_sym, type, options
9
+ @virtual = options.fetch(:virtual, false)
10
+
11
+ if abbr?
12
+ options[:abbr] = abbr.to_sym
13
+ model.alias_attribute(abbr, name)
14
+ end
15
+
16
+ model.attributes[name.to_s] = self
17
+ end
18
+
19
+ def from_store(value)
20
+ value = default if default? && value.nil?
21
+ type.from_store(value, self)
22
+ end
23
+
24
+ def to_store(value)
25
+ value = default if default? && value.nil?
26
+ type.to_store(value, self)
27
+ end
28
+
29
+ def default
30
+ if options.key?(:default)
31
+ options[:default].respond_to?(:call) ? options[:default].call : options[:default]
32
+ else
33
+ type.respond_to?(:store_default) ? type.store_default : nil
34
+ end
35
+ end
36
+
37
+ def default?
38
+ options.key?(:default) || type.respond_to?(:store_default)
39
+ end
40
+
41
+ def virtual?
42
+ @virtual
43
+ end
44
+
45
+ def persisted?
46
+ !virtual?
47
+ end
48
+
49
+ def abbr?
50
+ options.key?(:abbr)
51
+ end
52
+
53
+ def abbr
54
+ options[:abbr]
55
+ end
56
+
57
+ def store_key
58
+ (abbr? ? abbr : name).to_s
59
+ end
60
+
61
+ # Stores reference to related embedded list
62
+ def embedded_list
63
+ options[:embedded_list]
64
+ end
65
+
66
+ def eql?(other)
67
+ self.class.eql?(other.class) &&
68
+ model == other.model &&
69
+ name == other.name
70
+ end
71
+ alias :== :eql?
72
+ end
73
+ end
@@ -0,0 +1,137 @@
1
+ module Toy
2
+ module Attributes
3
+ extend ActiveSupport::Concern
4
+ include ActiveModel::AttributeMethods
5
+
6
+ included do
7
+ attribute_method_suffix('', '=', '?')
8
+ attribute :id, String
9
+ end
10
+
11
+ module ClassMethods
12
+ def attributes
13
+ @attributes ||= {}
14
+ end
15
+
16
+ def defaulted_attributes
17
+ attributes.values.select(&:default?)
18
+ end
19
+
20
+ def attribute(key, type, options = {})
21
+ Attribute.new(self, key, type, options)
22
+ end
23
+
24
+ def attribute?(key)
25
+ attributes.has_key?(key.to_s)
26
+ end
27
+ end
28
+
29
+ module InstanceMethods
30
+ def initialize(attrs={})
31
+ @_new_record = true unless defined?(@_new_record)
32
+ initialize_attributes_with_defaults
33
+ self.attributes = attrs
34
+ write_attribute :id, self.class.next_key(self) unless id?
35
+ end
36
+
37
+ def initialize_from_database(attrs={})
38
+ @_new_record = false
39
+ send(:initialize, attrs)
40
+ self
41
+ end
42
+
43
+ def reload
44
+ if attrs = store.read(store_key)
45
+ instance_variables.each { |ivar| instance_variable_set(ivar, nil) }
46
+ initialize_attributes_with_defaults
47
+ self.attributes = attrs
48
+ self.class.lists.each_key { |name| send(name).reset }
49
+ self.class.references.each_key { |name| send(name).reset }
50
+ else
51
+ raise NotFound.new(id)
52
+ end
53
+ self
54
+ end
55
+
56
+ def id
57
+ read_attribute(:id)
58
+ end
59
+
60
+ def attributes
61
+ @attributes
62
+ end
63
+
64
+ def persisted_attributes
65
+ {}.tap do |attrs|
66
+ self.class.attributes.each do |name, attribute|
67
+ next if attribute.virtual?
68
+ attrs[attribute.store_key] = attribute.to_store(read_attribute(attribute.name))
69
+ end
70
+ end.merge(embedded_attributes)
71
+ end
72
+
73
+ def embedded_attributes
74
+ {}.tap do |attrs|
75
+ self.class.embedded_lists.each_key do |name|
76
+ attrs[name.to_s] = send(name).map(&:persisted_attributes)
77
+ end
78
+ end
79
+ end
80
+
81
+ def attributes=(attrs)
82
+ return if attrs.nil?
83
+ attrs.each do |key, value|
84
+ if attribute_method?(key)
85
+ write_attribute(key, value)
86
+ elsif respond_to?("#{key}=")
87
+ send("#{key}=", value)
88
+ end
89
+ end
90
+ end
91
+
92
+ def [](key)
93
+ read_attribute(key)
94
+ end
95
+
96
+ def []=(key, value)
97
+ write_attribute(key, value)
98
+ end
99
+
100
+ private
101
+ def read_attribute(key)
102
+ @attributes[key]
103
+ end
104
+
105
+ def write_attribute(key, value)
106
+ @attributes[key] = attribute_definition(key).try(:from_store, value)
107
+ end
108
+
109
+ def attribute_definition(key)
110
+ self.class.attributes[key.to_s]
111
+ end
112
+
113
+ def attribute_method?(key)
114
+ self.class.attribute?(key)
115
+ end
116
+
117
+ def attribute(key)
118
+ read_attribute(key)
119
+ end
120
+
121
+ def attribute=(key, value)
122
+ write_attribute(key, value)
123
+ end
124
+
125
+ def attribute?(key)
126
+ read_attribute(key).present?
127
+ end
128
+
129
+ def initialize_attributes_with_defaults
130
+ @attributes = {}.with_indifferent_access
131
+ self.class.defaulted_attributes.each do |attribute|
132
+ @attributes[attribute.name] = attribute.default
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end