disposable 0.0.9 → 0.1.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -5
  3. data/CHANGES.md +4 -0
  4. data/Gemfile +1 -1
  5. data/README.md +154 -1
  6. data/database.sqlite3 +0 -0
  7. data/disposable.gemspec +7 -7
  8. data/gemfiles/Gemfile.rails-3.0.lock +10 -8
  9. data/gemfiles/Gemfile.rails-3.2.lock +9 -7
  10. data/gemfiles/Gemfile.rails-4.0.lock +9 -7
  11. data/gemfiles/Gemfile.rails-4.1.lock +10 -8
  12. data/lib/disposable.rb +6 -7
  13. data/lib/disposable/callback.rb +174 -0
  14. data/lib/disposable/composition.rb +21 -58
  15. data/lib/disposable/expose.rb +49 -0
  16. data/lib/disposable/twin.rb +85 -38
  17. data/lib/disposable/twin/builder.rb +12 -30
  18. data/lib/disposable/twin/changed.rb +50 -0
  19. data/lib/disposable/twin/collection.rb +95 -0
  20. data/lib/disposable/twin/composition.rb +43 -15
  21. data/lib/disposable/twin/option.rb +1 -1
  22. data/lib/disposable/twin/persisted.rb +20 -0
  23. data/lib/disposable/twin/property_processor.rb +29 -0
  24. data/lib/disposable/twin/representer.rb +42 -14
  25. data/lib/disposable/twin/save.rb +19 -34
  26. data/lib/disposable/twin/schema.rb +31 -0
  27. data/lib/disposable/twin/setup.rb +38 -0
  28. data/lib/disposable/twin/sync.rb +114 -0
  29. data/lib/disposable/version.rb +1 -1
  30. data/test/api_semantics_test.rb +263 -0
  31. data/test/callback_group_test.rb +222 -0
  32. data/test/callbacks_test.rb +450 -0
  33. data/test/example.rb +40 -0
  34. data/test/expose_test.rb +92 -0
  35. data/test/persisted_test.rb +101 -0
  36. data/test/test_helper.rb +64 -0
  37. data/test/twin/benchmarking.rb +33 -0
  38. data/test/twin/builder_test.rb +32 -0
  39. data/test/twin/changed_test.rb +108 -0
  40. data/test/twin/collection_test.rb +223 -0
  41. data/test/twin/composition_test.rb +56 -25
  42. data/test/twin/expose_test.rb +73 -0
  43. data/test/twin/feature_test.rb +61 -0
  44. data/test/twin/from_test.rb +37 -0
  45. data/test/twin/inherit_test.rb +57 -0
  46. data/test/twin/option_test.rb +27 -0
  47. data/test/twin/readable_test.rb +57 -0
  48. data/test/twin/save_test.rb +192 -0
  49. data/test/twin/schema_test.rb +69 -0
  50. data/test/twin/setup_test.rb +139 -0
  51. data/test/twin/skip_unchanged_test.rb +64 -0
  52. data/test/twin/struct_test.rb +168 -0
  53. data/test/twin/sync_option_test.rb +228 -0
  54. data/test/twin/sync_test.rb +128 -0
  55. data/test/twin/twin_test.rb +49 -128
  56. data/test/twin/writeable_test.rb +56 -0
  57. metadata +106 -20
  58. data/STUFF +0 -4
  59. data/lib/disposable/twin/finders.rb +0 -29
  60. data/lib/disposable/twin/new.rb +0 -30
  61. data/lib/disposable/twin/save_.rb +0 -21
  62. data/test/composition_test.rb +0 -102
