disposable 0.1.15 → 0.2.0.rc1

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: af71c707fe20d98b1c391731fdcf9364c1817132
4
- data.tar.gz: faae48ac6f616ebe485d7c9c4557cfe103ba9bb1
3
+ metadata.gz: a33b386392c77411ef19323562c9f0bb3b31761c
4
+ data.tar.gz: 789982e39d11feb8a4550e93452ca8d9ba91ac07
5
5
  SHA512:
6
- metadata.gz: af47c88b1c74259f7903ef82e5cd480e40b0437796d421c2cfa43065ed6d19a83fc4361fd679460490b3b722100146b95baaea7712f49af81147385093636fda
7
- data.tar.gz: 56482ea426fdb444826fca0240c97e0c615f155dc7bc7300c6e223f0f852484d7419d504fa7e8e55d5b73b1709212f3d0cce3d193fa0881b7034909dcf38ae80
6
+ metadata.gz: eb94a6c5097a5b380011f9a6cf6f6b02081b058842751110beec5b2f82cc37fc088f08d8b3ea2b8fb3d87e8607c9e44acc446d52470394f4ca27736cf8c29891
7
+ data.tar.gz: d11e58f841ecccfb165f6c48e6ddeb65eb3e9fe8b4aade955b6fc906bd056abc63589c9d42f05c1a35effb45becd6d0a6a616a171c81797d28fce1ac871895cf
data/.travis.yml CHANGED
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  rvm:
3
4
  - 2.2.0
4
5
  - 2.1.2
5
6
  - 2.0.0
6
7
  - 1.9.3
7
8
  gemfile:
8
- - Gemfile
9
+ - Gemfile
data/CHANGES.md CHANGED
@@ -1,6 +1,9 @@
1
- # 0.1.15
1
+ # 0.2.0
2
2
 
