disposable 0.4.3 → 0.4.4

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.
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