@@ -0,0 +1,128 @@
1
+ require "test_helper"
2
+
3
+ class TwinSyncTest < MiniTest::Spec
4
+ module Model
5
+ Song = Struct.new(:title, :composer)
6
+ Album = Struct.new(:name, :songs, :artist)
7
+ Artist = Struct.new(:name)
8
+ end
9
+
10
+
11
+ module Twin
12
+ class Album < Disposable::Twin
13
+ feature Setup
14
+ feature Sync
15
+
16
+ property :name
17
+
18
+ collection :songs do
19
+ property :title
20
+
21
+ property :composer do
22
+ property :name
23
+ end
24
+ end
25
+
26
+ property :artist do
27
+ property :name
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+ let (:song) { Model::Song.new() }
34
+ let (:composer) { Model::Artist.new(nil) }
35
+ let (:song_with_composer) { Model::Song.new(nil, composer) }
36
+ let (:artist) { Model::Artist.new(nil) }
37
+
38
+
39
+ describe "#sync" do
40
+ let (:album) { Model::Album.new(nil, [song, song_with_composer], artist) }
41
+
42
+ # with populated model.
43
+ it do
44
+ twin = Twin::Album.new(album)
45
+
46
+ # this usually happens in Contract::Validate or in from_* in a representer
47
+ fill_out!(twin)
48
+
49
+ # not written to model, yet.
50
+ album.name.must_equal nil
51
+ album.songs[0].title.must_equal nil
52
+ album.songs[1].title.must_equal nil
53
+ album.songs[1].composer.name.must_equal nil
54
+ album.artist.name.must_equal nil
55
+
56
+ twin.sync
57
+
58
+ album.name.must_equal "Live And Dangerous"
59
+ album.songs[0].must_be_instance_of Model::Song
60
+ album.songs[1].must_be_instance_of Model::Song
61
+ album.songs[0].title.must_equal "Southbound"
62
+ album.songs[1].title.must_equal "The Boys Are Back In Town"
63
+ album.songs[1].composer.must_be_instance_of Model::Artist
64
+ album.songs[1].composer.name.must_equal "Lynott"
65
+ album.artist.must_be_instance_of Model::Artist
66
+ album.artist.name.must_equal "Thin Lizzy"
67
+ end
68
+
69
+ # with empty, not populated model.
70
+ it do
71
+ album = Model::Album.new(nil, [])
72
+ twin = Twin::Album.new(album)
73
+
74
+ # this usually happens in Contract::Validate or in from_* in a representer
75
+ twin.name = "Live And Dangerous"
76
+
77
+ twin.songs.insert(0, song)
78
+ twin.songs.insert(1, song_with_composer)
79
+
80
+ twin.songs[0].title = "Southbound"
81
+ twin.songs[1].title = "The Boys Are Back In Town"
82
+ twin.songs[1].composer.name = "Lynott"
83
+
84
+ # not written to model, yet.
85
+ album.name.must_equal nil
86
+ album.songs.must_equal []
87
+ album.artist.must_equal nil
88
+
89
+ twin.sync # this assigns a new collection via #songs=.
90
+
91
+ album.name.must_equal "Live And Dangerous"
92
+ album.songs[0].title.must_equal "Southbound"
93
+ album.songs[1].title.must_equal "The Boys Are Back In Town"
94
+ album.songs[1].composer.name.must_equal "Lynott"
95
+ end
96
+
97
+ # save with block creates nested_hash and doesn't sync.
98
+ it do
99
+ twin = Twin::Album.new(album)
100
+
101
+ # this usually happens in Contract::Validate or in from_* in a representer
102
+ fill_out!(twin)
103
+
104
+ nested_hash = nil
105
+ twin.sync do |hash|
106
+ nested_hash = hash
107
+ end
108
+
109
+ nested_hash.must_equal({"name"=>"Live And Dangerous", "songs"=>[{"title"=>"Southbound"}, {"title"=>"The Boys Are Back In Town", "composer"=>{"name"=>"Lynott"}}], "artist"=>{"name"=>"Thin Lizzy"}})
110
+
111
+ # nothing written to model.
112
+ album.name.must_equal nil
113
+ album.songs[0].title.must_equal nil
114
+ album.songs[1].title.must_equal nil
115
+ album.songs[1].composer.name.must_equal nil
116
+ album.artist.name.must_equal nil
117
+ end
118
+
119
+
120
+ def fill_out!(twin)
121
+ twin.name = "Live And Dangerous"
122
+ twin.songs[0].title = "Southbound"
123
+ twin.songs[1].title = "The Boys Are Back In Town"
124
+ twin.songs[1].composer.name = "Lynott"
125
+ twin.artist.name = "Thin Lizzy"
126
+ end
127
+ end
128
+ end
@@ -1,10 +1,10 @@
1
1
  require 'test_helper'
