active_data 0.3.0 → 1.0.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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rspec +0 -1
  4. data/.rvmrc +1 -1
  5. data/.travis.yml +13 -6
  6. data/Appraisals +7 -0
  7. data/Gemfile +1 -5
  8. data/Guardfile +68 -15
  9. data/README.md +144 -2
  10. data/active_data.gemspec +19 -11
  11. data/gemfiles/rails.4.0.gemfile +14 -0
  12. data/gemfiles/rails.4.1.gemfile +14 -0
  13. data/gemfiles/rails.4.2.gemfile +14 -0
  14. data/gemfiles/rails.5.0.gemfile +14 -0
  15. data/lib/active_data.rb +120 -3
  16. data/lib/active_data/active_record/associations.rb +50 -0
  17. data/lib/active_data/active_record/nested_attributes.rb +24 -0
  18. data/lib/active_data/config.rb +40 -0
  19. data/lib/active_data/errors.rb +93 -0
  20. data/lib/active_data/extensions.rb +33 -0
  21. data/lib/active_data/model.rb +16 -74
  22. data/lib/active_data/model/associations.rb +84 -15
  23. data/lib/active_data/model/associations/base.rb +79 -0
  24. data/lib/active_data/model/associations/collection/embedded.rb +12 -0
  25. data/lib/active_data/model/associations/collection/proxy.rb +32 -0
  26. data/lib/active_data/model/associations/collection/referenced.rb +26 -0
  27. data/lib/active_data/model/associations/embeds_many.rb +124 -18
  28. data/lib/active_data/model/associations/embeds_one.rb +90 -15
  29. data/lib/active_data/model/associations/nested_attributes.rb +180 -0
  30. data/lib/active_data/model/associations/references_many.rb +96 -0
  31. data/lib/active_data/model/associations/references_one.rb +83 -0
  32. data/lib/active_data/model/associations/reflections/base.rb +100 -0
  33. data/lib/active_data/model/associations/reflections/embeds_many.rb +25 -0
  34. data/lib/active_data/model/associations/reflections/embeds_one.rb +49 -0
  35. data/lib/active_data/model/associations/reflections/reference_reflection.rb +45 -0
  36. data/lib/active_data/model/associations/reflections/references_many.rb +28 -0
  37. data/lib/active_data/model/associations/reflections/references_one.rb +28 -0
  38. data/lib/active_data/model/associations/validations.rb +63 -0
  39. data/lib/active_data/model/attributes.rb +247 -0
  40. data/lib/active_data/model/attributes/attribute.rb +73 -0
  41. data/lib/active_data/model/attributes/base.rb +116 -0
  42. data/lib/active_data/model/attributes/collection.rb +17 -0
  43. data/lib/active_data/model/attributes/dictionary.rb +26 -0
  44. data/lib/active_data/model/attributes/localized.rb +42 -0
  45. data/lib/active_data/model/attributes/reference_many.rb +21 -0
  46. data/lib/active_data/model/attributes/reference_one.rb +42 -0
  47. data/lib/active_data/model/attributes/reflections/attribute.rb +55 -0
  48. data/lib/active_data/model/attributes/reflections/base.rb +62 -0
  49. data/lib/active_data/model/attributes/reflections/collection.rb +10 -0
  50. data/lib/active_data/model/attributes/reflections/dictionary.rb +13 -0
  51. data/lib/active_data/model/attributes/reflections/localized.rb +43 -0
  52. data/lib/active_data/model/attributes/reflections/reference_many.rb +10 -0
  53. data/lib/active_data/model/attributes/reflections/reference_one.rb +58 -0
  54. data/lib/active_data/model/attributes/reflections/represents.rb +55 -0
  55. data/lib/active_data/model/attributes/represents.rb +64 -0
  56. data/lib/active_data/model/callbacks.rb +71 -0
  57. data/lib/active_data/model/conventions.rb +35 -0
  58. data/lib/active_data/model/dirty.rb +77 -0
  59. data/lib/active_data/model/lifecycle.rb +307 -0
  60. data/lib/active_data/model/localization.rb +21 -0
  61. data/lib/active_data/model/persistence.rb +57 -0
  62. data/lib/active_data/model/primary.rb +51 -0
  63. data/lib/active_data/model/scopes.rb +77 -0
  64. data/lib/active_data/model/validations.rb +27 -0
  65. data/lib/active_data/model/validations/associated.rb +19 -0
  66. data/lib/active_data/model/validations/nested.rb +39 -0
  67. data/lib/active_data/railtie.rb +7 -0
  68. data/lib/active_data/version.rb +1 -1
  69. data/spec/lib/active_data/active_record/associations_spec.rb +149 -0
  70. data/spec/lib/active_data/active_record/nested_attributes_spec.rb +16 -0
  71. data/spec/lib/active_data/config_spec.rb +44 -0
  72. data/spec/lib/active_data/model/associations/embeds_many_spec.rb +362 -52
  73. data/spec/lib/active_data/model/associations/embeds_one_spec.rb +250 -31
  74. data/spec/lib/active_data/model/associations/nested_attributes_spec.rb +23 -0
  75. data/spec/lib/active_data/model/associations/references_many_spec.rb +196 -0
  76. data/spec/lib/active_data/model/associations/references_one_spec.rb +134 -0
  77. data/spec/lib/active_data/model/associations/reflections/embeds_many_spec.rb +144 -0
  78. data/spec/lib/active_data/model/associations/reflections/embeds_one_spec.rb +116 -0
  79. data/spec/lib/active_data/model/associations/reflections/references_many_spec.rb +255 -0
  80. data/spec/lib/active_data/model/associations/reflections/references_one_spec.rb +208 -0
  81. data/spec/lib/active_data/model/associations/validations_spec.rb +153 -0
  82. data/spec/lib/active_data/model/associations_spec.rb +189 -0
  83. data/spec/lib/active_data/model/attributes/attribute_spec.rb +144 -0
  84. data/spec/lib/active_data/model/attributes/base_spec.rb +82 -0
  85. data/spec/lib/active_data/model/attributes/collection_spec.rb +73 -0
  86. data/spec/lib/active_data/model/attributes/dictionary_spec.rb +93 -0
  87. data/spec/lib/active_data/model/attributes/localized_spec.rb +88 -33
  88. data/spec/lib/active_data/model/attributes/reflections/attribute_spec.rb +72 -0
  89. data/spec/lib/active_data/model/attributes/reflections/base_spec.rb +56 -0
  90. data/spec/lib/active_data/model/attributes/reflections/collection_spec.rb +37 -0
  91. data/spec/lib/active_data/model/attributes/reflections/dictionary_spec.rb +43 -0
  92. data/spec/lib/active_data/model/attributes/reflections/localized_spec.rb +37 -0
  93. data/spec/lib/active_data/model/attributes/reflections/represents_spec.rb +70 -0
  94. data/spec/lib/active_data/model/attributes/represents_spec.rb +153 -0
  95. data/spec/lib/active_data/model/attributes_spec.rb +243 -0
  96. data/spec/lib/active_data/model/callbacks_spec.rb +338 -0
  97. data/spec/lib/active_data/model/conventions_spec.rb +12 -0
  98. data/spec/lib/active_data/model/dirty_spec.rb +75 -0
  99. data/spec/lib/active_data/model/lifecycle_spec.rb +330 -0
  100. data/spec/lib/active_data/model/nested_attributes.rb +202 -0
  101. data/spec/lib/active_data/model/persistence_spec.rb +47 -0
  102. data/spec/lib/active_data/model/primary_spec.rb +84 -0
  103. data/spec/lib/active_data/model/scopes_spec.rb +88 -0
  104. data/spec/lib/active_data/model/typecasting_spec.rb +192 -0
  105. data/spec/lib/active_data/model/validations/associated_spec.rb +94 -0
  106. data/spec/lib/active_data/model/validations/nested_spec.rb +93 -0
  107. data/spec/lib/active_data/model/validations_spec.rb +31 -0
  108. data/spec/lib/active_data/model_spec.rb +1 -32
  109. data/spec/lib/active_data_spec.rb +12 -0
  110. data/spec/spec_helper.rb +39 -0
  111. data/spec/support/model_helpers.rb +10 -0
  112. metadata +246 -54
  113. data/gemfiles/Gemfile.rails-3 +0 -14
  114. data/lib/active_data/attributes/base.rb +0 -69
  115. data/lib/active_data/attributes/localized.rb +0 -42
  116. data/lib/active_data/model/associations/association.rb +0 -30
  117. data/lib/active_data/model/attributable.rb +0 -122
  118. data/lib/active_data/model/collectionizable.rb +0 -55
  119. data/lib/active_data/model/collectionizable/proxy.rb +0 -42
  120. data/lib/active_data/model/extensions.rb +0 -9
  121. data/lib/active_data/model/extensions/array.rb +0 -24
  122. data/lib/active_data/model/extensions/big_decimal.rb +0 -17
  123. data/lib/active_data/model/extensions/boolean.rb +0 -38
  124. data/lib/active_data/model/extensions/date.rb +0 -17
  125. data/lib/active_data/model/extensions/date_time.rb +0 -17
  126. data/lib/active_data/model/extensions/float.rb +0 -17
  127. data/lib/active_data/model/extensions/hash.rb +0 -22
  128. data/lib/active_data/model/extensions/integer.rb +0 -17
  129. data/lib/active_data/model/extensions/localized.rb +0 -22
  130. data/lib/active_data/model/extensions/object.rb +0 -17
  131. data/lib/active_data/model/extensions/string.rb +0 -17
  132. data/lib/active_data/model/extensions/time.rb +0 -17
  133. data/lib/active_data/model/localizable.rb +0 -31
  134. data/lib/active_data/model/nested_attributes.rb +0 -58
  135. data/lib/active_data/model/parameterizable.rb +0 -29
  136. data/lib/active_data/validations.rb +0 -7
  137. data/lib/active_data/validations/associated.rb +0 -17
  138. data/spec/lib/active_data/model/attributable_spec.rb +0 -191
  139. data/spec/lib/active_data/model/collectionizable_spec.rb +0 -60
  140. data/spec/lib/active_data/model/nested_attributes_spec.rb +0 -67
  141. data/spec/lib/active_data/model/type_cast_spec.rb +0 -116
  142. data/spec/lib/active_data/validations/associated_spec.rb +0 -88
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Date
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- value.to_date rescue nil
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- Date.send :include, ActiveData::Model::Extensions::Date
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module DateTime
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- value.to_datetime rescue nil
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- DateTime.send :include, ActiveData::Model::Extensions::DateTime
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Float
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- Float(value) rescue nil if value
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- Float.send :include, ActiveData::Model::Extensions::Float
@@ -1,22 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Hash
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- case value
10
- when ::Hash then
11
- value
12
- else
13
- nil
14
- end
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
21
-
22
- Hash.send :include, ActiveData::Model::Extensions::Hash
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Integer
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- Float(value).to_i rescue nil if value
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- Integer.send :include, ActiveData::Model::Extensions::Integer
@@ -1,22 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Localized
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- case value
10
- when ::Hash then
11
- value.stringify_keys
12
- else
13
- nil
14
- end
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
21
-
22
- Localized.send :include, ActiveData::Model::Extensions::Localized
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Object
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- value
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- Object.send :include, ActiveData::Model::Extensions::Object
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module String
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- value.to_s if value.present?
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- String.send :include, ActiveData::Model::Extensions::String
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Time
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- value.to_time rescue nil
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- Time.send :include, ActiveData::Model::Extensions::Time
@@ -1,31 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Localizable
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- end
8
-
9
- module ClassMethods
10
- def fallbacks locale
11
- ::I18n.respond_to?(:fallbacks) ? ::I18n.fallbacks[locale] : [locale]
12
- end
13
-
14
- def locale
15
- I18n.locale
16
- end
17
- end
18
-
19
- def read_localized_attribute name, locale = self.class.locale
20
- translations = read_attribute(name.to_s)
21
- translations[self.class.fallbacks(locale).detect { |fallback| translations[fallback.to_s] }.to_s]
22
- end
23
- alias_method :read_localized_attribute_before_type_cast, :read_localized_attribute
24
-
25
- def write_localized_attribute name, value, locale = self.class.locale
26
- translations = read_attribute(name.to_s)
27
- write_attribute(name, translations.merge(locale.to_s => value))
28
- end
29
- end
30
- end
31
- end
@@ -1,58 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module NestedAttributes
4
- extend ActiveSupport::Concern
5
-
6
- module ClassMethods
7
-
8
- def nested_attributes? association_name
9
- method_defined?(:"#{association_name}_attributes=")
10
- end
11
-
12
- def accepts_nested_attributes_for *attr_names
13
- attr_names.each do |association_name|
14
- reflection = reflect_on_association association_name
15
- type = (reflection.collection? ? :collection : :one_to_one)
16
-
17
- class_eval <<-EOS, __FILE__, __LINE__ + 1
18
- if method_defined?(:#{association_name}_attributes=)
19
- remove_method(:#{association_name}_attributes=)
20
- end
21
- def #{association_name}_attributes=(attributes)
22
- assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
23
- end
24
- EOS
25
- end
26
- end
27
-
28
- end
29
-
30
- def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {})
31
- unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
32
- raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
33
- end
34
-
35
- if attributes_collection.is_a? Hash
36
- keys = attributes_collection.keys
37
- attributes_collection = if keys.include?('id') || keys.include?(:id)
38
- Array.wrap(attributes_collection)
39
- else
40
- attributes_collection.values
41
- end
42
- end
43
-
44
- reflection = self.class.reflect_on_association association_name
45
-
46
- send "#{association_name}=", attributes_collection
47
- end
48
-
49
- def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {})
50
- unless attributes.is_a?(Hash)
51
- raise ArgumentError, "Hash expected, got #{attributes.class.name} (#{attributes.inspect})"
52
- end
53
-
54
- send "#{association_name}=", attributes
55
- end
56
- end
57
- end
58
- end
@@ -1,29 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Parameterizable
4
- extend ActiveSupport::Concern
5
-
6
- def to_params options = nil
7
- hash = serializable_hash options
8
-
9
- self.class.association_names.each do |association_name|
10
- if self.class.nested_attributes? association_name
11
- records = send(association_name)
12
- hash["#{association_name}_attributes"] = if records.is_a?(Enumerable)
13
- attributes = {}
14
- records.each_with_index do |a, i|
15
- key = a.has_attribute?(:id) && a.id? ? a.id : i
16
- attributes[key.to_s] = a.serializable_hash
17
- end
18
- attributes
19
- else
20
- records.serializable_hash
21
- end
22
- end
23
- end
24
-
25
- hash
26
- end
27
- end
28
- end
29
- end
@@ -1,7 +0,0 @@
1
- require 'active_data/validations/associated'
2
-
3
- module ActiveData
4
- module Validations
5
- extend ActiveSupport::Concern
6
- end
7
- end
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Validations
3
- class AssociatedValidator < ActiveModel::EachValidator #:nodoc:
4
- def validate_each(record, attribute, value)
5
- if Array.wrap(value).reject { |r| r.respond_to?(:valid?) && r.valid?(record.validation_context) }.any?
6
- record.errors.add(attribute, :invalid, options.merge(:value => value))
7
- end
8
- end
9
- end
10
-
11
- module ClassMethods
12
- def validates_associated(*attr_names)
13
- validates_with AssociatedValidator, _merge_attributes(attr_names)
14
- end
15
- end
16
- end
17
- end
@@ -1,191 +0,0 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
3
-
4
- describe ActiveData::Model::Attributable do
5
-
6
- let(:klass) do
7
- Class.new do
8
- include ActiveData::Model::Attributable
9
- attr_reader :name
10
-
11
- attribute :hello
12
- attribute :string, type: String, default_blank: true, default: ->(record){ record.name }
13
- attribute :count, type: Integer, default: 10
14
- attribute(:calc, type: Integer) { 2 + 3 }
15
- attribute :enum, type: Integer, in: [1, 2, 3]
16
- attribute :foo, type: Boolean, default: false
17
-
18
- def initialize name = nil
19
- @attributes = self.class.initialize_attributes
20
- @name = name
21
- end
22
- end
23
- end
24
-
25
- context do
26
- subject { klass.new('world') }
27
- specify { klass.enum_values.should == [1, 2, 3] }
28
- its(:attributes) { should == { hello: nil, count: 10, calc: 5, enum: nil, string: 'world', foo: false } }
29
- its(:present_attributes) { should == { count: 10, calc: 5, string: 'world', foo: false } }
30
- its(:name) { should == 'world' }
31
- its(:hello) { should be_nil }
32
- its(:count) { should == 10 }
33
- its(:calc) { should == 5 }
34
- specify { expect { subject.hello = 'worlds' } .to change { subject.hello } .from(nil).to('worlds') }
35
- specify { expect { subject.count = 20 } .to change { subject.count } .from(10).to(20) }
36
- specify { expect { subject.calc = 15 } .to change { subject.calc } .from(5).to(15) }
37
- end
38
-
39
- context 'calculating default values' do
40
- let(:klass) do
41
- Class.new do
42
- include ActiveData::Model::Attributable
43
-
44
- attribute(:rand, type: String) { SecureRandom.uuid }
45
-
46
- def initialize
47
- @attributes = self.class.initialize_attributes
48
- end
49
- end
50
- end
51
-
52
- subject { klass.new }
53
- specify { subject.rand.should == subject.rand }
54
- specify { subject.rand.should_not == klass.new.rand }
55
- end
56
-
57
- context 'default_blank' do
58
- let(:klass) do
59
- Class.new do
60
- include ActiveData::Model::Attributable
61
-
62
- attribute :string1, type: String, default_blank: true, default: 'default'
63
- attribute :string2, type: String, default: 'default'
64
-
65
- def initialize attributes = {}
66
- @attributes = self.class.initialize_attributes
67
- self.attributes = attributes
68
- end
69
- end
70
- end
71
-
72
- specify { klass.new.string1.should == 'default' }
73
- specify { klass.new.string2.should == 'default' }
74
- specify { klass.new(string1: '').string1.should == 'default' }
75
- specify { klass.new(string2: '').string2.should == '' }
76
- specify { klass.new(string1: 'hello').string1.should == 'hello' }
77
- specify { klass.new(string2: 'hello').string2.should == 'hello' }
78
- end
79
-
80
- context 'default_blank with boolean' do
81
- let(:klass) do
82
- Class.new do
83
- include ActiveData::Model::Attributable
84
-
85
- attribute :boolean1, type: Boolean, default_blank: true, default: true
86
- attribute :boolean2, type: Boolean, default: true
87
- attribute :boolean3, type: Boolean, default_blank: true, default: false
88
- attribute :boolean4, type: Boolean, default: false
89
-
90
- def initialize attributes = {}
91
- @attributes = self.class.initialize_attributes
92
- self.attributes = attributes
93
- end
94
- end
95
- end
96
-
97
- specify { klass.new.boolean1.should == true }
98
- specify { klass.new.boolean2.should == true }
99
- specify { klass.new.boolean3.should == false }
100
- specify { klass.new.boolean4.should == false }
101
- specify { klass.new(boolean1: '').boolean1.should == true }
102
- specify { klass.new(boolean2: '').boolean2.should == true }
103
- specify { klass.new(boolean3: '').boolean3.should == false }
104
- specify { klass.new(boolean4: '').boolean4.should == false }
105
- specify { klass.new(boolean1: false).boolean1.should == false }
106
- specify { klass.new(boolean2: false).boolean2.should == false }
107
- specify { klass.new(boolean3: false).boolean3.should == false }
108
- specify { klass.new(boolean4: false).boolean4.should == false }
109
- specify { klass.new(boolean1: true).boolean1.should == true }
110
- specify { klass.new(boolean2: true).boolean2.should == true }
111
- specify { klass.new(boolean3: true).boolean3.should == true }
112
- specify { klass.new(boolean4: true).boolean4.should == true }
113
- end
114
-
115
- context 'attribute caching' do
116
- subject { klass.new('world') }
117
-
118
- context do
119
- before do
120
- subject.send(:attributes_cache).should_not_receive(:[])
121
- end
122
-
123
- specify { subject.hello }
124
- end
125
-
126
- context do
127
- before do
128
- subject.hello
129
- subject.send(:attributes_cache).should_receive(:[]).with(:hello).once
130
- end
131
-
132
- specify { subject.hello }
133
- end
134
-
135
- context 'attribute cache reset' do
136
- before do
137
- subject.hello = 'blabla'
138
- subject.hello
139
- subject.hello = 'newnewnew'
140
- end
141
-
142
- specify { subject.hello.should == 'newnewnew' }
143
- end
144
- end
145
-
146
- context 'inheritance' do
147
- let!(:ancestor) do
148
- Class.new do
149
- include ActiveData::Model::Attributable
150
- attribute :foo
151
- end
152
- end
153
-
154
- let!(:descendant1) do
155
- Class.new ancestor do
156
- attribute :bar
157
- end
158
- end
159
-
160
- let!(:descendant2) do
161
- Class.new ancestor do
162
- attribute :baz
163
- attribute :moo
164
- end
165
- end
166
-
167
- specify { ancestor._attributes.keys.should == [:foo] }
168
- specify { ancestor.instance_methods.should include :foo, :foo= }
169
- specify { ancestor.instance_methods.should_not include :bar, :bar=, :baz, :baz= }
170
- specify { descendant1._attributes.keys.should == [:foo, :bar] }
171
- specify { descendant1.instance_methods.should include :foo, :foo=, :bar, :bar= }
172
- specify { descendant1.instance_methods.should_not include :baz, :baz= }
173
- specify { descendant2._attributes.keys.should == [:foo, :baz, :moo] }
174
- specify { descendant2.instance_methods.should include :foo, :foo=, :baz, :baz=, :moo, :moo= }
175
- specify { descendant2.instance_methods.should_not include :bar, :bar= }
176
- end
177
-
178
- context '#write_attributes' do
179
- subject { klass.new('world') }
180
-
181
- specify { expect { subject.write_attributes(strange: 'value') }.to raise_error NoMethodError }
182
-
183
- context do
184
- before { subject.write_attributes('hello' => 'blabla', count: 20) }
185
- specify do
186
- subject.attributes.should == { hello: 'blabla', count: 20, calc: 5, enum: nil, string: 'world', foo: false }
187
- end
188
- end
189
- end
190
-
191
- end