3
- * Restrict to Representable < 2.4.
3
+ * Internally, use [Declarative](https://github.com/apotonick/declarative) now for schema creation, resulting in the following internal changes.
4
+ * `Twin::representer_class.representable_attrs` is now `Twin::definitions`.
5
+ * `Disposable::Twin::Schema` is now `Disposable::Rescheme`. Renamed its `:representer_from` option to `:definitions_from`.
6
+ * `twin: Twin::Song` is the only way to specify an external twin. To reduce complexity, I've removed the lambda version of `:twin`.
4
7
 
5
8
  # 0.1.14
6
9
 
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in disposable.gemspec
1
+ source "https://rubygems.org"
4
2
  gemspec
5
3
 
6
- # gem 'representable', path: '../representable'
4
+ # gem "representable", path: "../representable"
5
+ gem "representable", github: "apotonick/representable"
6
+ # gem "declarative", path: "../declarative"
7
+ # gem "declarative", github: "apotonick/declarative"
8
+ gem "minitest-line"
data/disposable.gemspec CHANGED
@@ -19,7 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "uber"
22
- spec.add_dependency "representable", ">= 2.2.3", "< 2.4.0"
22
+ spec.add_dependency "declarative", "~> 0.0.4"
23
+ spec.add_dependency "representable", ">= 2.4.0.rc1", "< 2.5.0"
23
24
 
24
25
  spec.add_development_dependency "bundler", "~> 1.3"
25
26
  spec.add_development_dependency "rake"
@@ -12,26 +12,16 @@ module Disposable::Callback
12
12
  # you can call collection :songs again, with :inherit. TODO: verify.
13
13
 
14
14
  class Group
15
- # TODO: make this easier via declarable.
16
- extend Uber::InheritableAttr
17
- inheritable_attr :representer_class
18
-
19
- # class << self
20
- # include Representable::Cloneable
21
- # end
22
- self.representer_class = Class.new(Representable::Decorator) do
23
- def self.default_inline_class
24
- Group.extend Representable::Cloneable
25
- end
15
+ extend Declarative::Schema
16
+
17
+ def self.default_nested_class
18
+ Group
26
19
  end
27
20
 
28
21
  def self.clone
29
22
  Class.new(self)
30
23
  end
31
24
 
32
- def self.feature(*args)
33
- end
34
-
35
25
  def self.collection(name, options={}, &block)
36
26
  property(name, options.merge(collection: true), &block)
37
27
  end
@@ -42,9 +32,9 @@ module Disposable::Callback
42
32
  # it should have a Definition per callback where the representer_module will be a nested Group or a Callback.
43
33
  inherit = options[:inherit] # FIXME: this is deleted in ::property.
44
34
 
45
- representer_class.property(name, options, &block).tap do |dfn|
35
+ super(name, options, &block).tap do |dfn|
46
36
  return if inherit
47
- hooks << ["property", dfn.name]
37
+ hooks << ["property", dfn[:name]]
48
38
  end
49
39
  end
50
40
 
@@ -60,12 +50,16 @@ module Disposable::Callback
60
50
 
61
51
  attr_reader :invocations
62
52
 
63
- inheritable_attr :hooks
64
- self.hooks = []
53
+ def self.hooks
54
+ @hooks ||= []
55
+ end
56
+
65
57
 
66
58
  class << self
67
59
  %w(on_add on_delete on_destroy on_update on_create on_change).each do |event|
68
60
  define_method event do |*args|
61
+ heritage.record(event, *args)
62
+
69
63
  hooks << [event.to_sym, args]
70
64
  end
71
65
  end
@@ -73,14 +67,13 @@ module Disposable::Callback
73
67
 
74
68
 
75
69
  def call(options={})
76
- self.class.hooks.each do |cfg|
77
- event, args = cfg
78
-
70
+ self.class.hooks.each do |event, args|
79
71
  if event == "property" # FIXME: make nicer.
80
- definition = self.class.representer_class.representable_attrs.get(args)
81
- twin = @twin.send(definition.getter) # album.songs
72
+ definition = self.class.definitions.get(args)
73
+ twin = @twin.send(definition[:name]) # album.songs
82
74
 
83
- @invocations += definition.representer_module.new(twin).(options).invocations # Group.new(twin).()
75
+ # recursively call nested group.
76
+ @invocations += definition[:nested].new(twin).(options).invocations # Group.new(twin).()
84
77
  next
85
78
  end
86
79
 
@@ -108,7 +101,7 @@ module Disposable::Callback
108
101
  # Implements the binding between the Callback API (on_change) and the underlying layer (twin/AR/etc.).
109
102
  class Dispatch
110
103
  def initialize(twins)
111
- @twins = twins.is_a?(Array) ? twins : [twins] # TODO: find that out with Collection.
104
+ @twins = Array(twins) # TODO: find that out with Collection.
112
105
  @invocations = []
113
106
  end
114
107
 
@@ -175,4 +168,4 @@ module Disposable::Callback
175
168
  end
176
169
  end
177
170
  end
178
- end
171
+ end
@@ -13,8 +13,8 @@ module Disposable
13
13
  # AlbumExpose.new(OpenStruct.new(title: "AFI")).name #=> "AFI"
14
14
  class Expose
15
15
  class << self
16
- def from(representer)
17
- representer.representable_attrs.each do |definition|
16
+ def from(schema)
17
+ schema.each do |definition|
18
18
  process_definition!(definition)
19
19
  end
20
20
  self
@@ -22,7 +22,7 @@ module Disposable
22
22
 
23
23
  private
24
24
  def process_definition!(definition)
25
- public_name = definition.name
25
+ public_name = definition[:name]
26
26
  private_name = definition[:private_name] || public_name
27
27
 
28
28
  accessors!(public_name, private_name, definition)
@@ -1,13 +1,13 @@
1
- # Schema::from allows to copy a representer structure. This will create "fresh" inline representers instead
1
+ # Rescheme::from allows to copy a schema structure. This will create "fresh" inline schemas instead
2
2
  # of inheriting/copying the original classes, making it a replication of the structure, only.
3
3
  #
4
- # Options allow to customize the copied representer.
4
+ # Options allow to customize the copied schema.
5
5
  #
6
6
  # +:exclude+: ignore options from original Definition when copying.
7
7
  #
8
8
  # Provided block is run per newly created Definition.
9
- # Schema.from(...) { |dfn| dfn[:readable] = true }
10
- class Disposable::Twin::Schema
9
+ # Rescheme.from(...) { |dfn| dfn[:readable] = true }
10
+ class Disposable::Rescheme
11
11
  def self.from(*args, &block)
12
12
  new.from(*args, &block)
13
13
  end
@@ -16,9 +16,9 @@ class Disposable::Twin::Schema
16
16
  def from(source_class, options, &block) # TODO: can we re-use this for all the decorator logic in #validate, etc?
17
17
  representer = build_representer(options)
18
18
 
19
- source_representer = options[:representer_from].call(source_class)
19
+ definitions = options[:definitions_from].call(source_class)
20
20
 
21
- source_representer.representable_attrs.each do |dfn|
21
+ definitions.each do |dfn|
22
22
  dfn = build_definition!(options, dfn, representer, &block)
23
23
  evaluate_block!(options, dfn, &block)
24
24
  end
@@ -41,7 +41,7 @@ private
41
41
  new_options.merge!(local_options)
42
42
 
43
43
  return from_scalar!(options, source_dfn, new_options, representer) if options[:recursive]==false
44
- return from_scalar!(options, source_dfn, new_options, representer) unless source_dfn[:extend]
44
+ return from_scalar!(options, source_dfn, new_options, representer) unless source_dfn[:nested]
45
45
  from_inline!(options, source_dfn, new_options, representer, &block)
46
46
  end
47
47
 
@@ -52,14 +52,14 @@ private
52
52
  end
53
53
 
54
54
  def from_scalar!(options, dfn, new_options, representer)
55
- representer.property(dfn.name, new_options)
55
+ representer.property(dfn[:name], new_options)
56
56
  end
57
57
 
58
58
  def from_inline!(options, dfn, new_options, representer, &block)
59
- nested = dfn[:extend].evaluate(nil) # nested now can be a Decorator, a representer module, a Form, a Twin.
60
- dfn_options = new_options.merge(extend: from(nested, options, &block))
59
+ nested = dfn[:nested]#.evaluate(nil) # nested now can be a Decorator, a representer module, a Form, a Twin.
60
+ dfn_options = new_options.merge(nested: from(nested, options, &block))
61
61
 
62
- representer.property(dfn.name, dfn_options)
62
+ representer.property(dfn[:name], dfn_options)
63
63
  end
64
64
 
65
65
  def evaluate_block!(options, definition)
@@ -44,7 +44,7 @@ private
44
44
  next unless twin = send(dfn.getter)
45
45
  next unless twin.changed?
46
46
 
47
- changes[dfn.name] = true
47
+ changes[dfn[:name]] = true
48
48
  end
49
49
  end
50
50
  end
@@ -6,7 +6,7 @@ module Disposable
6
6
  module Expose
7
7
  module ClassMethods
8
8
  def expose_class
9
- @expose_class ||= Class.new(Disposable::Expose).from(representer_class)
9
+ @expose_class ||= Class.new(Disposable::Expose).from(definitions.values)
10
10
  end
11
11
  end # ClassMethods.
12
12
 
@@ -26,7 +26,7 @@ module Disposable
26
26
  module Composition
27
27
  module ClassMethods
28
28
  def expose_class
29
- @expose_class ||= Class.new(Disposable::Composition).from(representer_class)
29
+ @expose_class ||= Class.new(Disposable::Composition).from(definitions.values)
30
30
  end
31
31
  end
32
32
 
@@ -39,7 +39,7 @@ module Disposable
39
39
  hash = {}
40
40
 
41
41
  @model.each do |name, model| # TODO: provide list of composee attributes in Composition.
42
- part_properties = self.class.representer_class.representable_attrs.find_all { |dfn| dfn[:on] == name }.collect(&:name).collect(&:to_sym)
42
+ part_properties = schema.find_all { |dfn| dfn[:on] == name }.collect{ |dfn| dfn[:name].to_sym }
43
43
  hash[name] = self.class.nested_hash_representer.new(self).to_hash(include: part_properties)
44
44
  end
45
45
 
@@ -0,0 +1,28 @@
1
+ class Disposable::Twin
2
+ class Definition < Declarative::Definitions::Definition
3
+ def getter
4
+ self[:name]
5
+ end
6
+
7
+ def setter
8
+ "#{self[:name]}="
9
+ end
10
+ end
11
+
12
+ module DefinitionsEach
13
+ def each(options={})
14
+ return self unless block_given?
15
+
16
+ super() do |dfn|
17
+ next if options[:exclude] and options[:exclude].include?(dfn[:name])
18
+ next if options[:scalar] and dfn[:collection]
19
+ next if options[:collection] and ! dfn[:collection]
20
+ next if options[:twin] and ! dfn[:nested]
21
+
22
+ yield dfn
23
+ end
24
+
25
+ self
26
+ end
27
+ end
28
+ end
@@ -24,8 +24,8 @@ module Disposable
24
24
 
25
25
  def setup_property!(dfn, options)
26
26
  value =
27
- if options.has_key?(name = dfn.name.to_sym)
28
- options[dfn.name.to_sym]
27
+ if options.has_key?(name = dfn[:name].to_sym)
28
+ options[dfn[:name].to_sym]
29
29
  else
30
30
  setup_value_for(dfn, options)
31
31
  end
@@ -39,17 +39,18 @@ module Disposable
39
39
  end
40
40
 
41
41
  def read_value_for(dfn, options)
42
- mapper.send(dfn.name) # model.title.
42
+ mapper.send(dfn[:name]) # model.title.
43
43
  end
44
44
 
45
45
  def setup_write!(dfn, value)
46
- send(dfn.setter, value)
46
+ # send(dfn.setter, value)
47
+ send("#{dfn[:name]}=", value) # FIXME!
47
48
  end
48
49
 
49
50
  # Including this will _not_ use the property's setter in Setup and allow you to override it.
50
51
  module SkipSetter
51
52
  def setup_write!(dfn, value)
52
- write_property(dfn.name, value, dfn)
53
+ write_property(dfn[:name], value, dfn)
53
54
  end
54
55
  end
55
56
  end # Setup
@@ -5,7 +5,7 @@
5
5
  # Twin.new(id: 1)
6
6
  module Struct
7
7
  def read_value_for(dfn, options)
8
- name = dfn.name
8
+ name = dfn[:name]
9
9
  @model[name.to_s] || @model[name.to_sym] # TODO: test sym vs. str.
10
10
  end
11
11
 
@@ -15,7 +15,7 @@
15
15
  prepare: lambda { |model, *| model },
16
16
  serialize: lambda { |model, *| model.sync! },
17
17
  representable: true
18
- ) if dfn[:twin]
18
+ ) if dfn[:nested]
19
19
  end