2
2
 
3
-
4
3
  class TwinTest < MiniTest::Spec
5
4
  module Model
6
5
  Song = Struct.new(:id, :title, :album)
7
- Album = Struct.new(:id, :name, :songs)
6
+ Album = Struct.new(:id, :name, :songs, :artist)
7
+ Artist = Struct.new(:id)
8
8
  end
9
9
 
10
10
 
@@ -13,16 +13,19 @@ class TwinTest < MiniTest::Spec
13
13
  property :id # DISCUSS: needed for #save.
14
14
  property :name
15
15
  collection :songs, :twin => lambda { |*| Song }
16
-
17
- # model Model::Album
16
+ property :artist, :twin => lambda { |*| Artist }
18
17
  end
19
18
 
20
19
  class Song < Disposable::Twin
21
20
  property :id # DISCUSS: needed for #save.
22
- property :name, :from => :title
21
+ property :title
23
22
  property :album, :twin => Album
23
+ end
24
24
 
25
- # model Model::Song
25
+ class Artist < Disposable::Twin
26
+ property :id
27
+
28
+ include Setup
26
29
  end
27
30
  end
28
31
 
@@ -33,14 +36,14 @@ class TwinTest < MiniTest::Spec
33
36
  twin = Twin::Song.new(song)
34
37
  song.id = 2
35
38
  # :from maps public name
36
- twin.name.must_equal "Broken" # public: #name
37
- twin.id.must_equal 2
39
+ twin.title.must_equal "Broken" # public: #record_name
40
+ twin.id.must_equal 1
38
41
  end
39
42
 
40
- # override property with public name in constructor.
43
+ # allows passing options.
41
44
  it do
42
45
  # override twin's value...
43
- Twin::Song.new(song, :name => "Kenny").name.must_equal "Kenny"
46
+ Twin::Song.new(song, :title => "Kenny").title.must_equal "Kenny"
44
47
 
45
48
  # .. but do not write to the model!
46
49
  song.title.must_equal "Broken"
@@ -49,19 +52,47 @@ class TwinTest < MiniTest::Spec
49
52
 
50
53
  describe "setter" do
51
54
  let (:twin) { Twin::Song.new(song) }
55
+ let (:album) { Model::Album.new(1, "The Stories Are True") }
52
56
 
53
- before do
57
+ it do
54
58
  twin.id = 3
55
- twin.name = "Lucky"
59
+ twin.title = "Lucky"
60
+ twin.album = album # this is a model, not a twin.
61
+
62
+ # updates twin
63
+ twin.id.must_equal 3
64
+ twin.title.must_equal "Lucky"
65
+
66
+ # setter for nested property will twin value.
67
+ twin.album.extend(Disposable::Comparable)
68
+ assert twin.album == Twin::Album.new(album) # FIXME: why does must_equal not call #== ?
69
+
70
+ # setter for nested collection.
71
+
72
+ # DOES NOT update model
73
+ song.id.must_equal 1
74
+ song.title.must_equal "Broken"
56
75
  end
57
76
 
58
- # updates twin
59
- it { twin.id.must_equal 3 }
60
- it { twin.name.must_equal "Lucky" }
77
+ # setters for twin properties return the twin, not the model
78
+ # it do
79
+ # result = twin.album = album
80
+ # result.must_equal twin.album
81
+ # end
82
+ end
83
+
84
+ # FIXME: experimental.
85
+ describe "#to_s" do
86
+ class HitTwin < Disposable::Twin
87
+ include Setup
61
88
 
62
- # DOES NOT update model
63
- it { song.id.must_equal 1 }
64
- it { song.title.must_equal "Broken" }
89
+ property :song do
90
+ end
91
+ end
92
+
93
+ let (:hit) { OpenStruct.new(song: song) }
94
+ it { HitTwin.new(hit).to_s.must_match "#<TwinTest::HitTwin:" }
95
+ it { HitTwin.new(hit).song.to_s.must_match "#<Twin (inline):" }
65
96
  end
