disposable 0.6.3 → 0.7.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +29 -20
- data/CHANGES.md +5 -0
- data/Gemfile +8 -4
- data/disposable.gemspec +1 -0
- data/lib/disposable/twin/sync.rb +3 -2
- data/lib/disposable/version.rb +1 -1
- data/test/api_semantics_test.rb +4 -4
- data/test/callback_group_test.rb +5 -5
- data/test/callbacks_test.rb +1 -1
- data/test/expose_test.rb +2 -2
- data/test/persisted_test.rb +1 -1
- data/test/rescheme_test.rb +17 -17
- data/test/skip_getter_test.rb +3 -3
- data/test/test_helper.rb +1 -1
- data/test/twin/benchmarking.rb +0 -1
- data/test/twin/builder_test.rb +1 -1
- data/test/twin/changed_test.rb +2 -2
- data/test/twin/coercion_test.rb +16 -10
- data/test/twin/collection_test.rb +5 -4
- data/test/twin/composition_test.rb +1 -1
- data/test/twin/expose_test.rb +1 -1
- data/test/twin/feature_test.rb +1 -1
- data/test/twin/from_collection_test.rb +1 -1
- data/test/twin/from_test.rb +1 -1
- data/test/twin/hash_test.rb +5 -5
- data/test/twin/inherit_test.rb +3 -3
- data/test/twin/inheritance_test.rb +1 -1
- data/test/twin/parent_test.rb +1 -1
- data/test/twin/process_inline_test.rb +1 -1
- data/test/twin/readable_test.rb +1 -1
- data/test/twin/save_test.rb +2 -2
- data/test/twin/setup_test.rb +3 -3
- data/test/twin/skip_unchanged_test.rb +1 -1
- data/test/twin/struct_test.rb +10 -4
- data/test/twin/sync_option_test.rb +4 -4
- data/test/twin/sync_test.rb +1 -1
- data/test/twin/twin_test.rb +2 -2
- data/test/twin/unnest_test.rb +8 -5
- data/test/twin/virtual_test.rb +1 -1
- data/test/twin/writeable_test.rb +1 -1
- metadata +5 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d646a66e2becc4ba68e55b942aafae4f91027b8d82469d56f23acba252a0951a
|
|
4
|
+
data.tar.gz: 29470df5d8c11e29b0b9659c14b07a527a3f59c08fdeb6210e4a792551d62aaf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eadc7b6ac6dc8c9db6bb731ab0f612d3e4a23e624c8839b3369e80371776d563e5b7d110adf215c2e2b5469cf603e4e38ef6266a401eea65dbf9ea400ef90956
|
|
7
|
+
data.tar.gz: 90979ea1e087ba34aa42f8136d2e2c4569fda867ba5c22c563df1d2b26c66675e191bba4792eba3c41a1e2eb5aaa2abe0a9cf2b113802106a5d650f1ea953ba7
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
name: CI
|
|
2
2
|
on: [push, pull_request]
|
|
3
|
+
|
|
3
4
|
jobs:
|
|
4
5
|
test:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
5
7
|
strategy:
|
|
6
8
|
fail-fast: false
|
|
7
9
|
matrix:
|
|
8
|
-
ruby: [2.6]
|
|
9
|
-
active_record: [5.2, 6.0]
|
|
10
|
-
dry_types: [1.0, 1.2]
|
|
11
|
-
|
|
12
10
|
include:
|
|
13
|
-
- ruby:
|
|
14
|
-
active_record:
|
|
15
|
-
dry_types: 1.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
- ruby: '3.3'
|
|
12
|
+
active_record: '8.0'
|
|
13
|
+
dry_types: '1.6'
|
|
14
|
+
- ruby: '3.3'
|
|
15
|
+
active_record: '8.1'
|
|
16
|
+
dry_types: '1.6'
|
|
17
|
+
- ruby: '3.4'
|
|
18
|
+
active_record: '8.0'
|
|
19
|
+
dry_types: '1.6'
|
|
20
|
+
- ruby: '3.4'
|
|
21
|
+
active_record: '8.1'
|
|
22
|
+
dry_types: '1.6'
|
|
23
|
+
- ruby: '4.0'
|
|
24
|
+
active_record: '8.0'
|
|
25
|
+
dry_types: '1.6'
|
|
26
|
+
- ruby: '4.0'
|
|
27
|
+
active_record: '8.1'
|
|
28
|
+
dry_types: '1.6'
|
|
29
|
+
env:
|
|
30
|
+
ACTIVERECORD: ${{ matrix.active_record }}
|
|
31
|
+
DRY_TYPES: ${{ matrix.dry_types }}
|
|
22
32
|
steps:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- run: ACTIVERECORD=${{ matrix.active_record}} DRY_TYPES=${{ matrix.dry_types }} bundle exec rake
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
|
+
- uses: ruby/setup-ruby@v1
|
|
35
|
+
with:
|
|
36
|
+
ruby-version: ${{ matrix.ruby }}
|
|
37
|
+
- run: bundle install
|
|
38
|
+
- run: bundle exec rake
|
data/CHANGES.md
CHANGED
data/Gemfile
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
source "https://rubygems.org"
|
|
2
2
|
gemspec
|
|
3
3
|
gem "minitest-line"
|
|
4
|
+
gem "trailblazer-core-utils"
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
gem gem_name, dependency
|
|
6
|
+
if ENV['DRY_TYPES']
|
|
7
|
+
gem "dry-types", ENV['DRY_TYPES']
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
if ENV['ACTIVERECORD']
|
|
11
|
+
gem "activerecord", "~> #{ENV['ACTIVERECORD']}.0"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
gem "sqlite3", "~> 2.1"
|
|
11
15
|
|
|
12
16
|
# gem "declarative-builder"
|
data/disposable.gemspec
CHANGED
|
@@ -11,6 +11,7 @@ Gem::Specification.new do |spec|
|
|
|
11
11
|
spec.summary = %q{Decorators on top of your ORM layer with change tracking, collection semantics and nesting.}
|
|
12
12
|
spec.homepage = "https://github.com/apotonick/disposable"
|
|
13
13
|
spec.license = "MIT"
|
|
14
|
+
spec.required_ruby_version = ">= 3.3.0"
|
|
14
15
|
|
|
15
16
|
spec.files = `git ls-files`.split($/)
|
|
16
17
|
spec.test_files = spec.files.grep(%r{^(test)/})
|
data/lib/disposable/twin/sync.rb
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# 2. call sync! on nested
|
|
4
4
|
#
|
|
5
5
|
# Note: #sync currently implicitly saves AR objects with collections
|
|
6
|
-
require 'ostruct'
|
|
7
6
|
class Disposable::Twin
|
|
8
7
|
module Sync
|
|
9
8
|
class Options < ::Hash
|
|
@@ -155,7 +154,9 @@ class Disposable::Twin
|
|
|
155
154
|
end
|
|
156
155
|
|
|
157
156
|
def nested_hash_source
|
|
158
|
-
|
|
157
|
+
names = schema.each.collect { |dfn| dfn[:name] }
|
|
158
|
+
|
|
159
|
+
Data.define(*names.map(&:to_sym)).new(*names.collect { |name| @fields[name] })
|
|
159
160
|
end
|
|
160
161
|
end
|
|
161
162
|
end
|
data/lib/disposable/version.rb
CHANGED
data/test/api_semantics_test.rb
CHANGED
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
|
|
139
|
-
# class ApiSemanticsTest <
|
|
139
|
+
# class ApiSemanticsTest < Minitest::Spec
|
|
140
140
|
# it "xxx" do
|
|
141
141
|
# album = Model::Album.new(1, "And So I Watch You From Afar", [Model::Song.new(2, "Solidarity"), Model::Song.new(0, "Tale That Wasn't Right")])
|
|
142
142
|
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
|
|
154
154
|
# end
|
|
155
155
|
|
|
156
|
-
# class RemoveFlagSetButNotEnabled <
|
|
156
|
+
# class RemoveFlagSetButNotEnabled < Minitest::Spec
|
|
157
157
|
# class AlbumDecorator < Representable::Decorator
|
|
158
158
|
# include Representable::Hash
|
|
159
159
|
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
# end
|
|
184
184
|
# end
|
|
185
185
|
|
|
186
|
-
# class UserCallableTest <
|
|
186
|
+
# class UserCallableTest < Minitest::Spec
|
|
187
187
|
# class MyOwnSemantic < Representable::Semantics::Semantic
|
|
188
188
|
# def self.call(model, fragment, index, options)
|
|
189
189
|
# if fragment["title"] =~ /Solidarity/
|
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
# end
|
|
221
221
|
|
|
222
222
|
|
|
223
|
-
# class ApiSemanticsWithUpdate <
|
|
223
|
+
# class ApiSemanticsWithUpdate < Minitest::Spec
|
|
224
224
|
# class AlbumDecorator < Representable::Decorator
|
|
225
225
|
# include Representable::Hash
|
|
226
226
|
|
data/test/callback_group_test.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
require "disposable/callback"
|
|
3
3
|
|
|
4
|
-
class CallbackGroupTest <
|
|
4
|
+
class CallbackGroupTest < Minitest::Spec
|
|
5
5
|
class Group < Disposable::Callback::Group
|
|
6
6
|
attr_reader :output
|
|
7
7
|
|
|
@@ -143,7 +143,7 @@ class CallbackGroupTest < MiniTest::Spec
|
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
|
|
146
|
-
class CallbackGroupInheritanceTest <
|
|
146
|
+
class CallbackGroupInheritanceTest < Minitest::Spec
|
|
147
147
|
class Group < Disposable::Callback::Group
|
|
148
148
|
on_change :change!
|
|
149
149
|
collection :songs do
|
|
@@ -158,11 +158,11 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
|
|
|
158
158
|
|
|
159
159
|
it do
|
|
160
160
|
expect(Group.hooks.size).must_equal 4
|
|
161
|
-
|
|
161
|
+
assert_equal "[:on_change, :change!, {}]", Trailblazer::Core::Utils.inspect(Group.hooks[0].to_s)
|
|
162
162
|
# Group.hooks[1][1][:nested].hooks.to_s.must_equal "[[:on_add, [:notify_album!]],[:on_add, [:reset_song!]]]"
|
|
163
|
-
|
|
163
|
+
assert_equal "[:on_change, :rehash_name!, {:property=>:title}]", Trailblazer::Core::Utils.inspect(Group.hooks[2].to_s)
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
assert_equal "[[:on_change, :sing!, {}]]", Trailblazer::Core::Utils.inspect(Group.definitions.get(Group.hooks[3][1])[:nested].hooks.to_s)
|
|
166
166
|
end
|
|
167
167
|
|
|
168
168
|
class EmptyGroup < Group
|
data/test/callbacks_test.rb
CHANGED
data/test/expose_test.rb
CHANGED
|
@@ -3,7 +3,7 @@ require "disposable/expose"
|
|
|
3
3
|
require "disposable/composition"
|
|
4
4
|
|
|
5
5
|
# Disposable::Expose.
|
|
6
|
-
class ExposeTest <
|
|
6
|
+
class ExposeTest < Minitest::Spec
|
|
7
7
|
module Model
|
|
8
8
|
Album = Struct.new(:id, :name)
|
|
9
9
|
end
|
|
@@ -45,7 +45,7 @@ end
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
# Disposable::Composition.
|
|
48
|
-
class ExposeCompositionTest <
|
|
48
|
+
class ExposeCompositionTest < Minitest::Spec
|
|
49
49
|
module Model
|
|
50
50
|
Band = Struct.new(:id)
|
|
51
51
|
Album = Struct.new(:id, :name)
|
data/test/persisted_test.rb
CHANGED
data/test/rescheme_test.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
|
|
3
|
-
class ReschemeTest <
|
|
3
|
+
class ReschemeTest < Minitest::Spec
|
|
4
4
|
module Representer
|
|
5
5
|
include Representable
|
|
6
6
|
|
|
@@ -40,19 +40,19 @@ class ReschemeTest < MiniTest::Spec
|
|
|
40
40
|
expect(decorator.new(nil).hello).must_equal "hello"
|
|
41
41
|
expect(decorator.new(nil).ciao).must_equal "ciao"
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
assert_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:id).inspect)
|
|
44
|
+
assert_equal "#<Representable::Definition ==>title @options={:writeable=>false, :deserializer=>{:skip_parse=>\"skip lambda\"}, :name=>\"title\", :parse_filter=>[], :render_filter=>[], :skip_parse=>\"skip lambda\"}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:title).inspect)
|
|
45
45
|
|
|
46
46
|
songs = decorator.representable_attrs.get(:songs)
|
|
47
47
|
options = songs.instance_variable_get(:@options)
|
|
48
48
|
options[:nested].extend(Declarative::Inspect)
|
|
49
|
-
|
|
49
|
+
assert_equal "{:readable=>false, :deserializer=>{:skip_parse=>\"another lambda\", :music=>true, :writeable=>false}, :nested=>#<Class:>, :extend=>#<Class:>, :name=>\"songs\", :parse_filter=>[], :render_filter=>[], :skip_parse=>\"another lambda\", :music=>true, :writeable=>false}", Trailblazer::Core::Utils.inspect(options)
|
|
50
50
|
|
|
51
51
|
# nested works.
|
|
52
52
|
expect(options[:nested].new(nil).hello).must_equal "hello"
|
|
53
53
|
expect(options[:nested].new(nil).ciao).must_equal "ciao"
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
assert_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :name=>\"name\", :parse_filter=>[], :render_filter=>[], :skip_parse=>\"a crazy cool instance method\"}>", Trailblazer::Core::Utils.inspect(options[:nested].representable_attrs.get(:name).inspect)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
# :options_from and :include is optional
|
|
@@ -61,8 +61,8 @@ class ReschemeTest < MiniTest::Spec
|
|
|
61
61
|
definitions_from: lambda { |nested| nested.definitions }
|
|
62
62
|
)
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
assert_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:id).inspect)
|
|
65
|
+
assert_equal "#<Representable::Definition ==>title @options={:writeable=>false, :deserializer=>{:skip_parse=>\"skip lambda\"}, :name=>\"title\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:title).inspect)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
|
|
@@ -73,9 +73,9 @@ class ReschemeTest < MiniTest::Spec
|
|
|
73
73
|
exclude_options: [:deserializer]
|
|
74
74
|
)
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
assert_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:id).inspect)
|
|
77
|
+
assert_equal "#<Representable::Definition ==>title @options={:writeable=>false, :name=>\"title\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:title).inspect)
|
|
78
|
+
assert_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :name=>\"name\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
|
|
@@ -85,8 +85,8 @@ class ReschemeTest < MiniTest::Spec
|
|
|
85
85
|
definitions_from: lambda { |nested| nested.definitions },
|
|
86
86
|
) { |dfn| dfn.merge!(amazing: true) }
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
assert_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[], :amazing=>true}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:id).inspect)
|
|
89
|
+
assert_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :name=>\"name\", :parse_filter=>[], :render_filter=>[], :amazing=>true}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
it "recursive: false only copies first level" do
|
|
@@ -97,8 +97,8 @@ class ReschemeTest < MiniTest::Spec
|
|
|
97
97
|
exclude_options: [:deserializer]
|
|
98
98
|
)
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
assert_equal "#<Representable::Definition ==>title @options={:writeable=>false, :name=>\"title\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:title).inspect)
|
|
101
|
+
assert_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :name=>\"name\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect)
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
describe ":exclude_properties" do
|
|
@@ -128,7 +128,7 @@ class ReschemeTest < MiniTest::Spec
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
|
|
131
|
-
class TwinReschemeTest <
|
|
131
|
+
class TwinReschemeTest < Minitest::Spec
|
|
132
132
|
class Artist < Disposable::Twin
|
|
133
133
|
property :name
|
|
134
134
|
end
|
|
@@ -145,8 +145,8 @@ class TwinReschemeTest < MiniTest::Spec
|
|
|
145
145
|
artist = decorator.representable_attrs.get(:artist)
|
|
146
146
|
options = artist.instance_variable_get(:@options)
|
|
147
147
|
nested_extend = options[:nested]
|
|
148
|
-
|
|
148
|
+
assert_equal "{:private_name=>:artist, :nested=>#<Class:>, :name=>\"artist\", :extend=>#<Class:>, :parse_filter=>[], :render_filter=>[]}", Trailblazer::Core::Utils.inspect(options.extend(Declarative::Inspect).inspect)
|
|
149
149
|
assert nested_extend < Representable::Decorator
|
|
150
|
-
|
|
150
|
+
assert_equal "#<Representable::Definition ==>name @options={:private_name=>:name, :name=>\"name\", :parse_filter=>[], :render_filter=>[]}>", Trailblazer::Core::Utils.inspect(nested_extend.representable_attrs.get(:name).inspect)
|
|
151
151
|
end
|
|
152
152
|
end
|
data/test/skip_getter_test.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
|
|
3
|
-
class SkipGetterTest <
|
|
3
|
+
class SkipGetterTest < Minitest::Spec
|
|
4
4
|
Album = Struct.new(:title, :artist)
|
|
5
5
|
Artist = Struct.new(:name)
|
|
6
6
|
|
|
@@ -44,7 +44,7 @@ class SkipGetterTest < MiniTest::Spec
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class SkipSetterTest <
|
|
47
|
+
class SkipSetterTest < Minitest::Spec
|
|
48
48
|
Album = Struct.new(:title, :artist)
|
|
49
49
|
Artist = Struct.new(:name)
|
|
50
50
|
|
|
@@ -74,7 +74,7 @@ class SkipSetterTest < MiniTest::Spec
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
class SkipGetterAndSetterWithChangedTest <
|
|
77
|
+
class SkipGetterAndSetterWithChangedTest < Minitest::Spec
|
|
78
78
|
Album = Struct.new(:title, :artist)
|
|
79
79
|
Artist = Struct.new(:name)
|
|
80
80
|
|
data/test/test_helper.rb
CHANGED
|
@@ -3,6 +3,7 @@ require "minitest/autorun"
|
|
|
3
3
|
# require "representable/debug"
|
|
4
4
|
# require "pp"
|
|
5
5
|
require "declarative/testing"
|
|
6
|
+
require "trailblazer/core"
|
|
6
7
|
|
|
7
8
|
require "disposable/twin/coercion"
|
|
8
9
|
DRY_TYPES_CONSTANT = Disposable::Twin::Coercion::DRY_TYPES_CONSTANT
|
|
@@ -78,4 +79,3 @@ module Disposable
|
|
|
78
79
|
end
|
|
79
80
|
end
|
|
80
81
|
end
|
|
81
|
-
|
data/test/twin/benchmarking.rb
CHANGED
data/test/twin/builder_test.rb
CHANGED
data/test/twin/changed_test.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
# require 'reform/form/coercion'
|
|
3
3
|
|
|
4
|
-
class ChangedWithSetupTest <
|
|
4
|
+
class ChangedWithSetupTest < Minitest::Spec
|
|
5
5
|
module Model
|
|
6
6
|
Song = Struct.new(:title, :length, :composer)
|
|
7
7
|
Album = Struct.new(:name, :songs, :artist)
|
|
@@ -107,7 +107,7 @@ end
|
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
require "disposable/twin/coercion"
|
|
110
|
-
class ChangedWithCoercionTest <
|
|
110
|
+
class ChangedWithCoercionTest < Minitest::Spec
|
|
111
111
|
Song = Struct.new(:released)
|
|
112
112
|
|
|
113
113
|
class SongTwin < Disposable::Twin
|
data/test/twin/coercion_test.rb
CHANGED
|
@@ -2,7 +2,13 @@ require "test_helper"
|
|
|
2
2
|
|
|
3
3
|
require "disposable/twin/coercion"
|
|
4
4
|
|
|
5
|
-
class CoercionTest <
|
|
5
|
+
class CoercionTest < Minitest::Spec
|
|
6
|
+
Album = Struct.new(:id, :released_at, :hit, :band, keyword_init: true)
|
|
7
|
+
Hit = Struct.new(:length, :good, keyword_init: true)
|
|
8
|
+
Band = Struct.new(:label, keyword_init: true)
|
|
9
|
+
Label = Struct.new(:value, keyword_init: true)
|
|
10
|
+
Person = Struct.new(:id, :date_of_birth, :date_of_death_by_unicorns, keyword_init: true)
|
|
11
|
+
|
|
6
12
|
class TwinWithSkipSetter < Disposable::Twin
|
|
7
13
|
feature Coercion
|
|
8
14
|
feature Setup::SkipSetter
|
|
@@ -28,11 +34,11 @@ class CoercionTest < MiniTest::Spec
|
|
|
28
34
|
end
|
|
29
35
|
|
|
30
36
|
let (:album) {
|
|
31
|
-
|
|
37
|
+
Album.new(
|
|
32
38
|
id: 1,
|
|
33
39
|
:released_at => "31/03/1981",
|
|
34
|
-
:hit =>
|
|
35
|
-
:band =>
|
|
40
|
+
:hit => Hit.new(:length => "312"),
|
|
41
|
+
:band => Band.new(:label => Label.new(:value => "9999.99"))
|
|
36
42
|
)
|
|
37
43
|
}
|
|
38
44
|
|
|
@@ -65,7 +71,7 @@ class CoercionTest < MiniTest::Spec
|
|
|
65
71
|
describe "without Setup::SkipSetter" do
|
|
66
72
|
|
|
67
73
|
subject do
|
|
68
|
-
TwinWithoutSkipSetter.new(
|
|
74
|
+
TwinWithoutSkipSetter.new(Person.new(id: "1"))
|
|
69
75
|
end
|
|
70
76
|
|
|
71
77
|
it "coerce values in setup and when using a setter" do
|
|
@@ -95,9 +101,9 @@ class CoercionTest < MiniTest::Spec
|
|
|
95
101
|
|
|
96
102
|
describe "with Nilify" do
|
|
97
103
|
subject do
|
|
98
|
-
TwinWithNilify.new(
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
TwinWithNilify.new(Person.new(date_of_birth: '1990-01-12',
|
|
105
|
+
date_of_death_by_unicorns: '2037-02-18',
|
|
106
|
+
id: 1))
|
|
101
107
|
end
|
|
102
108
|
|
|
103
109
|
it "coerce values correctly" do
|
|
@@ -125,7 +131,7 @@ class CoercionTest < MiniTest::Spec
|
|
|
125
131
|
let(:date_of_birth) { '1990-01-12' }
|
|
126
132
|
subject do
|
|
127
133
|
TwinWithoutTypeWithNilify.new(
|
|
128
|
-
|
|
134
|
+
Person.new(
|
|
129
135
|
date_of_birth: date_of_birth,
|
|
130
136
|
date_of_death_by_unicorns: '2037-02-18',
|
|
131
137
|
id: 1
|
|
@@ -156,7 +162,7 @@ end
|
|
|
156
162
|
# this converts "" to nil and then breaks because it's strict.
|
|
157
163
|
# Types::Strict::String.constructor(Dry::Types::Params.method(:to_nil))
|
|
158
164
|
|
|
159
|
-
class CoercionTypingTest <
|
|
165
|
+
class CoercionTypingTest < Minitest::Spec
|
|
160
166
|
class Song < Disposable::Twin
|
|
161
167
|
include Coercion
|
|
162
168
|
include Setup::SkipSetter
|
|
@@ -5,7 +5,7 @@ require 'test_helper'
|
|
|
5
5
|
|
|
6
6
|
# TODO: eg "after delete hook (dynamic_delete)", after_add
|
|
7
7
|
|
|
8
|
-
class TwinCollectionTest <
|
|
8
|
+
class TwinCollectionTest < Minitest::Spec
|
|
9
9
|
module Model
|
|
10
10
|
Song = Struct.new(:id, :title, :album)
|
|
11
11
|
Album = Struct.new(:id, :name, :songs, :artist)
|
|
@@ -54,7 +54,7 @@ end
|
|
|
54
54
|
require "disposable/twin/sync"
|
|
55
55
|
require "disposable/twin/save"
|
|
56
56
|
|
|
57
|
-
class TwinCollectionActiveRecordTest <
|
|
57
|
+
class TwinCollectionActiveRecordTest < Minitest::Spec
|
|
58
58
|
module Twin
|
|
59
59
|
class Song < Disposable::Twin
|
|
60
60
|
property :id # DISCUSS: needed for #save.
|
|
@@ -204,7 +204,7 @@ class TwinCollectionActiveRecordTest < MiniTest::Spec
|
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
|
|
207
|
-
class CollectionUnitTest <
|
|
207
|
+
class CollectionUnitTest < Minitest::Spec
|
|
208
208
|
module Twin
|
|
209
209
|
class Album < Disposable::Twin
|
|
210
210
|
end
|
|
@@ -215,11 +215,12 @@ class CollectionUnitTest < MiniTest::Spec
|
|
|
215
215
|
end
|
|
216
216
|
|
|
217
217
|
module Model
|
|
218
|
+
Song = Struct.new(:id, :title, :album)
|
|
218
219
|
Album = Struct.new(:id, :name, :songs, :artist)
|
|
219
220
|
end
|
|
220
221
|
|
|
221
222
|
# THIS is why private tests suck!
|
|
222
|
-
let(:collection) { Disposable::Twin::Collection.new(Disposable::Twin::Twinner.new(Twin::Song.new(
|
|
223
|
+
let(:collection) { Disposable::Twin::Collection.new(Disposable::Twin::Twinner.new(Twin::Song.new(Model::Song.new), Twin::Song.definitions.get(:album)), []) }
|
|
223
224
|
|
|
224
225
|
# #insert(index, model)
|
|
225
226
|
it do
|
data/test/twin/expose_test.rb
CHANGED
data/test/twin/feature_test.rb
CHANGED
data/test/twin/from_test.rb
CHANGED
data/test/twin/hash_test.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
require "disposable/twin/property/hash"
|
|
3
3
|
|
|
4
|
-
class HashTest <
|
|
4
|
+
class HashTest < Minitest::Spec
|
|
5
5
|
Model = Struct.new(:id, :content)
|
|
6
6
|
|
|
7
7
|
class Song < Disposable::Twin
|
|
@@ -64,7 +64,7 @@ class HashTest < MiniTest::Spec
|
|
|
64
64
|
|
|
65
65
|
song.sync
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
assert_equal "#<struct HashTest::Model id=nil, content={\"band\"=>{\"label\"=>{\"location\"=>\"San Francisco\"}}, \"releases\"=>[]}>", Trailblazer::Core::Utils.inspect(model.inspect)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
it "#appends to collections" do
|
|
@@ -76,7 +76,7 @@ class HashTest < MiniTest::Spec
|
|
|
76
76
|
|
|
77
77
|
song.sync
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
assert_equal "#<struct HashTest::Model id=nil, content={\"band\"=>{\"label\"=>{}}, \"releases\"=>[{\"version\"=>1}]}>", Trailblazer::Core::Utils.inspect(model.inspect)
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
it "doesn't erase existing, undeclared content" do
|
|
@@ -88,7 +88,7 @@ class HashTest < MiniTest::Spec
|
|
|
88
88
|
# puts song.content.class.ancestors
|
|
89
89
|
song.sync
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
assert_equal "#<struct HashTest::Model id=nil, content={\"artist\"=>{}, \"band\"=>{\"label\"=>{\"location\"=>\"San Francisco\"}}, \"releases\"=>[]}>", Trailblazer::Core::Utils.inspect(model.inspect)
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
it "doesn't erase existing, undeclared content in existing content" do
|
|
@@ -99,7 +99,7 @@ class HashTest < MiniTest::Spec
|
|
|
99
99
|
|
|
100
100
|
song.sync
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
assert_equal "#<struct HashTest::Model id=nil, content={\"band\"=>{\"label\"=>{\"owner\"=>\"Brett Gurewitz\", \"location\"=>\"San Francisco\"}, \"genre\"=>\"Punkrock\"}, \"releases\"=>[]}>", Trailblazer::Core::Utils.inspect(model.inspect)
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
|
data/test/twin/inherit_test.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
|
|
3
|
-
class InheritTest <
|
|
3
|
+
class InheritTest < Minitest::Spec
|
|
4
4
|
module Model
|
|
5
5
|
Song = Struct.new(:title, :album)
|
|
6
6
|
Album = Struct.new(:name, :songs, :artist)
|
|
@@ -40,8 +40,8 @@ class InheritTest < MiniTest::Spec
|
|
|
40
40
|
|
|
41
41
|
# definitions are not shared.
|
|
42
42
|
it do
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
assert_equal "#<Disposable::Twin::Definition: @options={:fromage=>:_name, :private_name=>:name, :name=>\"name\"}>", Trailblazer::Core::Utils.inspect(Twin::Album.definitions.get(:name).extend(Declarative::Inspect).inspect)
|
|
44
|
+
assert_equal "#<Disposable::Twin::Definition: @options={:fromage=>:_name, :private_name=>:name, :name=>\"name\", :writeable=>false}>", Trailblazer::Core::Utils.inspect(Twin::Compilation.definitions.get(:name).extend(Declarative::Inspect).inspect) # FIXME: where did :inherit go?
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
|
data/test/twin/parent_test.rb
CHANGED
data/test/twin/readable_test.rb
CHANGED
data/test/twin/save_test.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
|
-
class SaveTest <
|
|
3
|
+
class SaveTest < Minitest::Spec
|
|
4
4
|
module Model
|
|
5
5
|
Song = Struct.new(:title, :composer)
|
|
6
6
|
Album = Struct.new(:name, :songs, :artist)
|
|
@@ -166,7 +166,7 @@ end
|
|
|
166
166
|
|
|
167
167
|
# TODO: with block
|
|
168
168
|
|
|
169
|
-
# class SaveWithDynamicOptionsTest <
|
|
169
|
+
# class SaveWithDynamicOptionsTest < Minitest::Spec
|
|
170
170
|
# Song = Struct.new(:id, :title, :length) do
|
|
171
171
|
# include Disposable::Saveable
|
|
172
172
|
# end
|
data/test/twin/setup_test.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
|
|
3
|
-
class TwinSetupTest <
|
|
3
|
+
class TwinSetupTest < Minitest::Spec
|
|
4
4
|
module Model
|
|
5
5
|
Song = Struct.new(:id, :title, :album, :composer)
|
|
6
6
|
Album = Struct.new(:id, :name, :songs, :artist)
|
|
@@ -82,7 +82,7 @@ class TwinSetupTest < MiniTest::Spec
|
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
# test inline twin building and setup.
|
|
85
|
-
class TwinSetupWithInlineTwinsTest <
|
|
85
|
+
class TwinSetupWithInlineTwinsTest < Minitest::Spec
|
|
86
86
|
module Model
|
|
87
87
|
Song = Struct.new(:id, :composer)
|
|
88
88
|
Album = Struct.new(:id, :name, :songs, :artist)
|
|
@@ -139,7 +139,7 @@ class TwinSetupWithInlineTwinsTest < MiniTest::Spec
|
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
# Twin.new(model, is_online: true)
|
|
142
|
-
class TwinWithVirtualSetupTest <
|
|
142
|
+
class TwinWithVirtualSetupTest < Minitest::Spec
|
|
143
143
|
Song = Struct.new(:id)
|
|
144
144
|
|
|
145
145
|
class AlbumTwin < Disposable::Twin
|
data/test/twin/struct_test.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
|
3
3
|
|
|
4
4
|
require 'disposable/twin/struct'
|
|
5
5
|
|
|
6
|
-
class TwinStructTest <
|
|
6
|
+
class TwinStructTest < Minitest::Spec
|
|
7
7
|
class Song < Disposable::Twin
|
|
8
8
|
include Property::Struct
|
|
9
9
|
property :number#, default: 1 # FIXME: this should be :default_if_nil so it becomes clear with a model.
|
|
@@ -54,7 +54,7 @@ class TwinStructTest < MiniTest::Spec
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
class TwinWithNestedStructTest <
|
|
57
|
+
class TwinWithNestedStructTest < Minitest::Spec
|
|
58
58
|
class Song < Disposable::Twin
|
|
59
59
|
property :title
|
|
60
60
|
include Sync
|
|
@@ -78,7 +78,11 @@ class TwinWithNestedStructTest < MiniTest::Spec
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
# FIXME: test with missing hash properties, e.g. without released and with released:false.
|
|
81
|
-
|
|
81
|
+
Model = Struct.new(:title, :options, keyword_init: true) do
|
|
82
|
+
def save = true
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
let (:model) { Model.new(title: "Seed of Fear and Anger", options: {recorded: true, released: 1,
|
|
82
86
|
preferences: {show_image: true, play_teaser: 2}, roles: [{name: "user"}]}) }
|
|
83
87
|
|
|
84
88
|
# public "hash" reader
|
|
@@ -288,8 +292,10 @@ class CompositionWithStructTest < Minitest::Spec
|
|
|
288
292
|
end
|
|
289
293
|
end
|
|
290
294
|
|
|
295
|
+
Model = Struct.new(:content, keyword_init: true)
|
|
296
|
+
|
|
291
297
|
let (:model) do
|
|
292
|
-
|
|
298
|
+
Model.new(
|
|
293
299
|
content: {
|
|
294
300
|
tags: "#hashtag",
|
|
295
301
|
notes: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# require 'test_helper'
|
|
2
2
|
# require "disposable/twin/changed"
|
|
3
3
|
|
|
4
|
-
# class SyncOptionTest <
|
|
4
|
+
# class SyncOptionTest < Minitest::Spec
|
|
5
5
|
# module Model
|
|
6
6
|
# Song = Struct.new(:title, :composer)
|
|
7
7
|
# Album = Struct.new(:id, :name, :songs, :artist)
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
# end
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
# class SyncWithDynamicOptionsTest <
|
|
81
|
+
# class SyncWithDynamicOptionsTest < Minitest::Spec
|
|
82
82
|
# module Model
|
|
83
83
|
# Song = Struct.new(:title, :composer)
|
|
84
84
|
# Album = Struct.new(:id, :name, :songs, :artist)
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
# end
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
# class SyncWithOptionsAndSkipUnchangedTest <
|
|
155
|
+
# class SyncWithOptionsAndSkipUnchangedTest < Minitest::Spec
|
|
156
156
|
# module Model
|
|
157
157
|
# Song = Struct.new(:title, :composer)
|
|
158
158
|
# Album = Struct.new(:id, :name, :songs, :artist)
|
|
@@ -200,7 +200,7 @@
|
|
|
200
200
|
# end
|
|
201
201
|
|
|
202
202
|
# # :virtual wins over :sync
|
|
203
|
-
# # class SyncWithVirtualTest <
|
|
203
|
+
# # class SyncWithVirtualTest < Minitest::Spec
|
|
204
204
|
# # Song = Struct.new(:title, :image, :band)
|
|
205
205
|
# # Band = Struct.new(:name)
|
|
206
206
|
|
data/test/twin/sync_test.rb
CHANGED
data/test/twin/twin_test.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
|
-
class TwinTest <
|
|
3
|
+
class TwinTest < Minitest::Spec
|
|
4
4
|
module Model
|
|
5
5
|
Song = Struct.new(:id, :title, :album)
|
|
6
6
|
Album = Struct.new(:id, :name, :songs, :artist)
|
|
@@ -114,7 +114,7 @@ class OverridingAccessorsTest < TwinTest
|
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
|
|
117
|
-
class TwinAsTest <
|
|
117
|
+
class TwinAsTest < Minitest::Spec
|
|
118
118
|
module Model
|
|
119
119
|
Song = Struct.new(:title, :album)
|
|
120
120
|
Album = Struct.new(:name)
|
data/test/twin/unnest_test.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
|
|
3
|
-
class UnnestTest <
|
|
3
|
+
class UnnestTest < Minitest::Spec
|
|
4
4
|
class Twin < Disposable::Twin
|
|
5
5
|
property :content do
|
|
6
6
|
property :id, nice: "yes"
|
|
@@ -16,14 +16,17 @@ class UnnestTest < MiniTest::Spec
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "copies property option" do
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
assert_equal %{#<Disposable::Twin::Definition: @options={:nice=>\"yes\", :private_name=>:id, :name=>\"id\", :readable=>false, :writeable=>false}>}, Trailblazer::Core::Utils.inspect(Twin.definitions.get(:id).extend(Declarative::Inspect).inspect)
|
|
20
|
+
assert_equal %{#<Disposable::Twin::Definition: @options={:status=>\"healthy\", :collection=>true, :private_name=>:ids, :name=>\"ids\", :readable=>false, :writeable=>false}>}, Trailblazer::Core::Utils.inspect(Twin.definitions.get(:ids).extend(Declarative::Inspect).inspect)
|
|
21
21
|
# also copies :nested.
|
|
22
|
-
|
|
22
|
+
assert_equal %{#<Disposable::Twin::Definition: @options={:private_name=>:email, :nested=>#<Class:>, :name=>\"email\", :readable=>false, :writeable=>false}>}, Trailblazer::Core::Utils.inspect(Twin.definitions.get(:email).extend(Declarative::Inspect).inspect)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
Content = Struct.new(:id, :ids, :email)
|
|
26
|
+
Model = Struct.new(:content)
|
|
27
|
+
|
|
25
28
|
it "exposes accessors on top-level twin" do
|
|
26
|
-
twin = Twin.new(
|
|
29
|
+
twin = Twin.new(Model.new(Content.new))
|
|
27
30
|
|
|
28
31
|
expect(twin.email).must_be_nil
|
|
29
32
|
twin.email= 2
|
data/test/twin/virtual_test.rb
CHANGED
data/test/twin/writeable_test.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: disposable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nick Sutterer
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: declarative
|
|
@@ -127,6 +126,7 @@ executables: []
|
|
|
127
126
|
extensions: []
|
|
128
127
|
extra_rdoc_files: []
|
|
129
128
|
files:
|
|
129
|
+
- ".github/dependabot.yml"
|
|
130
130
|
- ".github/workflows/ci.yml"
|
|
131
131
|
- ".gitignore"
|
|
132
132
|
- CHANGES.md
|
|
@@ -203,7 +203,6 @@ homepage: https://github.com/apotonick/disposable
|
|
|
203
203
|
licenses:
|
|
204
204
|
- MIT
|
|
205
205
|
metadata: {}
|
|
206
|
-
post_install_message:
|
|
207
206
|
rdoc_options: []
|
|
208
207
|
require_paths:
|
|
209
208
|
- lib
|
|
@@ -211,15 +210,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
211
210
|
requirements:
|
|
212
211
|
- - ">="
|
|
213
212
|
- !ruby/object:Gem::Version
|
|
214
|
-
version:
|
|
213
|
+
version: 3.3.0
|
|
215
214
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
215
|
requirements:
|
|
217
216
|
- - ">="
|
|
218
217
|
- !ruby/object:Gem::Version
|
|
219
218
|
version: '0'
|
|
220
219
|
requirements: []
|
|
221
|
-
rubygems_version:
|
|
222
|
-
signing_key:
|
|
220
|
+
rubygems_version: 4.0.17
|
|
223
221
|
specification_version: 4
|
|
224
222
|
summary: Decorators on top of your ORM layer with change tracking, collection semantics
|
|
225
223
|
and nesting.
|