disposable 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 530dcd8e13e2d3eeb6a5ef859a3380f610454980
4
- data.tar.gz: d6a2514c02e39f6bdd45d92c604f1ee332edb1f3
3
+ metadata.gz: c909813e9e956a7fc7f01053b0be5984ccfb8ca9
4
+ data.tar.gz: dfa602431c42bb639e696eaf07e5822ad2f89e58
5
5
  SHA512:
6
- metadata.gz: 7f78687f62314fc4dd51b2ed1a6cca4313c84db0f78e18d683131daf18acab106a1e5e031e0e27bf05e26111a68e8e5e67aeba431aa842ee7eff9889349f81d2
7
- data.tar.gz: 5875a24195e83c063c8446dc9a06ad9642e861b52b1f2573ed1ac6884d2a4eaee0af82a7dc7de3fc6261797e51f02593ef6f9aa48d18d46221d1d0303b633e63
6
+ metadata.gz: 8fdf6d50142307f1dad082e3ab73639888e1fe37c482fa49e3379d5751e39e83ba3d60e6f00699083d402f4ca56eb21be111ccbc069f2e0ee28f573838953d18
7
+ data.tar.gz: 99b5c357dbb03d0870ae9934732cc7786e37d728abdcfc6e7430b0cb6ba7de8fb47fd4d589edd501b14528bda26831fced5939814198e7e6906b397907f5bf93
@@ -1,13 +1,31 @@
1
1
  language: ruby
2
2
  sudo: false
3
3
  rvm:
4
- - 2.4.0
5
- - 2.3.0
4
+ - ruby-head
5
+ - 2.5
6
+ - 2.4
7
+ - 2.3
6
8
  - 2.2
7
- - 2.1
8
- # - 2.0
9
+ env:
10
+ - "DRY_TYPES=0.13"
11
+ - "DRY_TYPES=0.12"
12
+ - "ACTIVERECORD=5.0"
13
+ - "ACTIVERECORD=5.1"
14
+ - "ACTIVERECORD=5.2"
9
15
  gemfile:
10
16
  - Gemfile
11
17
  matrix:
18
+ fast_finish: true
19
+ include:
20
+ - { rvm: 2.3, env: ACTIVERECORD=4.2 }
21
+ - { rvm: 2.2, env: ACTIVERECORD=4.2 }
22
+ - { rvm: 2.3, env: ACTIVERECORD=4.1 }
23
+ - { rvm: 2.2, env: ACTIVERECORD=4.1 }
24
+ - rvm: 2.1
25
+ env:
26
+ - ACTIVERECORD=4.1
27
+ - DRY_TYPES=0.10
12
28
  allow_failures:
13
- - rvm: 2.4.0
29
+ - rvm: ruby-head
30
+ - env: ACTIVERECORD=4.1
31
+ - rvm: 2.1
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.4.4
2
+
3
+ * Add support for Dry::Types version 0.13
4
+
1
5
  # 0.4.3
2
6
 
3
7
  * Fix `NoMethodError: private method `property' called for MyForm:Class in Reform.` by using `class_eval`.
data/Gemfile CHANGED
@@ -8,6 +8,11 @@ gemspec
8
8
  # gem "declarative", github: "apotonick/declarative"
9
9
  gem "minitest-line"
10
10
 
11
+ { "dry-types" => ENV['DRY_TYPES'], "activerecord" => ENV['ACTIVERECORD']}.each do |gem_name, dependency|
12
+ next if dependency.nil?
13
+ gem gem_name, dependency
14
+ end
15
+
11
16
  # gem "dry-struct"
12
17
 
13
18
 
data/README.md CHANGED
@@ -181,7 +181,7 @@ property :artist, twin: TwinArtist
181
181
 
182
182
  ## Unnest
183
183
 
184
- #todo: document
184
+ # todo: document
185
185
 
186
186
  ## Features
187
187
 
@@ -206,7 +206,7 @@ class AlbumTwin < Disposable::Twin
206
206
  feature Coercion
207
207
  feature Setup::SkipSetter
208
208
 