66
97
  end
67
98
 
@@ -80,36 +111,6 @@ class OverridingAccessorsTest < TwinTest
80
111
  end
81
112
 
82
113
 
83
- class TwinDecoratorTest < MiniTest::Spec
84
- subject { TwinTest::Twin::Song.representer_class.new(nil) }
85
-
86
- it { subject.twin_names.must_equal [:album] }
87
- end
88
-
89
-
90
- require 'disposable/twin/struct'
91
- class TwinStructTest < MiniTest::Spec
92
- class Song < Disposable::Twin
93
- include Struct
94
- property :number, :default => 1 # FIXME: this should be :default_if_nil so it becomes clear with a model.
95
- option :cool?
96
- end
97
-
98
- # empty hash
99
- it { Song.new({}).number.must_equal 1 }
100
- # model hash
101
- it { Song.new(number: 2).number.must_equal 2 }
102
-
103
- # with hash and options as one hash.
104
- it { Song.new(number: 3, cool?: true).cool?.must_equal true }
105
- it { Song.new(number: 3, cool?: true).number.must_equal 3 }
106
-
107
- # with model hash and options hash separated.
108
- it { Song.new({number: 3}, {cool?: true}).cool?.must_equal true }
109
- it { Song.new({number: 3}, {cool?: true}).number.must_equal 3 }
110
- end
111
-
112
-
113
114
  class TwinAsTest < MiniTest::Spec
114
115
  module Model
115
116
  Song = Struct.new(:title, :album)
@@ -133,84 +134,4 @@ class TwinAsTest < MiniTest::Spec
133
134
  end
134
135
 
135
136
  end
136
-
137
-
138
- class TwinOptionTest < TwinTest
139
- class Song < Disposable::Twin
140
- property :id # DISCUSS: needed for #save.
141
- property :title
142
-
143
- option :preview?
144
- option :highlight?
145
- end
146
-
147
- let (:song) { Model::Song.new(1, "Broken") }
148
- let (:twin) { Song.new(song, :preview? => false) }
149
-
150
-
151
- # properties are read from model.
152
- it { twin.id.must_equal 1 }
153
- it { twin.title.must_equal "Broken" }
154
-
155
- # option is not delegated to model.
156
- it { twin.preview?.must_equal false }
157
- # not passing option means zero.
158
- it { twin.highlight?.must_equal nil }
159
-
160
- # passing both options.
161
- it { Song.new(song, preview?: true, highlight?: false).preview?.must_equal true }
162
- end
163
-
164
-
165
- class TwinBuilderTest < MiniTest::Spec
166
- class Twin < Disposable::Twin
167
- property :id
168
- property :title
169
- option :is_released
170
- end
171
-
172
- describe "without property setup" do
173
- class Host
174
- include Disposable::Twin::Builder
175
-
176
- twin Twin
177
-
178
- def initialize(*args)
179
- @model = build_twin(*args)
180
- end
181
-
182
- attr_reader :model
183
- end
184
-
185
- subject { Host.new(TwinTest::Model::Song.new(1, "Saturday Night"), is_released: true) }
186
-
187
- # model is simply the twin.
188
- it { subject.respond_to?(:title).must_equal false }
189
- it { subject.model.id.must_equal 1 }
190
- it { subject.model.title.must_equal "Saturday Night" }
191
- it { subject.model.is_released.must_equal true }
192
- end
193
-
194
-
195
- describe "without property setup" do
196
- class HostWithReaders
197
- include Disposable::Twin::Builder
198
-
199
- extend Forwardable
200
- twin(Twin) { |dfn| def_delegator :@model, dfn.name }
201
-
202
- def initialize(*args)
203
- @model = build_twin(*args)
204
- end
205
- end
206
-
207
- subject { HostWithReaders.new(TwinTest::Model::Song.new(1, "Saturday Night"), is_released: true) }
208
-
209
- # both twin gets created and reader method defined.
210
- it { subject.id.must_equal 1 }
211
- it { subject.title.must_equal "Saturday Night" }
212
- it { subject.is_released.must_equal true }
213
- end
214
- end
215
-
216
137
  # TODO: test coercion!