20
20
  end
21
21
 
@@ -5,12 +5,23 @@
5
5
  # Note: #sync currently implicitly saves AR objects with collections
6
6
  class Disposable::Twin
7
7
  module Sync
8
+ class Options < ::Hash
9
+ def exclude!(names)
10
+ excludes.push(*names)
11
+ self
12
+ end
13
+
14
+ def excludes
15
+ self[:exclude] ||= []
16
+ end
17
+ end
18
+
8
19
  # Creates a fresh copy of the internal representer and adds Representable::Hash.
9
20
  # This is used wherever a hash transformation is needed.
10
21
  def self.hash_representer(twin_class, &block)
11
- Schema.from(twin_class,
22
+ Disposable::Rescheme.from(twin_class,
12
23
  recursive: false,
13
- representer_from: lambda { |twin_class| twin_class.representer_class },
24
+ definitions_from: lambda { |twin_class| twin_class.definitions },
14
25
  superclass: Representable::Decorator,
15
26
  include: Representable::Hash,
16
27
  exclude_options: [:default], # TODO: TEST IN default_test.
@@ -25,19 +36,16 @@ class Disposable::Twin
25
36
  end
26
37
  alias_method :sync, :sync_models
27
38
 
28
- # reading from fields allows using readers in form for presentation
29
- # and writers still pass to fields in #validate????
30
-
31
39
  # Sync all scalar attributes, call sync! on nested and return model.
32
40
  def sync!(options) # semi-public.
33
41
  # TODO: merge this into Sync::Run or something and use in Struct, too, so we don't
34
42
  # need the representer anymore?
35
- options_for_sync = sync_options(Decorator::Options[options])
43
+ options_for_sync = sync_options(Options[options])
36
44
 
37
45
  schema.each(options_for_sync) do |dfn|
38
46
  property_value = sync_read(dfn) #
39
47
 
40
- unless dfn[:twin]
48
+ unless dfn[:nested]
41
49
  mapper.send(dfn.setter, property_value) # always sync the property
42
50
  next
43
51
  end
@@ -61,6 +69,7 @@ class Disposable::Twin
61
69
  send(definition.getter)
62
70
  end
63
71
 
72
+ # TODO: simplify that using a decent pipeline from Representable.
64
73
  module ToNestedHash
65
74
  def to_nested_hash(*)
66
75
  self.class.nested_hash_representer.new(nested_hash_source).to_hash
@@ -86,7 +95,7 @@ class Disposable::Twin
86
95
  dfn.merge!(
87
96
  prepare: lambda { |model, *| model }, # TODO: why do we need that here?
88
97
  serialize: lambda { |form, args| form.to_nested_hash },
89
- ) if dfn[:twin]
98
+ ) if dfn[:nested]
90
99
  end
91
100
  end # #build_nested_hash_representer
92
101
  end
@@ -107,7 +116,7 @@ class Disposable::Twin
107
116
  def sync_options(options)
108
117
  options = super
109
118
 
110
- protected_fields = schema.each.find_all { |d| d[:writeable] == false }.collect { |d| d.name }
119
+ protected_fields = schema.each.find_all { |d| d[:writeable] == false }.collect { |d| d[:name] }
111
120
  options.exclude!(protected_fields)
112
121
  end
113
122
  end
@@ -126,7 +135,7 @@ class Disposable::Twin
126
135
  def sync_options(options)
127
136
  # DISCUSS: we currently don't track if nested forms have changed (only their attributes). that's why i include them all here, which
128
137
  # is additional sync work/slightly wrong. solution: allow forms to form.changed? not sure how to do that with collections.
129
- scalars = schema.each(scalar: true).collect { |dfn| dfn.name }
138
+ scalars = schema.each(scalar: true).collect { |dfn| dfn[:name ]}
130
139
  unchanged = scalars - changed.keys
131
140
 
132
141
  # exclude unchanged scalars, nested forms and changed scalars still go in here!
@@ -139,7 +148,7 @@ class Disposable::Twin
139
148
  # Include this won't use the getter #title in #sync but read directly from @fields.
140
149
  module SkipGetter
141
150
  def sync_read(dfn)
142
- @fields[dfn.name]
151
+ @fields[dfn[:name]]
143
152
  end
144
153
 
145
154
  def nested_hash_source
@@ -1,19 +1,18 @@
1
- # DISCUSS: sync via @fields, not reader? allows overriding a la reform 1.
2
-
3
1
  require "uber/inheritable_attr"
4
-
5
- require "disposable/twin/representer"
2
+ require "declarative/schema"
3
+ require "disposable/twin/definitions"
6
4
  require "disposable/twin/collection"
7
5
  require "disposable/twin/setup"
8
6
  require "disposable/twin/sync"
9
7
  require "disposable/twin/save"
10
- require "disposable/twin/option"
11
8
  require "disposable/twin/builder"
12
9
  require "disposable/twin/changed"
13
10
  require "disposable/twin/property_processor"
14
11
  require "disposable/twin/persisted"
15
12
  require "disposable/twin/default"
16
13
 
14
+ require "representable/decorator"
15
+
17
16
  # Twin.new(model/composition hash/hash, options)
18
17
  # assign hash to @fields
19
18
  # write: write to @fields
@@ -21,29 +20,20 @@ require "disposable/twin/default"
21
20
 
22
21
  module Disposable
23
22
  class Twin
24
- extend Uber::InheritableAttr
25
-
26
- inheritable_attr :representer_class
27
- self.representer_class = Class.new(Decorator)
28
-
29
- # Returns an each'able array of all properties defined in this twin.
30
- # Allows to filter using
31
- # * collection: true
32
- # * twin: true
33
- # * scalar: true
34
- # * exclude: ["title", "email"]
35
- def schema
36
- self.class.representer_class
23
+ extend Declarative::Schema
24
+ def self.definition_class
25
+ Definition
37
26
  end
38
27
 
39
-
40
- extend Representable::Feature # imports ::feature, which calls ::register_feature.
41
- def self.register_feature(mod)
42
- representer_class.representable_attrs[:features][mod] = true
28
+ def schema
29
+ self.class.definitions.extend(DefinitionsEach)
43
30
  end
44
31
 
45
-
46
32
  class << self
33
+ def default_nested_class
34
+ Twin
35
+ end
36
+
47
37
  # TODO: move to Declarative, as in Representable and Reform.
48
38
  def property(name, options={}, &block)
49
39
  options[:private_name] = options.delete(:from) || name
@@ -52,18 +42,10 @@ module Disposable
52
42
  options[:writeable] = options[:readable] = false
53
43
  end
54
44
 
55
- options[:extend] = options[:twin] # e.g. property :album, twin: Album.
45
+ options[:nested] = options.delete(:twin) if options[:twin]
56
46
 
57
- representer_class.property(name, options, &block).tap do |definition|
47
+ super(name, options, &block).tap do |definition|
58
48
  create_accessors(name, definition)
59
-
60
- if definition[:extend] and !options[:twin]
61
- # This will soon be replaced with Declarative's API. # DISCUSS: could we use build_inline's api here to inject the name feature?
62
- nested_twin = definition[:extend].evaluate(nil)
63
- process_inline!(nested_twin, definition)
64
-
65
- definition.merge!(twin: nested_twin) # DISCUSS: where do we need this?
66
- end
67
49
  end
68
50
  end
69
51
 
@@ -80,14 +62,10 @@ module Disposable
80
62
  mod = Module.new do
81
63
  define_method(name) { @fields[name.to_s] }
82
64
  # define_method(name) { read_property(name) }
83
- define_method("#{name}=") { |value| write_property(name, value, definition) } # TODO: this is more like prototyping.
65
+ define_method("#{name}=") { |value| write_property(name, value, definition) }
84
66
  end
85
67
  include mod
86
68
  end
87
-
88
- # DISCUSS: this method might disappear or change pretty soon.
89
- def process_inline!(mod, definition)
90
- end
91
69
  end
92
70
 
93
71
  include Setup
@@ -97,8 +75,8 @@ module Disposable
97
75
  private
98
76
  # assumption: collections are always initialized from Setup since we assume an empty [] for "nil"/uninitialized collections.
99
77
  def write_property(name, value, dfn)
100
- if dfn[:twin] and value
101
- value = dfn.array? ? wrap_collection(dfn, value) : wrap_scalar(dfn, value)
78
+ if dfn[:nested] and value
79
+ value = dfn[:collection] ? wrap_collection(dfn, value) : wrap_scalar(dfn, value)
102
80
  end
103
81
 
104
82
  field_write(name, value)
@@ -124,24 +102,13 @@ module Disposable
124
102
  end
125
103
  include Accessors
126
104
 
127
-
128
- # FIXME: this is experimental.
129
- module ToS
130
- def to_s
131
- return super if self.class.name
132
- "#<Twin (inline):#{object_id}>"
133
- end
134
- end
135
- include ToS
136
-
137
-
138
105
  class Twinner
139
106
  def initialize(dfn)
140
107
  @dfn = dfn
141
108
  end
142
109
 
143
110
  def call(value)
144
- @dfn.twin_class.new(value)
111
+ @dfn[:nested].new(value)
145
112
  end
146
113
  end
147
114
 
@@ -152,7 +119,5 @@ module Disposable
152
119
  attr_reader :mapper
153
120
  end
154
121
  include ModelReaders
155
-
156
- include Option
157
122
  end
158
- end
123
+ end
@@ -1,3 +1,3 @@
1
1
  module Disposable
2
- VERSION = "0.1.15"
2
+ VERSION = "0.2.0.rc1"
3
3
  end
data/lib/disposable.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "disposable/version"
2
2
  require "disposable/twin"
3
+ require "disposable/rescheme"
3
4
 
4
5
  module Disposable
5
6
  class Twin
@@ -148,10 +148,10 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
148
148
  it do
149
149
  Group.hooks.size.must_equal 4
150
150
  Group.hooks[0].to_s.must_equal "[:on_change, [:change!]]"
151
- # Group.hooks[1][1].representer_module.hooks.to_s.must_equal "[[:on_add, [:notify_album!]],[:on_add, [:reset_song!]]]"
151
+ # Group.hooks[1][1][:nested].hooks.to_s.must_equal "[[:on_add, [:notify_album!]],[:on_add, [:reset_song!]]]"
152
152
  Group.hooks[2].to_s.must_equal "[:on_change, [:rehash_name!, {:property=>:title}]]"
153
153
 
154
- Group.representer_class.representable_attrs.get(Group.hooks[3][1]).representer_module.hooks.to_s.must_equal "[[:on_change, [:sing!]]]"
154
+ Group.definitions.get(Group.hooks[3][1])[:nested].hooks.to_s.must_equal "[[:on_change, [:sing!]]]"
155
155
  end
156
156
 
157
157
  class EmptyGroup < Group
@@ -173,8 +173,9 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
173
173
 
174
174
  it do
175
175
  Group.hooks.size.must_equal 4
176
+ pp EnhancedGroup.hooks
176
177
  EnhancedGroup.hooks.size.must_equal 6
177
- EnhancedGroup.representer_class.representable_attrs.get(EnhancedGroup.hooks[5][1]).representer_module.hooks.to_s.must_equal "[[:on_add, [:rewind!]]]"
178
+ EnhancedGroup.definitions.get(EnhancedGroup.hooks[5][1])[:nested].hooks.to_s.must_equal "[[:on_add, [:rewind!]]]"
178
179
  end
179
180
 
180
181
  class EnhancedWithInheritGroup < EnhancedGroup
@@ -190,10 +191,10 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
190
191
  Group.hooks.size.must_equal 4
191
192
  EnhancedGroup.hooks.size.must_equal 6
192
193
 
193
- EnhancedGroup.representer_class.representable_attrs.get(EnhancedGroup.hooks[5][1]).representer_module.hooks.to_s.must_equal "[[:on_add, [:rewind!]]]"
194
+ EnhancedGroup.definitions.get(EnhancedGroup.hooks[5][1])[:nested].hooks.to_s.must_equal "[[:on_add, [:rewind!]]]"
194
195
  EnhancedWithInheritGroup.hooks.size.must_equal 6
195
- EnhancedWithInheritGroup.representer_class.representable_attrs.get(EnhancedWithInheritGroup.hooks[1][1]).representer_module.hooks.to_s.must_equal "[[:on_add, [:rewind!]], [:on_add, [:eat!]]]"
196
- EnhancedWithInheritGroup.representer_class.representable_attrs.get(EnhancedWithInheritGroup.hooks[3][1]).representer_module.hooks.to_s.must_equal "[[:on_change, [:sing!]], [:on_delete, [:yell!]]]"
196
+ EnhancedWithInheritGroup.definitions.get(EnhancedWithInheritGroup.hooks[1][1])[:nested].hooks.to_s.must_equal "[[:on_add, [:rewind!]], [:on_add, [:eat!]]]"
197
+ EnhancedWithInheritGroup.definitions.get(EnhancedWithInheritGroup.hooks[3][1])[:nested].hooks.to_s.must_equal "[[:on_change, [:sing!]], [:on_delete, [:yell!]]]"
197
198
  end
198
199
 
199
200
  class RemovingInheritGroup < Group
@@ -205,19 +206,19 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
205
206
 
206
207
  # # puts "@@@@@ #{Group.hooks.object_id.inspect}"
207
208
  # # puts "@@@@@ #{EmptyGroup.hooks.object_id.inspect}"
208
- # puts "@@@@@ Group: #{Group.representer_class.representable_attrs.get(:songs).representer_module.hooks.inspect}"
209
- # puts "@@@@@ EnhancedGroup: #{EnhancedGroup.representer_class.representable_attrs.get(:songs).representer_module.hooks.inspect}"
210
- # puts "@@@@@ InheritGroup: #{EnhancedWithInheritGroup.representer_class.representable_attrs.get(:songs).representer_module.hooks.inspect}"
211
- # puts "@@@@@ RemovingGroup: #{RemovingInheritGroup.representer_class.representable_attrs.get(:songs).representer_module.hooks.inspect}"
212
- # # puts "@@@@@ #{EnhancedWithInheritGroup.representer_class.representable_attrs.get(:songs).representer_module.hooks.object_id.inspect}"
209
+ # puts "@@@@@ Group: #{Group.definitions.get(:songs)[:nested].hooks.inspect}"
210
+ # puts "@@@@@ EnhancedGroup: #{EnhancedGroup.definitions.get(:songs)[:nested].hooks.inspect}"
211
+ # puts "@@@@@ InheritGroup: #{EnhancedWithInheritGroup.definitions.get(:songs)[:nested].hooks.inspect}"
212
+ # puts "@@@@@ RemovingGroup: #{RemovingInheritGroup.definitions.get(:songs)[:nested].hooks.inspect}"
213
+ # # puts "@@@@@ #{EnhancedWithInheritGroup.definitions.get(:songs)[:nested].hooks.object_id.inspect}"
213
214
 
214
215
  # TODO: object_id tests for all nested representers.
215
216
 
216
217
  it do
217
218
  Group.hooks.size.must_equal 4
218
219
  RemovingInheritGroup.hooks.size.must_equal 3
219
- RemovingInheritGroup.representer_class.representable_attrs.get(RemovingInheritGroup.hooks[0][1]).representer_module.hooks.to_s.must_equal "[[:on_add, [:reset_song!]]]"
220
- RemovingInheritGroup.representer_class.representable_attrs.get(RemovingInheritGroup.hooks[2][1]).representer_module.hooks.to_s.must_equal "[[:on_change, [:sing!]]]"
220
+ RemovingInheritGroup.definitions.get(RemovingInheritGroup.hooks[0][1])[:nested].hooks.to_s.must_equal "[[:on_add, [:reset_song!]]]"
221
+ RemovingInheritGroup.definitions.get(RemovingInheritGroup.hooks[2][1])[:nested].hooks.to_s.must_equal "[[:on_change, [:sing!]]]"
221
222
  end
222
223
 
223
224
  # Group::clone
data/test/expose_test.rb CHANGED
@@ -16,7 +16,7 @@ class ExposeTest < MiniTest::Spec
16
16
  end
17
17
 
18
18
  class AlbumExpose < Disposable::Expose
19
- from Twin::Album.representer_class
19
+ from Twin::Album.definitions.values
20
20
  end
21
21
 
22
22
  let (:album) { Model::Album.new(1, "Dick Sandwich") }
@@ -59,7 +59,7 @@ class ExposeCompositionTest < MiniTest::Spec
59
59
  end
60
60
 
61
61
  class AlbumComposition < Disposable::Composition
62
- from Twin::Album.representer_class
62
+ from Twin::Album.definitions.values
63
63
  end
64
64
  end
65
65
 
@@ -1,8 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
- require "disposable/twin/schema"
4
-
5
- class SchemaTest < MiniTest::Spec
3
+ class ReschemeTest < MiniTest::Spec
6
4
  module Representer
7
5
  include Representable
8
6
 
@@ -32,80 +30,80 @@ class SchemaTest < MiniTest::Spec
32
30
  end
33
31
 
34
32
  it do
35
- decorator = Disposable::Twin::Schema.from(Representer, superclass: Representable::Decorator,
36
- include: [Hello, Gday, Ciao], # Hello will win over Gday.
33
+ decorator = Disposable::Rescheme.from(Representer, superclass: Representable::Decorator,
34
+ include: [Representable::Hash, Hello, Gday, Ciao], # Hello will win over Gday.
37
35
  options_from: :deserializer,
38
- representer_from: lambda { |nested| nested }
36
+ definitions_from: lambda { |nested| nested.definitions }
39
37
  )
40
38
 
41
39
  # include: works.
42
40
  decorator.new(nil).hello.must_equal "hello"
43
41
  decorator.new(nil).ciao.must_equal "ciao"
44
42
 
45
- decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:parse_filter=>[], :render_filter=>[], :as=>\"id\"}>"
46
- decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :deserializer=>{:skip_parse=>\"skip lambda\"}, :parse_filter=>[], :render_filter=>[], :as=>\"title\", :skip_parse=>\"skip lambda\"}>"
43
+ decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[]}>"
44
+ decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :deserializer=>{:skip_parse=>\"skip lambda\"}, :name=>\"title\", :parse_filter=>[], :render_filter=>[], :skip_parse=>\"skip lambda\"}>"
47
45
 
48
46
  songs = decorator.representable_attrs.get(:songs)
49
47
  options = songs.instance_variable_get(:@options)
50
- nested_extend = options.delete(:extend)
51
- options.inspect.must_equal "{:readable=>false, :deserializer=>{:skip_parse=>\"another lambda\", :music=>true, :writeable=>false}, :parse_filter=>[], :render_filter=>[], :as=>\"songs\", :_inline=>true, :skip_parse=>\"another lambda\", :music=>true, :writeable=>false}"
48
+ options[:nested].extend(Declarative::Inspect)
49
+ options.inspect.must_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}"
52
50
 
53
51
  # nested works.
54
- nested_extend.new(nil).hello.must_equal "hello"
55
- nested_extend.new(nil).ciao.must_equal "ciao"
52
+ options[:nested].new(nil).hello.must_equal "hello"
53
+ options[:nested].new(nil).ciao.must_equal "ciao"
56
54
 
57
- nested_extend.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :parse_filter=>[], :render_filter=>[], :skip_parse=>\"a crazy cool instance method\"}>"
55
+ options[:nested].representable_attrs.get(:name).inspect.must_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\"}>"
58
56
  end
59
57
 
60
58
  # :options_from and :include is optional
61
59
  it do
62
- decorator = Disposable::Twin::Schema.from(Representer, superclass: Representable::Decorator,
63
- representer_from: lambda { |nested| nested }
60
+ decorator = Disposable::Rescheme.from(Representer, superclass: Representable::Decorator, include: [Representable::Hash],
61
+ definitions_from: lambda { |nested| nested.definitions }
64
62
  )
65
63
 
66
- decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:parse_filter=>[], :render_filter=>[], :as=>\"id\"}>"
67
- decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :deserializer=>{:skip_parse=>\"skip lambda\"}, :parse_filter=>[], :render_filter=>[], :as=>\"title\"}>"
64
+ decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[]}>"
65
+ decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :deserializer=>{:skip_parse=>\"skip lambda\"}, :name=>\"title\", :parse_filter=>[], :render_filter=>[]}>"
68
66
  end
69
67
 
70
68
 
71
69
  # :exclude_options allows skipping particular options when copying.
72
70
  it do
73
- decorator = Disposable::Twin::Schema.from(Representer, superclass: Representable::Decorator,
74
- representer_from: lambda { |nested| nested },
71
+ decorator = Disposable::Rescheme.from(Representer, superclass: Representable::Decorator, include: [Representable::Hash],
72
+ definitions_from: lambda { |nested| nested.definitions },
75
73
  exclude_options: [:deserializer]
76
74
  )
77
75
 
78
- decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:parse_filter=>[], :render_filter=>[], :as=>\"id\"}>"
79
- decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :parse_filter=>[], :render_filter=>[], :as=>\"title\"}>"
80
- decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :parse_filter=>[], :render_filter=>[]}>"
76
+ decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[]}>"
77
+ decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :name=>\"title\", :parse_filter=>[], :render_filter=>[]}>"
78
+ decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :name=>\"name\", :parse_filter=>[], :render_filter=>[]}>"
81
79
  end
82
80
 
83
81
 
84
82
  it "::from with block allows customizing every definition and returns representer" do
85
- decorator = Disposable::Twin::Schema.from(Representer,
83
+ decorator = Disposable::Rescheme.from(Representer, include: [Representable::Hash],
86
84
  superclass: Representable::Decorator,
87
- representer_from: lambda { |nested| nested },
85
+ definitions_from: lambda { |nested| nested.definitions },
88
86
  ) { |dfn| dfn.merge!(amazing: true) }
89
87
 
90
- decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:parse_filter=>[], :render_filter=>[], :as=>\"id\", :amazing=>true}>"
91
- decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :parse_filter=>[], :render_filter=>[], :amazing=>true}>"
88
+ decorator.representable_attrs.get(:id).inspect.must_equal "#<Representable::Definition ==>id @options={:name=>\"id\", :parse_filter=>[], :render_filter=>[], :amazing=>true}>"
89
+ decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :name=>\"name\", :parse_filter=>[], :render_filter=>[], :amazing=>true}>"
92
90
  end
93
91
 
94
92
  it "recursive: false only copies first level" do
95
- decorator = Disposable::Twin::Schema.from(Representer,
93
+ decorator = Disposable::Rescheme.from(Representer, include: [Representable::Hash],
96
94
  superclass: Representable::Decorator,
97
- representer_from: lambda { |nested| nested },
95
+ definitions_from: lambda { |nested| nested.definitions },
98
96
  recursive: false,
99
97
  exclude_options: [:deserializer]
100
98
  )
101
99
 
102
- decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :parse_filter=>[], :render_filter=>[], :as=>\"title\"}>"
103
- decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :parse_filter=>[], :render_filter=>[]}>"
100
+ decorator.representable_attrs.get(:title).inspect.must_equal "#<Representable::Definition ==>title @options={:writeable=>false, :name=>\"title\", :parse_filter=>[], :render_filter=>[]}>"
101
+ decorator.representable_attrs.get(:songs).representer_module.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:as=>\"Name\", :deserializer=>{:skip_parse=>\"a crazy cool instance method\"}, :name=>\"name\", :parse_filter=>[], :render_filter=>[]}>"
104
102
  end
105
103
  end
106
104
 
107
105
 
108
- class TwinSchemaTest < MiniTest::Spec
106
+ class TwinReschemeTest < MiniTest::Spec
109
107
  class Artist < Disposable::Twin
110
108
  property :name
111
109
  end
@@ -115,15 +113,15 @@ class TwinSchemaTest < MiniTest::Spec
115
113
  end
116
114
 
117
115
  it do
118
- decorator = Disposable::Twin::Schema.from(Album, superclass: Representable::Decorator,
119
- representer_from: lambda { |nested| nested.representer_class }
116
+ decorator = Disposable::Rescheme.from(Album, superclass: Representable::Decorator, include: [Representable::Hash],
117
+ definitions_from: lambda { |nested| nested.definitions }
120
118
  )
121
119
 
122
120
  artist = decorator.representable_attrs.get(:artist)
123
121
  options = artist.instance_variable_get(:@options)
124
- nested_extend = options.delete(:extend)
125
- options.inspect.must_equal "{:twin=>TwinSchemaTest::Artist, :private_name=>:artist, :parse_filter=>[], :render_filter=>[], :as=>\"artist\"}"
122
+ nested_extend = options[:nested]
123
+ options.extend(Declarative::Inspect).inspect.must_equal "{:private_name=>:artist, :nested=>#<Class:>, :name=>\"artist\", :extend=>#<Class:>, :parse_filter=>[], :render_filter=>[]}"
126
124
  assert nested_extend < Representable::Decorator
127
- nested_extend.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:private_name=>:name, :parse_filter=>[], :render_filter=>[], :as=>\"name\"}>"
125
+ nested_extend.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:private_name=>:name, :name=>\"name\", :parse_filter=>[], :render_filter=>[]}>"
128
126
  end
129
127
  end
data/test/test_helper.rb CHANGED
@@ -1,7 +1,8 @@
1
- require 'disposable'
2
- require 'minitest/autorun'
1
+ require "disposable"
2
+ require "minitest/autorun"
3
3
  require "pp"
4
4
  require "representable/debug"
5
+ require "declarative/testing"
5
6
 
6
7
  class Track
7
8
  def initialize(options={})
@@ -16,13 +16,13 @@ class TwinCollectionTest < MiniTest::Spec
16
16
  class Song < Disposable::Twin
17
17
  property :id # DISCUSS: needed for #save.
18
18
  property :title
19
- property :album, :twin => Album
19
+ # property :album, twin: Album
20
20
  end
21
21
 
22
22
  class Album < Disposable::Twin
23
23
  property :id # DISCUSS: needed for #save.
24
24
  property :name
25
- collection :songs, :twin => lambda { |*| Song }
25
+ collection :songs, twin: Song
26
26
  end
27
27
  end
28
28
 
@@ -62,8 +62,8 @@ class TwinCollectionActiveRecordTest < MiniTest::Spec
62
62
  class Album < Disposable::Twin
63
63
  property :id # DISCUSS: needed for #save.
64
64
  property :name
65
- collection :songs, :twin => lambda { |*| Song }
66
- property :artist, twin: lambda { |*| Artist }
65
+ collection :songs, twin: Twin::Song
66
+ property :artist, twin: Twin::Artist
67
67
 
68
68
  include Sync
69
69
  include Save
@@ -208,7 +208,7 @@ class CollectionUnitTest < MiniTest::Spec
208
208
  Album = Struct.new(:id, :name, :songs, :artist)
209
209
  end
210
210
 
211
- let(:collection) { Disposable::Twin::Collection.new(Disposable::Twin::Twinner.new(Twin::Song.representer_class.representable_attrs.get(:album)), []) }
211
+ let(:collection) { Disposable::Twin::Collection.new(Disposable::Twin::Twinner.new(Twin::Song.definitions.get(:album)), []) }
212
212
 
213
213
  # #insert(index, model)
214
214
  it do
@@ -18,23 +18,19 @@ class FeatureTest < MiniTest::Spec
18
18
  end
19
19
 
20
20
  class AlbumForm < Disposable::Twin
21
- include Setup
22
21
  feature Date
23
22
  property :name
24
23
 
25
24
  collection :songs do
26
- include Setup
27
25
  property :title
28
26
 
29
27
  property :composer do
30
- include Setup
31
28
  feature Instrument
32
29
  property :name
33
30
  end
34
31
  end
35
32
 
36
33
  property :artist do
37
- include Setup
38
34
  property :name
39
35
  end
40
36
  end
@@ -40,8 +40,8 @@ class InheritTest < MiniTest::Spec
40
40
 
41
41
  # definitions are not shared.
42
42
  it do
43
- Twin::Album.representer_class.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:fromage=>:_name, :private_name=>:name, :parse_filter=>[], :render_filter=>[], :as=>\"name\"}>"
44
- Twin::Compilation.representer_class.representable_attrs.get(:name).inspect.must_equal "#<Representable::Definition ==>name @options={:fromage=>:_name, :private_name=>:name, :parse_filter=>[], :render_filter=>[], :as=>\"name\", :writeable=>false, :inherit=>true}>"
43
+ Twin::Album.definitions.get(:name).extend(Declarative::Inspect).inspect.must_equal "#<Disposable::Twin::Definition: @options={:fromage=>:_name, :private_name=>:name, :name=>\"name\"}>"
44
+ Twin::Compilation.definitions.get(:name).extend(Declarative::Inspect).inspect.must_equal "#<Disposable::Twin::Definition: @options={:fromage=>:_name, :private_name=>:name, :name=>\"name\", :writeable=>false}>" # FIXME: where did :inherit go?
45
45
  end
46
46
 
47
47
 
@@ -1,35 +1,35 @@
1
- require "test_helper"
1
+ # require "test_helper"
2
2
 
3
- class ProcessInlineTest < MiniTest::Spec
4
- Album = Struct.new(:artist, :composer, :recursive_composer)
3
+ # class ProcessInlineTest < MiniTest::Spec
4
+ # Album = Struct.new(:artist, :composer, :recursive_composer)
5
5
 
6
- module InlineTwin
7
- end
6
+ # module InlineTwin
7
+ # end
8
8
 
9
- class RecursiveComposerTwin < Disposable::Twin
10
- property :composer, twin: self
11
- end
9
+ # class RecursiveComposerTwin < Disposable::Twin
10
+ # property :composer, twin: self
11
+ # end
12
12
 
13
- class AlbumTwin < Disposable::Twin
14
- def self.process_inline!(inline_class, definition)
15
- inline_class.send :include, InlineTwin
16
- end
13
+ # class AlbumTwin < Disposable::Twin
14
+ # def self.process_inline!(inline_class, definition)
15
+ # inline_class.send :include, InlineTwin
16
+ # end
17
17
 
18
- property :artist do
19
- end
18
+ # property :artist do
19
+ # end
20
20
 
21
- property :composer, twin: ->{ ComposerTwin }
21
+ # property :composer, twin: ->{ ComposerTwin }
22
22
 
23
- property :recursive_composer, twin: RecursiveComposerTwin
24
- end
23
+ # property :recursive_composer, twin: RecursiveComposerTwin
24
+ # end
25
25
 
26
- class ComposerTwin < Disposable::Twin
27
- end
26
+ # class ComposerTwin < Disposable::Twin
27
+ # end
28
28
 
29
- it do
30
- twin = AlbumTwin.new(Album.new(Object, Object))
31
- assert ! (twin.class < InlineTwin)
32
- assert (twin.artist.class < InlineTwin)
33
- assert ! (twin.composer.class < InlineTwin)
34
- end
35
- end
29
+ # it do
30
+ # twin = AlbumTwin.new(Album.new(Object, Object))
31
+ # assert ! (twin.class < InlineTwin)
32
+ # assert (twin.artist.class < InlineTwin)
33
+ # assert ! (twin.composer.class < InlineTwin)
34
+ # end
35
+ # end
@@ -17,7 +17,7 @@ class TwinSetupTest < MiniTest::Spec
17
17
 
18
18
  class Song < Disposable::Twin
19
19
  property :id
20
- property :composer, twin: lambda { |*| Twin::Artist }
20
+ property :composer, twin: Twin::Artist
21
21
 
22
22
  include Setup
23
23
  end
@@ -25,8 +25,8 @@ class TwinSetupTest < MiniTest::Spec
25
25
  class Album < Disposable::Twin
26
26
  property :id
27
27
  property :name
28
- collection :songs, twin: lambda { |*| Twin::Song }
29
- property :artist, twin: lambda { |*| Twin::Artist }
28
+ collection :songs, twin: Twin::Song
29
+ property :artist, twin: Twin::Artist
30
30
 
31
31
  include Setup
32
32
  end
@@ -7,25 +7,24 @@ class TwinTest < MiniTest::Spec
7
7
  Artist = Struct.new(:id)
8
8
  end
9
9
 
10
-
10
+ # test twin: option
11
11
  module Twin
12
+ class Artist < Disposable::Twin
13
+ property :id
14
+
15
+ include Setup
16
+ end
17
+
12
18
  class Album < Disposable::Twin
13
19
  property :id # DISCUSS: needed for #save.
14
20
  property :name
15
- collection :songs, :twin => lambda { |*| Song }
16
- property :artist, :twin => lambda { |*| Artist }
21
+ property :artist, twin: Artist
17
22
  end
18
23
 
19
24
  class Song < Disposable::Twin
20
25
  property :id # DISCUSS: needed for #save.
21
26
  property :title
22
- property :album, :twin => Album
23
- end
24
-
25
- class Artist < Disposable::Twin
26
- property :id
27
-
28
- include Setup
27
+ property :album, twin: Album
29
28
  end
30
29
  end
31
30
 
@@ -91,20 +90,6 @@ class TwinTest < MiniTest::Spec
91
90
  # result.must_equal twin.album
92
91
  # end
93
92
  end
94
-
95
- # FIXME: experimental.
96
- describe "#to_s" do
97
- class HitTwin < Disposable::Twin
98
- include Setup
99
-
100
- property :song do
101
- end
102
- end
103
-
104
- let (:hit) { OpenStruct.new(song: song) }
105
- it { HitTwin.new(hit).to_s.must_match "#<TwinTest::HitTwin:" }
106
- it { HitTwin.new(hit).song.to_s.must_match "#<Twin (inline):" }
107
- end
108
93
  end
109
94
 
110
95
 
@@ -138,7 +123,7 @@ class TwinAsTest < MiniTest::Spec
138
123
 
139
124
  class Song < Disposable::Twin
140
125
  property :name, :from => :title
141
- property :record, :twin => Album, :from => :album
126
+ property :record, twin: Album, :from => :album
142
127
 
143
128
  # model Model::Song
144
129
  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.1.15
4
+ version: 0.2.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-27 00:00:00.000000000 Z
11
+ date: 2015-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uber
@@ -24,26 +24,40 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: declarative
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.4
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: representable
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
32
46
  - !ruby/object:Gem::Version
33
- version: 2.2.3
47
+ version: 2.4.0.rc1
34
48
  - - "<"
35
49
  - !ruby/object:Gem::Version
36
- version: 2.4.0
50
+ version: 2.5.0
37
51
  type: :runtime
38
52
  prerelease: false
39
53
  version_requirements: !ruby/object:Gem::Requirement
40
54
  requirements:
41
55
  - - ">="
42
56
  - !ruby/object:Gem::Version
43
- version: 2.2.3
57
+ version: 2.4.0.rc1
44
58
  - - "<"
45
59
  - !ruby/object:Gem::Version
46
- version: 2.4.0
60
+ version: 2.5.0
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: bundler
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -152,6 +166,7 @@ files:
152
166
  - lib/disposable/callback.rb
153
167
  - lib/disposable/composition.rb
154
168
  - lib/disposable/expose.rb
169
+ - lib/disposable/rescheme.rb
155
170
  - lib/disposable/twin.rb
156
171
  - lib/disposable/twin/builder.rb
157
172
  - lib/disposable/twin/changed.rb
@@ -159,12 +174,10 @@ files:
159
174
  - lib/disposable/twin/collection.rb
160
175
  - lib/disposable/twin/composition.rb
161
176
  - lib/disposable/twin/default.rb
162
- - lib/disposable/twin/option.rb
177
+ - lib/disposable/twin/definitions.rb
163
178
  - lib/disposable/twin/persisted.rb
164
179
  - lib/disposable/twin/property_processor.rb
165
- - lib/disposable/twin/representer.rb
166
180
  - lib/disposable/twin/save.rb
167
- - lib/disposable/twin/schema.rb
168
181
  - lib/disposable/twin/setup.rb
169
182
  - lib/disposable/twin/struct.rb
170
183
  - lib/disposable/twin/sync.rb
@@ -175,6 +188,7 @@ files:
175
188
  - test/example.rb
176
189
  - test/expose_test.rb
177
190
  - test/persisted_test.rb
191
+ - test/rescheme_test.rb
178
192
  - test/skip_getter_test.rb
179
193
  - test/test_helper.rb
180
194
  - test/twin/benchmarking.rb
@@ -193,7 +207,6 @@ files:
193
207
  - test/twin/process_inline_test.rb
194
208
  - test/twin/readable_test.rb
195
209
  - test/twin/save_test.rb
196
- - test/twin/schema_test.rb
197
210
  - test/twin/setup_test.rb
198
211
  - test/twin/skip_unchanged_test.rb
199
212
  - test/twin/struct_test.rb
@@ -217,9 +230,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
217
230
  version: '0'
218
231
  required_rubygems_version: !ruby/object:Gem::Requirement
219
232
  requirements:
220
- - - ">="
233
+ - - ">"
221
234
  - !ruby/object:Gem::Version
222
- version: '0'
235
+ version: 1.3.1
223
236
  requirements: []
224
237
  rubyforge_project:
225
238
  rubygems_version: 2.4.8
@@ -234,6 +247,7 @@ test_files:
234
247
  - test/example.rb
235
248
  - test/expose_test.rb
236
249
  - test/persisted_test.rb
250
+ - test/rescheme_test.rb
237
251
  - test/skip_getter_test.rb
238
252
  - test/test_helper.rb
239
253
  - test/twin/benchmarking.rb
@@ -252,7 +266,6 @@ test_files:
252
266
  - test/twin/process_inline_test.rb
253
267
  - test/twin/readable_test.rb
254
268
  - test/twin/save_test.rb
255
- - test/twin/schema_test.rb
256
269
  - test/twin/setup_test.rb
257
270
  - test/twin/skip_unchanged_test.rb
258
271
  - test/twin/struct_test.rb
@@ -1,12 +0,0 @@
1
- module Disposable::Twin::Option
2
- def self.included(base)
3
- base.extend ClassMethods
4
- end
5
-
6
- module ClassMethods
7
- def option(name, options={})
8
- # default: nil will always set an option in the, even when not in the incoming options.
9
- property(name, options.merge(readable: false, writeable: false, default: nil))
10
- end
11
- end
12
- end
@@ -1,57 +0,0 @@
1
- require "representable/decorator"
2
- # require "representable/hash"
3
-
4
- module Disposable
5
- class Twin
6
- class Decorator < Representable::Decorator
7
- # Overrides representable's Definition class so we can add semantics in our representers.
8
- class Definition < Representable::Definition
9
- def dynamic_options
10
- super + [:twin]
11
- end
12
-
13
- def twin_class
14
- self[:twin].evaluate(nil) # FIXME: do we support the :twin option, and should it be wrapped?
15
- end
16
- end
17
-
18
- # FIXME: this is not properly used when inheriting - fix that in representable.
19
- def self.build_config
20
- Config.new(Definition)
21
- end
22
-
23
- def self.each(options={})
24
- return representable_attrs[:definitions].values unless block_given?
25
-
26
- definitions = representable_attrs
27
-
28
- definitions.each do |dfn|
29
- next if options[:exclude] and options[:exclude].include?(dfn.name)
30
- next if options[:scalar] and dfn[:collection]
31
- next if options[:collection] and ! dfn[:collection]
32
- next if options[:twin] and ! dfn[:twin]
33
-
34
- yield dfn
35
- end
36
-
37
- definitions
38
- end
39
-
40
- def self.default_inline_class
41
- Twin
42
- end
43
-
44
-
45
- class Options < ::Hash
46
- def exclude!(names)
47
- excludes.push(*names)
48
- self
49
- end
50
-
51
- def excludes
52
- self[:exclude] ||= []
53
- end
54
- end
55
- end # Decorator.
56
- end
57
- end