209
- property :id, type: Types::Form::Int
209
+ property :id, type: Types::Params::Integer
210
210
  ```
211
211
 
212
212
  The `:type` option defines the coercion type. You may incluce `Setup::SkipSetter`, too, as otherwise the coercion will happen at initialization time and in the setter.
@@ -26,8 +26,8 @@ Gem::Specification.new do |spec|
26
26
  spec.add_development_dependency "bundler", "~> 1.3"
27
27
  spec.add_development_dependency "rake"
28
28
  spec.add_development_dependency "minitest"
29
- spec.add_development_dependency "activerecord", "4.2.5"
29
+ spec.add_development_dependency "activerecord"#, "4.2.5"
30
30
  spec.add_development_dependency "sqlite3"
31
- spec.add_development_dependency "dry-types", "~> 0.6"
31
+ spec.add_development_dependency "dry-types"# "~> 0.6"
32
32
  # spec.add_development_dependency "database_cleaner"
33
33
  end
@@ -30,9 +30,7 @@ class Disposable::Rescheme
30
30
 
31
31
  private
32
32
  def build_representer(options)
33
- Class.new(options[:superclass]) do
34
- include *options[:include]
35
- end
33
+ Class.new(options[:superclass]) { include(*options[:include]) }
36
34
  end
37
35
 
38
36
  def build_definition!(options, source_dfn, representer, &block)
@@ -5,6 +5,9 @@ module Disposable::Twin::Coercion
5
5
  include Dry::Types.module
6
6
  end
7
7
 
8
+ DRY_TYPES_VERSION = Integer(Dry::Types::VERSION.split('.')[-2])
9
+ DRY_TYPES_CONSTANT = DRY_TYPES_VERSION < 13 ? Types::Form : Types::Params
10
+
8
11
  module ClassMethods
9
12
  def property(name, options={}, &block)
10
13
  super(name, options, &block).tap do
@@ -13,11 +16,11 @@ module Disposable::Twin::Coercion
13
16
  end
14
17
 
15
18
  def coercing_setter!(name, type, nilify=false)
16
- type = type ? (Types::Form::Nil | type) : Types::Form::Nil if nilify
19
+ type = type ? (DRY_TYPES_CONSTANT::Nil | type) : DRY_TYPES_CONSTANT::Nil if nilify
17
20
 
18
21
  mod = Module.new do
19
22
  define_method("#{name}=") do |value|
20
- super type.call(value)
23
+ super type.(value)
21
24
  end
22
25
  end
23
26
  include mod
@@ -23,7 +23,7 @@ module Disposable
23
23
  end
24
24
 
25
25
  def setup_property!(dfn, options)
26
- if options.has_key?(name = dfn[:name].to_sym)
26
+ if options.has_key?(dfn[:name].to_sym)
27
27
  value = options[dfn[:name].to_sym]
28
28
  return setup_write!(dfn, value)
29
29
  end
@@ -22,7 +22,7 @@ class Disposable::Twin
22
22
  def self.hash_representer(twin_class, &block)
23
23
  Disposable::Rescheme.from(twin_class,
24
24
  recursive: false,
25
- definitions_from: lambda { |twin_class| twin_class.definitions },
25
+ definitions_from: lambda { |twin_klass| twin_klass.definitions },
26
26
  superclass: Representable::Decorator,
27
27
  include: Representable::Hash,
28
28
  exclude_options: [:default], # TODO: TEST IN default_test.
@@ -1,3 +1,3 @@
1
1
  module Disposable
2
- VERSION = "0.4.3"
2
+ VERSION = "0.4.4"
3
3
  end
@@ -1,6 +1,5 @@
1
1
  require "test_helper"
2
2
  require "disposable/callback"
3
- require "pp"
4
3
 
5
4
  class CallbackGroupTest < MiniTest::Spec
6
5
  class Group < Disposable::Callback::Group
@@ -125,7 +124,7 @@ class CallbackGroupTest < MiniTest::Spec
125
124
 
126
125
  twin.name = "Dear Landlord"
127
126
 
128
- group = Group.new(twin).(context: context = Operation.new, content: content)
127
+ group = Group.new(twin).(context: Operation.new, content: content)
129
128
  # Disposable::Callback::Dispatch.new(twin).on_change{ |twin| puts twin;puts }
130
129
 
131
130
  # pp group.invocations
@@ -185,7 +184,7 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
185
184
 
186
185
  it do
187
186
  Group.hooks.size.must_equal 4
188
- pp EnhancedGroup.hooks
187
+ # pp EnhancedGroup.hooks
189
188
  EnhancedGroup.hooks.size.must_equal 6
190
189
  EnhancedGroup.definitions.get(EnhancedGroup.hooks[5][1])[:nested].hooks.to_s.must_equal "[[:on_add, :rewind!, {}]]"
191
190
  end
@@ -74,9 +74,9 @@ class CallbacksTest < MiniTest::Spec
74
74
 
75
75
  # for collections.
76
76
  it do
77
- album.songs << song1 = Song.new
77
+ album.songs << Song.new
78
78
  album.songs << Song.create(title: "Run For Cover")
79
- album.songs << song2 = Song.new
79
+ album.songs << Song.new
80
80
  invokes = []
81
81
 
82
82
  Callback.new(twin.songs).on_create { |t| invokes << t }
@@ -144,9 +144,9 @@ class CallbacksTest < MiniTest::Spec
144
144
 
145
145
  # for collections.
146
146
  it do
147
- album.songs << song1 = Song.new
147
+ album.songs << Song.new
148
148
  album.songs << Song.create(title: "Run For Cover")
149
- album.songs << song2 = Song.new
149
+ album.songs << Song.new
150
150
 
151
151
  invokes = []
152
152
  Callback.new(twin.songs).on_update { |t| invokes << t }
@@ -350,7 +350,7 @@ class CallbacksTest < MiniTest::Spec
350
350
  song = Song.new
351
351
  album.songs = [ex_song, song]
352
352
 
353
- twin.songs.delete(deleted = twin.songs[0])
353
+ twin.songs.delete(twin.songs[0])
354
354
 
355
355
  Callback.new(twin.songs).on_destroy { |t| invokes << t }
356
356
  invokes.must_equal []
@@ -1,9 +1,13 @@
1
1
  require "disposable"
2
2
  require "minitest/autorun"
3
- require "pp"
4
3
  require "representable/debug"
4
+ # require "pp"
5
5
  require "declarative/testing"
6
6
 
7
+ require "disposable/twin/coercion"
8
+ DRY_TYPES_CONSTANT = Disposable::Twin::Coercion::DRY_TYPES_CONSTANT
9
+ DRY_TYPES_INT_CONSTANT = Disposable::Twin::Coercion::DRY_TYPES_VERSION < 13 ? 'Int' : 'Integer'
10
+
7
11
  class Track
8
12
  def initialize(options={})
9
13
  @title = options[:title]
@@ -12,7 +16,6 @@ class Track
12
16
  attr_reader :title
13
17
  end
14
18
 
15
-
16
19
  # require 'active_record'
17
20
  # require 'database_cleaner'
18
21
  # DatabaseCleaner.strategy = :truncation
@@ -39,18 +42,18 @@ ActiveRecord::Base.establish_connection(
39
42
  ActiveRecord::Schema.define do
40
43
  create_table :artists do |table|
41
44
  table.column :name, :string
42
- table.timestamps
45
+ table.timestamps null: false
43
46
  end
44
47
  create_table :songs do |table|
45
48
  table.column :title, :string
46
49
  table.column :artist_id, :integer
47
50
  table.column :album_id, :integer
48
- table.timestamps
51
+ table.timestamps null: false
49
52
  end
50
53
  create_table :albums do |table|
51
54
  table.column :name, :string
52
55
  table.column :artist_id, :integer
53
- table.timestamps
56
+ table.timestamps null: false
54
57
  end
55
58
  end
56
59
 
@@ -71,7 +74,7 @@ module Disposable
71
74
  end
72
75
 
73
76
  def saved?
74
- @saved
77
+ defined?(@saved) ? @saved : nil
75
78
  end
76
79
  end
77
80
  end
@@ -114,7 +114,7 @@ class ChangedWithCoercionTest < MiniTest::Spec
114
114
  include Changed
115
115
  include Coercion
116
116
 
117
- property :released, type: Types::Form::Bool
117
+ property :released, type: DRY_TYPES_CONSTANT::Bool
118
118
  end
119
119
 
120
120
  it do
@@ -3,16 +3,15 @@ require "test_helper"
3
3
  require "disposable/twin/coercion"
4
4
 
5
5
  class CoercionTest < MiniTest::Spec
6
-
7
6
  class TwinWithSkipSetter < Disposable::Twin
8
7
  feature Coercion
9
8
  feature Setup::SkipSetter
10
9
 
11
10
  property :id
12
- property :released_at, type: Types::Form::DateTime
11
+ property :released_at, type: DRY_TYPES_CONSTANT::DateTime
13
12
 
14
13
  property :hit do
15
- property :length, type: Types::Coercible::Int
14
+ property :length, type: const_get("Types::Coercible::#{DRY_TYPES_INT_CONSTANT}")
16
15
  property :good, type: Types::Bool
17
16
  end
18
17
 
@@ -24,7 +23,6 @@ class CoercionTest < MiniTest::Spec
24
23
  end
25
24
 
26
25
  describe "with Setup::SkipSetter" do
27
-
28
26
  subject do
29
27
  TwinWithSkipSetter.new(album)
30
28
  end
@@ -54,14 +52,14 @@ class CoercionTest < MiniTest::Spec
54
52
  subject.released_at.must_be_kind_of DateTime
55
53
  subject.released_at.must_equal DateTime.parse("30/03/1981")
56
54
  subject.hit.length.must_equal 312
57
- subject.hit.good.must_equal nil
55
+ subject.hit.good.must_be_nil
58
56
  subject.band.label.value.must_equal 9999.99
59
57
  end
60
58
  end
61
59
 
62
60
  class TwinWithoutSkipSetter < Disposable::Twin
63
61
  feature Coercion
64
- property :id, type: Types::Coercible::Int
62
+ property :id, type: const_get("Types::Coercible::#{DRY_TYPES_INT_CONSTANT}")
65
63
  end
66
64
 
67
65
  describe "without Setup::SkipSetter" do
@@ -81,9 +79,9 @@ class CoercionTest < MiniTest::Spec
81
79
  feature Coercion
82
80
 
83
81
  property :date_of_birth,
84
- type: Types::Form::Date, nilify: true
82
+ type: DRY_TYPES_CONSTANT::Date, nilify: true
85
83
  property :date_of_death_by_unicorns,
86
- type: Types::Form::Nil | Types::Form::Date
84
+ type: DRY_TYPES_CONSTANT::Nil | DRY_TYPES_CONSTANT::Date
87
85
  property :id, nilify: true
88
86
  end
89
87
 
@@ -102,33 +100,33 @@ class CoercionTest < MiniTest::Spec
102
100
 
103
101
  it "coerce empty values to nil when using option nilify: true" do
104
102
  subject.date_of_birth = ""
105
- subject.date_of_birth.must_equal nil
103
+ subject.date_of_birth.must_be_nil
106
104
  end
107
105
 
108
106
  it "coerce empty values to nil when using dry-types | operator" do
109
107
  subject.date_of_death_by_unicorns = ""
110
- subject.date_of_death_by_unicorns.must_equal nil
108
+ subject.date_of_death_by_unicorns.must_be_nil
111
109
  end
112
110
 
113
111
  it "converts blank string to nil, without :type option" do
114
112
  subject.id = ""
115
- subject.id.must_equal nil
113
+ subject.id.must_be_nil
116
114
  end
117
115
  end
118
116
  end
119
117
 
120
118
  # this converts "" to nil and then breaks because it's strict.
121
- # Types::Strict::String.constructor(Dry::Types::Coercions::Form.method(:to_nil))
119
+ # Types::Strict::String.constructor(Dry::Types::Params.method(:to_nil))
122
120
 
123
121
  class CoercionTypingTest < MiniTest::Spec
124
122
  class Song < Disposable::Twin
125
123
  include Coercion
126
124
  include Setup::SkipSetter
127
125
 
128
- # property :title, type: Dry::Types::Strict::String.constructor(Dry::Types::Coercions::Form.method(:to_nil))
126
+ # property :title, type: Dry::Types::Strict::String.constructor(Dry::Types::Params.method(:to_nil))
129
127
  property :title, type: Types::Strict::String.optional # this is the behavior of the "DB" data twin. this is NOT the form.
130
128
 
131
- # property :name, type: Types::Form::String
129
+ # property :name, type: Types::Params::String
132
130
  end
133
131
 
134
132
  it do
@@ -155,12 +153,14 @@ class CoercionTypingTest < MiniTest::Spec
155
153
  include Setup::SkipSetter
156
154
 
157
155
 
158
- # property :title, type: Dry::Types::Strict::String.constructor(Dry::Types::Coercions::Form.method(:to_nil))
159
- property :title, type: Types::Strict::String.optional.constructor(Dry::Types::Coercions::Form.method(:to_nil)) # this is the behavior of the "DB" data twin. this is NOT the form.
156
+ # property :title, type: Dry::Types::Strict::String.constructor(Dry::Types::Params.method(:to_nil))
157
+
158
+ constructor = Disposable::Twin::Coercion::DRY_TYPES_VERSION < 13 ? 'form.nil' : 'params.nil'
159
+ property :title, type: Types::Strict::String.optional.constructor(Dry::Types[constructor]) # this is the behavior of the "DB" data twin. this is NOT the form.
160
160
 
161
- # property :name, type: Types::Form::String
161
+ # property :name, type: Types::Params::String
162
162
 
163
- property :enabled, type: Types::Form::Bool
163
+ property :enabled, type: DRY_TYPES_CONSTANT::Bool
164
164
  # property :enabled, Bool.constructor(:trim!)
165
165
  end
166
166
  it do
@@ -44,7 +44,7 @@ class TwinCollectionTest < MiniTest::Spec
44
44
  let (:album) { Model::Album.new(1, "The Rest Is Silence", [Model::Song.new(3), Model::Song.new(4)]) }
45
45
  let (:twin) { Twin::Album.new(album) }
46
46
 
47
- it { twin.songs.find_by(id: 1).must_equal nil }
47
+ it { twin.songs.find_by(id: 1).must_be_nil }
48
48
  it { twin.songs.find_by(id: 3).must_equal twin.songs[0] }
49
49
  it { twin.songs.find_by(id: 4).must_equal twin.songs[1] }
50
50
  it { twin.songs.find_by(id: "4").must_equal twin.songs[1] }
@@ -172,7 +172,7 @@ class TwinCollectionActiveRecordTest < MiniTest::Spec
172
172
  twin.songs.added.must_equal []
173
173
  twin.songs << song2
174
174
  twin.songs.added.must_equal [twin.songs[1]]
175
- twin.songs.insert(2, song3 = Song.new)
175
+ twin.songs.insert(2, Song.new)
176
176
  twin.songs.added.must_equal [twin.songs[1], twin.songs[2]]
177
177
 
178
178
  # TODO: what to do if we override an item (insert)?
@@ -180,7 +180,7 @@ class TwinCollectionActiveRecordTest < MiniTest::Spec
180
180
  end
181
181
 
182
182
  describe "#deleted" do
183
- let (:album) { Album.create(name: "The Rest Is Silence", songs: [song1, song2, song3 = Song.new]) }
183
+ let (:album) { Album.create(name: "The Rest Is Silence", songs: [song1, song2, Song.new]) }
184
184
 
185
185
  it do
186
186
  twin = Twin::Album.new(album)
@@ -33,9 +33,9 @@ class HashTest < MiniTest::Spec
33
33
 
34
34
  song = Song.new(model)
35
35
  song.id.must_equal 1
36
- song.content.title.must_equal nil
37
- song.content.band.name.must_equal nil
38
- song.content.band.label.location.must_equal nil
36
+ song.content.title.must_be_nil
37
+ song.content.band.name.must_be_nil
38
+ song.content.band.label.location.must_be_nil
39
39
  song.content.releases.must_equal []
40
40
 
41
41
  # model's hash hasn't changed.
@@ -48,9 +48,9 @@ class HashTest < MiniTest::Spec
48
48
 
49
49
  song = Song.new(model)
50
50
  song.id.must_equal 1
51
- song.content.title.must_equal nil
52
- song.content.band.name.must_equal nil
53
- song.content.band.label.location.must_equal nil
51
+ song.content.title.must_be_nil
52
+ song.content.band.name.must_be_nil
53
+ song.content.band.label.location.must_be_nil
54
54
 
55
55
  # model's hash hasn't changed.
56
56
  model.inspect.must_equal "#<struct HashTest::Model id=1, content=nil>"
@@ -137,7 +137,7 @@ class HashTest < MiniTest::Spec
137
137
  include Property::Hash
138
138
  feature Coercion
139
139
 
140
- property :id, type: Types::Coercible::Int
140
+ property :id, type: const_get("Types::Coercible::#{DRY_TYPES_INT_CONSTANT}")
141
141
  property :content, field: :hash do
142
142
  property :title
143
143
  property :band do
@@ -161,7 +161,7 @@ class HashTest < MiniTest::Spec
161
161
  include Property::Hash
162
162
 
163
163
  property :id
164
- content=property :content, field: :hash do
164
+ property :content, field: :hash do
165
165
  property :title
166
166
  property :band do
167
167
  property :name
@@ -198,12 +198,59 @@ class HashTest < MiniTest::Spec
198
198
  song.content.title.must_equal "Notorious"
199
199
 
200
200
  # singular nested accessors
201
- song.band.name.must_equal nil
202
- song.content.band.name.must_equal nil
201
+ song.band.name.must_be_nil
202
+ song.content.band.name.must_be_nil
203
203
  song.band.name = "Duran Duran"
204
204
  song.band.name.must_equal "Duran Duran"
205
205
  end
206
206
  end
207
+
208
+ describe 'collection schema' do
209
+ AlbumModel = Struct.new(:id, :songs)
210
+ class Album < Disposable::Twin
211
+ feature Sync
212
+ feature Property::Hash
213
+
214
+ property :id
215
+ collection :songs, field: :hash do
216
+ property :title
217
+ property :band do
218
+ property :name
219
+
220
+ property :label do
221
+ property :location
222
+ end
223
+ end
224
+
225
+ collection :featured_artists do
226
+ property :name
227
+ end
228
+ end
229
+ end
230
+
231
+ it "exposes reader and writer" do
232
+ model = AlbumModel.new(1, [
233
+ { title: "Sherry", band: { name: 'The Four Seasons', label: { location: 'US' } }, featured_artists: [{ name: 'Frankie Valli' }, { name: 'The Variatones' }] },
234
+ { title: "Walk Like a Man", band: { name: 'The Four Seasons', label: { location: 'US' } }, featured_artists: [{ name: 'Frankie Valli' }] }
235
+ ])
236
+ contract = Album.new(model)
237
+
238
+ song1 = contract.songs[0]
239
+
240
+ song1.title.must_equal "Sherry"
241
+ song1.band.name.must_equal 'The Four Seasons'
242
+ song1.band.label.location.must_equal 'US'
243
+ song1.featured_artists[0].name.must_equal 'Frankie Valli'
244
+ song1.featured_artists[1].name.must_equal 'The Variatones'
245
+
246
+ song2 = contract.songs[1]
247
+
248
+ song2.title.must_equal "Walk Like a Man"
249
+ song2.band.name.must_equal 'The Four Seasons'
250
+ song2.band.label.location.must_equal 'US'
251
+ song2.featured_artists[0].name.must_equal 'Frankie Valli'
252
+ end
253
+ end
207
254
  end
208
255
 
209
256
  # fixme: make sure default hash is different for every invocation, and not created at compile time.
@@ -28,7 +28,7 @@
28
28
  # # option is not delegated to model.
29
29
  # it { twin.preview?.must_equal false }
30
30
  # # not passing option means zero.
31
- # it { twin.current_user.must_equal nil }
31
+ # it { twin.current_user.must_be_nil }
32
32
 
33
33
  # describe "passing all options" do
34
34
  # let (:twin) { Song.new(song, :preview? => false, current_user: Object) }
@@ -27,14 +27,14 @@ class TwinParentTest < MiniTest::Spec
27
27
 
28
28
  let (:album) { Album.new(Model::Album.new(1, Model::Artist.new("Helloween"), [Model::Song.new("I'm Alive", Model::Artist.new("Kai Hansen"))])) }
29
29
 
30
- it { album.parent.must_equal nil }
30
+ it { album.parent.must_be_nil }
31
31
  it { album.artist.parent.must_equal album }
32
32
  it { album.songs[0].parent.must_equal album }
33
33
  it { album.songs[0].composer.parent.must_equal album.songs[0] }
34
34
 
35
35
  describe "Collection#append" do
36
36
  it do
37
- album.songs.append(song = Model::Song.new)
37
+ album.songs.append(Model::Song.new)
38
38
  album.songs[1].parent.must_equal album
39
39
  end
40
40
  end
@@ -5,7 +5,7 @@ class PropertyProcessorTest < Minitest::Spec
5
5
  Artist = Struct.new(:name)
6
6
  Song = Struct.new(:id)
7
7
 
8
- class AlbumTwin < Disposable::Twin
8
+ class AlbumTwin < Disposable::Twin
9
9
  property :title
10
10
 
11
11
  property :artist do
@@ -35,7 +35,7 @@ class PropertyProcessorTest < Minitest::Spec
35
35
 
36
36
  it "allows nil collection" do
37
37
  twin = AlbumTwin.new(Album.new("Live!", Artist.new, nil))
38
-
38
+
39
39
  called = []
40
40
  Disposable::Twin::PropertyProcessor.new(twin.class.definitions.get(:songs), twin).() { |v, i| called << [v.model, i] }
41
41
 
@@ -30,9 +30,9 @@ class ReadableTest < MiniTest::Spec
30
30
  let (:twin) { PasswordForm.new(cred) }
31
31
 
32
32
  it {
33
- twin.password.must_equal nil # not readable.
33
+ twin.password.must_be_nil # not readable.
34
34
  twin.credit_card.name.must_equal "Jonny"
35
- twin.credit_card.number.must_equal nil # not readable.
35
+ twin.credit_card.number.must_be_nil # not readable.
36
36
 
37
37
  # manual setting on the twin works.
38
38
  twin.password = "123"
@@ -88,19 +88,19 @@ class SaveTest < MiniTest::Spec
88
88
  nested_hash.must_equal({"name"=>"Live And Dangerous", "songs"=>[{"title"=>"Southbound", "composer"=>nil}, {"title"=>"The Boys Are Back In Town", "composer"=>{"name"=>"Lynott"}}], "artist"=>{"name"=>"Thin Lizzy"}})
89
89
 
90
90
  # nothing written to model.
91
- album.name.must_equal nil
92
- album.songs[0].title.must_equal nil
93
- album.songs[1].title.must_equal nil
94
- album.songs[1].composer.name.must_equal nil
95
- album.artist.name.must_equal nil
91
+ album.name.must_be_nil
92
+ album.songs[0].title.must_be_nil
93
+ album.songs[1].title.must_be_nil
94
+ album.songs[1].composer.name.must_be_nil
95
+ album.artist.name.must_be_nil
96
96
 
97
97
  # nothing saved.
98
98
  # saved?
99
- album.saved?.must_equal nil
100
- album.songs[0].saved?.must_equal nil
101
- album.songs[1].saved?.must_equal nil
102
- album.songs[1].composer.saved?.must_equal nil
103
- album.artist.saved?.must_equal nil
99
+ album.saved?.must_be_nil
100
+ album.songs[0].saved?.must_be_nil
101
+ album.songs[1].saved?.must_be_nil
102
+ album.songs[1].composer.saved?.must_be_nil
103
+ album.artist.saved?.must_be_nil
104
104
  end
105
105
 
106
106
 
@@ -148,9 +148,9 @@ class SaveTest < MiniTest::Spec
148
148
 
149
149
  # saved?
150
150
  album.saved?.must_equal true
151
- album.songs[0].saved?.must_equal nil
152
- album.songs[1].saved?.must_equal nil
153
- album.songs[1].composer.saved?.must_equal nil # doesn't get saved.
151
+ album.songs[0].saved?.must_be_nil
152
+ album.songs[1].saved?.must_be_nil
153
+ album.songs[1].composer.saved?.must_be_nil # doesn't get saved.
154
154
  album.artist.saved?.must_equal true
155
155
  end
156
156
 
@@ -186,7 +186,7 @@ end
186
186
  # form.save(length: lambda { |value, options| form.model.id = "#{value}: #{length_seconds}" })
187
187
 
188
188
  # song.title.must_equal "A Poor Man's Memory"
189
- # song.length.must_equal nil
189
+ # song.length.must_be_nil
190
190
  # song.id.must_equal "10: 120"
191
191
  # end
192
192
  # end
@@ -0,0 +1,36 @@
1
+ require "test_helper"
2
+ require "disposable/twin/coercion"
3
+ require "disposable/twin/property/struct"
4
+
5
+ class StructCoercionTest < Minitest::Spec
6
+ ExpenseModel = Struct.new(:content)
7
+
8
+ class Expense < Disposable::Twin
9
+ feature Property::Struct
10
+ feature Coercion
11
+
12
+ property :content do
13
+ property :amount, type: DRY_TYPES_CONSTANT::Float
14
+ end
15
+
16
+ unnest :amount, from: :content
17
+ end
18
+
19
+
20
+ it do
21
+ twin = Expense.new( ExpenseModel.new({}) )
22
+
23
+ #- direct access, without unnest
24
+ twin.content.amount.must_be_nil
25
+ twin.content.amount = "1.8"
26
+ twin.content.amount.must_equal 1.8
27
+ end
28
+
29
+ it "via unnest" do
30
+ twin = Expense.new( ExpenseModel.new({}) )
31
+
32
+ twin.amount.must_be_nil
33
+ twin.amount = "1.8"
34
+ twin.amount.must_equal 1.8
35
+ end
36
+ end
@@ -12,7 +12,7 @@ class TwinStructTest < MiniTest::Spec
12
12
 
13
13
  # empty hash
14
14
  # it { Song.new({}).number.must_equal 1 }
15
- it { Song.new({}).number.must_equal nil } # TODO: implement default.
15
+ it { Song.new({}).number.must_be_nil } # TODO: implement default.
16
16
 
17
17
  # model hash
18
18
  it { Song.new(number: 2).number.must_equal 2 }
@@ -179,7 +179,7 @@ class StructReadableWriteableTest < Minitest::Spec
179
179
  it "ignores readable: false" do
180
180
  song = Song.new(length: 123, id: 1)
181
181
  song.length.must_equal 123
182
- song.id.must_equal nil
182
+ song.id.must_be_nil
183
183
  end
184
184
 
185
185
  it "ignores writeable: false" do
@@ -58,7 +58,7 @@
58
58
  # # Album#name :sync was called, first case.
59
59
  # album.name.must_equal "processed+Run For Cover"
60
60
  # # Song#title :sync called but returns nil.
61
- # song.title.must_equal nil
61
+ # song.title.must_be_nil
62
62
  # # Song#title :sync called and processed, first case.
63
63
  # song_with_composer.title.must_equal "++Empty Rooms"
64
64
 
@@ -139,7 +139,7 @@
139
139
  # # Album#name :sync was called, first case.
140
140
  # album.name.must_equal "processed+Run For Cover"
141
141
  # # Song#title :sync called but returns nil.
142
- # song.title.must_equal nil
142
+ # song.title.must_be_nil
143
143
  # # Song#title :sync called and processed, first case.
144
144
  # #### song_with_composer.title.must_equal "++Empty Rooms"
145
145
 
@@ -47,11 +47,11 @@ class TwinSyncTest < MiniTest::Spec
47
47
  fill_out!(twin)
48
48
 
49
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
50
+ album.name.must_be_nil
51
+ album.songs[0].title.must_be_nil
52
+ album.songs[1].title.must_be_nil
53
+ album.songs[1].composer.name.must_be_nil
54
+ album.artist.name.must_be_nil
55
55
 
56
56
  twin.sync
57
57
 
@@ -82,9 +82,9 @@ class TwinSyncTest < MiniTest::Spec
82
82
  twin.songs[1].composer.name = "Lynott"
83
83
 
84
84
  # not written to model, yet.
85
- album.name.must_equal nil
85
+ album.name.must_be_nil
86
86
  album.songs.must_equal []
87
- album.artist.must_equal nil
87
+ album.artist.must_be_nil
88
88
 
89
89
  twin.sync # this assigns a new collection via #songs=.
90
90
 
@@ -110,11 +110,11 @@ class TwinSyncTest < MiniTest::Spec
110
110
  nested_hash.must_equal({"name"=>"Live And Dangerous", "songs"=>[{"title"=>"Southbound", "composer"=>nil}, {"title"=>"The Boys Are Back In Town", "composer"=>{"name"=>"Lynott"}}], "artist"=>{"name"=>"Thin Lizzy"}})
111
111
 
112
112
  # nothing written to model.
113
- album.name.must_equal nil
114
- album.songs[0].title.must_equal nil
115
- album.songs[1].title.must_equal nil
116
- album.songs[1].composer.name.must_equal nil
117
- album.artist.name.must_equal nil
113
+ album.name.must_be_nil
114
+ album.songs[0].title.must_be_nil
115
+ album.songs[1].title.must_be_nil
116
+ album.songs[1].composer.name.must_be_nil
117
+ album.artist.name.must_be_nil
118
118
  end
119
119
 
120
120
  describe "nil values" do
@@ -75,12 +75,12 @@ class TwinTest < MiniTest::Spec
75
75
 
76
76
  describe "deleting" do
77
77
  it "allows overwriting nested twin with nil" do
78
- album = Model::Album.new(1, "Uncertain Terms", [], artist=Model::Artist.new("Greg Howe"))
78
+ album = Model::Album.new(1, "Uncertain Terms", [], Model::Artist.new("Greg Howe"))
79
79
  twin = Twin::Album.new(album)
80
80
  twin.artist.id.must_equal "Greg Howe"
81
81
 
82
82
  twin.artist = nil
83
- twin.artist.must_equal nil
83
+ twin.artist.must_be_nil
84
84
  end
85
85
  end
86
86
 
@@ -25,12 +25,12 @@ class UnnestTest < MiniTest::Spec
25
25
  it "exposes accessors on top-level twin" do
26
26
  twin = Twin.new(OpenStruct.new(content: OpenStruct.new()))
27
27
 
28
- twin.email.must_equal nil
28
+ twin.email.must_be_nil
29
29
  twin.email= 2
30
30
  twin.email.model.must_equal 2
31
31
 
32
32
 
33
- twin.id.must_equal nil
33
+ twin.id.must_be_nil
34
34
  twin.id = 1
35
35
  twin.id.must_equal 1
36
36
  end
@@ -33,7 +33,7 @@ class VirtualTest < MiniTest::Spec
33
33
  end
34
34
 
35
35
  it "what" do
36
- Raising.new(Object.new).id.must_equal nil
36
+ Raising.new(Object.new).id.must_be_nil
37
37
  end
38
38
  end
39
39
  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.4.3
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-10 00:00:00.000000000 Z
11
+ date: 2018-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uber
@@ -138,16 +138,16 @@ dependencies:
138
138
  name: activerecord
139
139
  requirement: !ruby/object:Gem::Requirement
140
140
  requirements:
141
- - - '='
141
+ - - ">="
142
142
  - !ruby/object:Gem::Version
143
- version: 4.2.5
143
+ version: '0'
144
144
  type: :development
145
145
  prerelease: false
146
146
  version_requirements: !ruby/object:Gem::Requirement
147
147
  requirements:
148
- - - '='
148
+ - - ">="
149
149
  - !ruby/object:Gem::Version
150
- version: 4.2.5
150
+ version: '0'
151
151
  - !ruby/object:Gem::Dependency
152
152
  name: sqlite3
153
153
  requirement: !ruby/object:Gem::Requirement
@@ -166,16 +166,16 @@ dependencies:
166
166
  name: dry-types
167
167
  requirement: !ruby/object:Gem::Requirement
168
168
  requirements:
169
- - - "~>"
169
+ - - ">="
170
170
  - !ruby/object:Gem::Version
171
- version: '0.6'
171
+ version: '0'
172
172
  type: :development
173
173
  prerelease: false
174
174
  version_requirements: !ruby/object:Gem::Requirement
175
175
  requirements:
176
- - - "~>"
176
+ - - ">="
177
177
  - !ruby/object:Gem::Version
178
- version: '0.6'
178
+ version: '0'
179
179
  description: Decorators on top of your ORM layer.
180
180
  email:
181
181
  - apotonick@gmail.com
@@ -251,6 +251,7 @@ files:
251
251
  - test/twin/save_test.rb
252
252
  - test/twin/setup_test.rb
253
253
  - test/twin/skip_unchanged_test.rb
254
+ - test/twin/struct/coercion_test.rb
254
255
  - test/twin/struct_test.rb
255
256
  - test/twin/sync_option_test.rb
256
257
  - test/twin/sync_test.rb
@@ -278,7 +279,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
278
279
  version: '0'
279
280
  requirements: []
280
281
  rubyforge_project:
281
- rubygems_version: 2.5.2
282
+ rubygems_version: 2.6.14
282
283
  signing_key:
283
284
  specification_version: 4
284
285
  summary: Decorators on top of your ORM layer with change tracking, collection semantics
@@ -315,6 +316,7 @@ test_files:
315
316
  - test/twin/save_test.rb
316
317
  - test/twin/setup_test.rb
317
318
  - test/twin/skip_unchanged_test.rb
319
+ - test/twin/struct/coercion_test.rb
318
320
  - test/twin/struct_test.rb
319
321
  - test/twin/sync_option_test.rb
320
322
  - test/twin/sync_test.rb