@@ -0,0 +1,56 @@
1
+ require 'test_helper'
2
+
3
+ class WriteableTest < MiniTest::Spec
4
+ Credentials = Struct.new(:password, :credit_card) do
5
+ def password=(v)
6
+ raise "don't call me!"
7
+ end
8
+ end
9
+
10
+ CreditCard = Struct.new(:name, :number) do
11
+ def number=(v)
12
+ raise "don't call me!"
13
+ end
14
+ end
15
+
16
+ class PasswordForm < Disposable::Twin
17
+ feature Setup
18
+ feature Sync
19
+
20
+ property :password, writeable: false
21
+
22
+ property :credit_card do
23
+ property :name
24
+ property :number, writeable: false
25
+ end
26
+ end
27
+
28
+ let (:cred) { Credentials.new("secret", CreditCard.new("Jonny", "0987654321")) }
29
+
30
+ let (:twin) { PasswordForm.new(cred) }
31
+
32
+ it {
33
+ twin.password.must_equal "secret"
34
+ twin.credit_card.name.must_equal "Jonny"
35
+ twin.credit_card.number.must_equal "0987654321"
36
+
37
+ # manual setting on the twin works.
38
+ twin.password = "123"
39
+ twin.password.must_equal "123"
40
+
41
+ twin.credit_card.number = "456"
42
+ twin.credit_card.number.must_equal "456"
43
+
44
+ twin.sync
45
+
46
+ cred.inspect.must_equal '#<struct WriteableTest::Credentials password="secret", credit_card=#<struct WriteableTest::CreditCard name="Jonny", number="0987654321">>'
47
+
48
+ # test sync{}.
49
+ hash = {}
50
+ twin.sync do |nested|
51
+ hash = nested
52
+ end
53
+
54
+ hash.must_equal("password"=> "123", "credit_card"=>{"name"=>"Jonny", "number"=>"456"})
55
+ }
56
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disposable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-06 00:00:00.000000000 Z
11
+ date: 2015-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uber
@@ -28,16 +28,22 @@ dependencies:
28
28
  name: representable
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.3
34
+ - - "<="
32
35
  - !ruby/object:Gem::Version
33
- version: '2.0'
36
+ version: 2.3.0
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
39
42
  - !ruby/object:Gem::Version
40
- version: '2.0'
43
+ version: 2.2.3
44
+ - - "<="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.3.0
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: bundler
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -70,17 +76,45 @@ dependencies:
70
76
  name: minitest
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
- - - '='
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: activerecord
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: sqlite3
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
74
108
  - !ruby/object:Gem::Version
75
- version: 5.4.1
109
+ version: '0'
76
110
  type: :development
77
111
  prerelease: false
78
112
  version_requirements: !ruby/object:Gem::Requirement
79
113
  requirements:
80
- - - '='
114
+ - - ">="
81
115
  - !ruby/object:Gem::Version
82
- version: 5.4.1
83
- description: Domain-Oriented Refactoring Framework.
116
+ version: '0'
117
+ description: Decorators on top of your ORM layer.
84
118
  email:
85
119
  - apotonick@gmail.com
86
120
  executables: []
@@ -94,7 +128,6 @@ files:
94
128
  - LICENSE.txt
95
129
  - README.md
96
130
  - Rakefile
97
- - STUFF
98
131
  - database.sqlite3
99
132
  - disposable.gemspec
100
133
  - gemfiles/Gemfile.rails-2.3
@@ -108,23 +141,52 @@ files:
108
141
  - gemfiles/Gemfile.rails-4.1
109
142
  - gemfiles/Gemfile.rails-4.1.lock
110
143
  - lib/disposable.rb
144
+ - lib/disposable/callback.rb
111
145
  - lib/disposable/composition.rb
146
+ - lib/disposable/expose.rb
112
147
  - lib/disposable/twin.rb
113
148
  - lib/disposable/twin/builder.rb
149
+ - lib/disposable/twin/changed.rb
150
+ - lib/disposable/twin/collection.rb
114
151
  - lib/disposable/twin/composition.rb
115
- - lib/disposable/twin/finders.rb
116
- - lib/disposable/twin/new.rb
117
152
  - lib/disposable/twin/option.rb
153
+ - lib/disposable/twin/persisted.rb
154
+ - lib/disposable/twin/property_processor.rb
118
155
  - lib/disposable/twin/representer.rb
119
156
  - lib/disposable/twin/save.rb
120
- - lib/disposable/twin/save_.rb
157
+ - lib/disposable/twin/schema.rb
158
+ - lib/disposable/twin/setup.rb
121
159
  - lib/disposable/twin/struct.rb
160
+ - lib/disposable/twin/sync.rb
122
161
  - lib/disposable/version.rb
123
- - test/composition_test.rb
162
+ - test/api_semantics_test.rb
163
+ - test/callback_group_test.rb
164
+ - test/callbacks_test.rb
165
+ - test/example.rb
166
+ - test/expose_test.rb
167
+ - test/persisted_test.rb
124
168
  - test/test_helper.rb
169
+ - test/twin/benchmarking.rb
170
+ - test/twin/builder_test.rb
171
+ - test/twin/changed_test.rb
172
+ - test/twin/collection_test.rb
125
173
  - test/twin/composition_test.rb
174
+ - test/twin/expose_test.rb
175
+ - test/twin/feature_test.rb
176
+ - test/twin/from_test.rb
177
+ - test/twin/inherit_test.rb
178
+ - test/twin/option_test.rb
179
+ - test/twin/readable_test.rb
180
+ - test/twin/save_test.rb
181
+ - test/twin/schema_test.rb
182
+ - test/twin/setup_test.rb
183
+ - test/twin/skip_unchanged_test.rb
184
+ - test/twin/struct_test.rb
185
+ - test/twin/sync_option_test.rb
186
+ - test/twin/sync_test.rb
126
187
  - test/twin/twin_test.rb
127
- homepage: ''
188
+ - test/twin/writeable_test.rb
189
+ homepage: https://github.com/apotonick/disposable
128
190
  licenses:
129
191
  - MIT
130
192
  metadata: {}
@@ -144,12 +206,36 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
206
  version: '0'
145
207
  requirements: []
146
208
  rubyforge_project:
147
- rubygems_version: 2.2.2
209
+ rubygems_version: 2.4.8
148
210
  signing_key:
149
211
  specification_version: 4
150
- summary: Domain-Oriented Refactoring Framework.
212
+ summary: Decorators on top of your ORM layer with change tracking, collection semantics
213
+ and nesting.
151
214
  test_files:
152
- - test/composition_test.rb
215
+ - test/api_semantics_test.rb
216
+ - test/callback_group_test.rb
217
+ - test/callbacks_test.rb
218
+ - test/example.rb
219
+ - test/expose_test.rb
220
+ - test/persisted_test.rb
153
221
  - test/test_helper.rb
222
+ - test/twin/benchmarking.rb
223
+ - test/twin/builder_test.rb
224
+ - test/twin/changed_test.rb
225
+ - test/twin/collection_test.rb
154
226
  - test/twin/composition_test.rb
227
+ - test/twin/expose_test.rb
228
+ - test/twin/feature_test.rb
229
+ - test/twin/from_test.rb
230
+ - test/twin/inherit_test.rb
231
+ - test/twin/option_test.rb
232
+ - test/twin/readable_test.rb
233
+ - test/twin/save_test.rb
234
+ - test/twin/schema_test.rb
235
+ - test/twin/setup_test.rb
236
+ - test/twin/skip_unchanged_test.rb
237
+ - test/twin/struct_test.rb
238
+ - test/twin/sync_option_test.rb
239
+ - test/twin/sync_test.rb
155
240
  - test/twin/twin_test.rb
241
+ - test/twin/writeable_test.rb