entity_schema 0.1.1 → 0.1.2

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
  SHA256:
3
- metadata.gz: 175e615c64727f0402ec59b48af5500e84138f10c545f1da46463329d877e538
4
- data.tar.gz: 7333bf377c6e6027565d2ff7a1dbf0083f56043db6529e6127df3f7519bd972a
3
+ metadata.gz: eb6af17a67827a528cf8e5ed2bd486bec9454cfb615e0165fbb324391b9edebb
4
+ data.tar.gz: a09a8843994a3417b06fc484b78d90266b9354e5853b32ec48cf7bdeda3f3fad
5
5
  SHA512:
6
- metadata.gz: 20945880185e2307906a80acc9b20ab28e0b3510fcb984c0dd40f7e569166d7d1b8608df5393c645fe046f556f645ff4954ac720b14b183d1da7a31f7065aeb6
7
- data.tar.gz: acaefb4a8fbe2d7cfd450e03354938a5022604822a3553e083434ac6041a5a46c8a9d44b018be073758226608a8a3fec3563478f57406598e7f630ffb95c1941
6
+ metadata.gz: 981e2337ac115f3bf97f734a5f42fdcdbb0cf1bd217f195db591e9fa79009a06fe9d9b73d8c0f59778a5729d324efaf619584a45e0e4ed609ecdd8f4c0942638
7
+ data.tar.gz: 1b46da351f08c9208fa4c023c5c01a9f619713cc720e2b71c42c80f22a738329798874750cd970a8606a4be518eaccfd83d909ba2f4ad843f72f98dc18344d19
data/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.1.2]
8
+ ### Added
9
+ + added `.object serializer:` and `mapper:` options
10
+ + options `.object serializer:` and `mapper:` can receive `Symbol`, that will be substituted
11
+ to defined by user _class-level methods_
12
+
13
+ ### Refactored
14
+ + serialization of objects
15
+ + mapping of objects
16
+ + interface of Schema extending from parent schema
17
+ + "unknown field" checking (now, without additional 'if')
18
+
7
19
  ## [0.1.1]
8
20
  ### Added (development-only)
9
21
  + SimpleCov
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- entity_schema (0.1.1)
4
+ entity_schema (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -17,7 +17,7 @@ module EntitySchema
17
17
  "`#{Schema}`, but returns a `#{superschema.class}`"
18
18
  end
19
19
 
20
- Schema.new(owner_name: to_s).extends(superschema)
20
+ Schema.new(owner_name: to_s, extends: superschema)
21
21
  else
22
22
  Schema.new(owner_name: to_s)
23
23
  end
@@ -11,28 +11,28 @@ module EntitySchema
11
11
  module Dsl
12
12
  include DslHelper
13
13
 
14
- def property(name, **opts)
15
- setup_field Fields::Builders::Property.(name, to_s, opts)
16
- end
17
-
18
14
  def property?(name, **opts)
19
15
  property(name, opts.merge!(predicate: true))
20
16
  end
21
17
 
18
+ def property(name, **opts)
19
+ setup_field Fields::Builders::Property.(name, self, opts)
20
+ end
21
+
22
22
  def object(name, **opts)
23
- setup_field Fields::Builders::Object.(name, to_s, opts)
23
+ setup_field Fields::Builders::Object.(name, self, opts)
24
24
  end
25
25
 
26
26
  alias has_one object
27
27
 
28
28
  def collection(name, **opts)
29
- setup_field Fields::Builders::Collection.(name, to_s, opts)
29
+ setup_field Fields::Builders::Collection.(name, self, opts)
30
30
  end
31
31
 
32
32
  alias has_many collection
33
33
 
34
34
  def belongs_to(name, **opts)
35
- fk, object = Fields::Builders::BelongsTo.(name, to_s, opts)
35
+ fk, object = Fields::Builders::BelongsTo.(name, self, opts)
36
36
  setup_field object
37
37
  setup_field fk
38
38
  end
@@ -7,6 +7,14 @@ module EntitySchema
7
7
  module Fields
8
8
  module Builders
9
9
  # TODO: doc
10
+ # Todo: refactor overweight class:
11
+ # Responsibilities:
12
+ # - options with strict contract and meaningfull exceptions,
13
+ # - options transformation,
14
+ # - building object,
15
+ # building default mappers/serializers
16
+ # refactor to Specification, Builder,
17
+ # or to ParamsObject, Specification, Builder
10
18
  class Abstract
11
19
  include Singleton
12
20
 
@@ -14,11 +22,11 @@ module EntitySchema
14
22
  instance.call(*args)
15
23
  end
16
24
 
17
- def call(name, owner_name, options)
18
- options = options.dup
19
- opts = extract_options(options)
25
+ def call(name, owner, options)
26
+ options = substitute_callable_with_methods(options, owner)
27
+ opts = extract_options(options)
20
28
  guard_unknown_options!(options, name)
21
- create_field(name, owner_name, opts)
29
+ create_field(name, owner, opts)
22
30
  end
23
31
 
24
32
  private
@@ -32,8 +40,8 @@ module EntitySchema
32
40
  }
33
41
  end
34
42
 
35
- def create_field(name, owner_name, opts)
36
- field_klass.new(name, owner_name, **create_field_params(opts, name))
43
+ def create_field(name, owner, opts)
44
+ field_klass.new(name, owner.to_s, **create_field_params(opts, name))
37
45
  end
38
46
 
39
47
  # rubocop:disable Metrics/AbcSize:
@@ -52,6 +60,14 @@ module EntitySchema
52
60
  end
53
61
  # :nocov:
54
62
 
63
+ # TODO: test #substitute_callable_with_methods
64
+ def substitute_callable_with_methods(options, owner)
65
+ options.dup.tap do |opts|
66
+ opts[:serializer] = owner.method(opts[:serializer]) if opts[:serializer].is_a?(Symbol)
67
+ opts[:mapper] = owner.method(opts[:mapper]) if opts[:mapper].is_a?(Symbol)
68
+ end
69
+ end
70
+
55
71
  # Helpers
56
72
 
57
73
  # rubocop:disable Naming/UncommunicativeMethodParamName
@@ -7,30 +7,46 @@ module EntitySchema
7
7
  module Fields
8
8
  module Builders
9
9
  # TODO: doc
10
-
11
10
  class Object < Abstract
12
11
  private
13
12
 
14
13
  # rubocop:disable Naming/UncommunicativeMethodParamName
15
14
  def extract_options(h)
16
15
  super.merge!(
17
- mapper: check_ducktype!(:mapper, h, [:call]),
18
- map_to: check!(:map_to, h, [Class]),
19
- map_method: check!(:map_method, h, [Symbol, nil]),
20
- serialize_method: check!(:serialize, h, [Symbol, nil]),
21
- serializer: check_ducktype!(:serializer, h, [:call])
16
+ mapper: check_ducktype!(:mapper, h, [:call]),
17
+ map_to: check!(:map_to, h, [Class, nil]),
18
+ map_method: check!(:map_method, h, [Symbol, nil]),
19
+ serializer: check_ducktype!(:serializer, h, [:call]),
20
+ serialize: check!(:serialize, h, [Symbol, nil])
22
21
  )
23
22
  end
24
23
  # rubocop:enable Naming/UncommunicativeMethodParamName
25
24
 
26
- def create_field_params(o, name)
25
+ # TODO: test default_mapper, :mapper, :serializer
26
+ def create_field_params(opts, name)
27
27
  super.merge!(
28
- map_to: o[:map_to],
29
- map_method: o[:map_method] || :new,
30
- serialize_method: o[:serialize_method] || :to_h
28
+ mapper: first_of(opts[:mapper], build_mapper(opts), default_mapper),
29
+ serializer: first_of(opts[:serializer], build_serializer(opts))
31
30
  )
32
31
  end
33
32
 
33
+ def build_mapper(opts)
34
+ return if opts[:map_to].nil?
35
+
36
+ map_to = opts[:map_to]
37
+ map_method = opts[:map_method] || :new
38
+ ->(hash) { map_to.public_send(map_method, hash) }
39
+ end
40
+
41
+ def default_mapper
42
+ ->(hash) { hash }
43
+ end
44
+
45
+ def build_serializer(opts)
46
+ map_method = opts[:serialize] || :to_h
47
+ ->(object) { object.public_send(map_method) }
48
+ end
49
+
34
50
  def field_klass
35
51
  Fields::Object
36
52
  end
@@ -21,14 +21,12 @@ module EntitySchema
21
21
 
22
22
  private
23
23
 
24
- attr_reader :serialize_method
25
-
26
- def map(tuples)
27
- tuples.map { |tuple| map_to.public_send(map_method, tuple) }
24
+ def map(hashes)
25
+ hashes.map { |hash| super(hash) }
28
26
  end
29
27
 
30
28
  def unwrap(objects)
31
- objects.map { |obj| obj.public_send(serialize_method) }
29
+ objects.map { |object| super(object) }
32
30
  end
33
31
  end
34
32
  end
@@ -5,9 +5,8 @@ module EntitySchema
5
5
  # TODO: doc
6
6
  class Object < Abstract
7
7
  def initialize(name, schema, options)
8
- @map_to = options.delete(:map_to)
9
- @map_method = options.delete(:map_method)
10
- @serialize_method = options.delete(:serialize_method)
8
+ @mapper = options.delete(:mapper)
9
+ @serializer = options.delete(:serializer)
11
10
  super(name, schema, options)
12
11
  guard_unknown_options!(options)
13
12
  end
@@ -21,15 +20,19 @@ module EntitySchema
21
20
  return unless given?(obj)
22
21
  value = read(obj)
23
22
  return output[src_key] = value if value.is_a?(Hash)
24
- output[src_key] = value.public_send(serialize_method)
23
+ output[src_key] = unwrap(value)
25
24
  end
26
25
 
27
26
  private
28
27
 
29
- attr_reader :map_to, :map_method, :serialize_method
28
+ attr_reader :mapper, :serializer
30
29
 
31
- def map(tuple)
32
- map_to.public_send(map_method, tuple)
30
+ def map(hash)
31
+ mapper.call(hash)
32
+ end
33
+
34
+ def unwrap(object)
35
+ serializer.call(object)
33
36
  end
34
37
  end
35
38
  end
@@ -5,17 +5,16 @@ module EntitySchema
5
5
  class Schema
6
6
  attr_reader :owner_name
7
7
 
8
- def initialize(owner_name:)
8
+ def initialize(owner_name:, extends: nil)
9
9
  @owner_name = owner_name
10
- @fields = {}
11
- @fields_by_key = {}
12
- end
13
10
 
14
- def extends(other)
15
- raise 'Cant extend not empty Schema' if fields.any?
16
- @fields.merge! other.fields
17
- @fields_by_key.merge! other.fields_by_key
18
- self
11
+ if extends
12
+ @fields = extends.fields
13
+ @fields_by_key = extends.fields_by_key
14
+ else
15
+ @fields = new_strict_hash
16
+ @fields_by_key = {}
17
+ end
19
18
  end
20
19
 
21
20
  def add_field(field)
@@ -28,12 +27,10 @@ module EntitySchema
28
27
  end
29
28
 
30
29
  def public_set(obj, name, value)
31
- guard_unknown_field!(name)
32
30
  fields[name].public_set(obj, value)
33
31
  end
34
32
 
35
33
  def public_get(obj, name)
36
- guard_unknown_field!(name)
37
34
  fields[name].public_get(obj)
38
35
  end
39
36
 
@@ -46,12 +43,11 @@ module EntitySchema
46
43
  end
47
44
 
48
45
  def given?(obj, name)
49
- guard_unknown_field!(name)
50
46
  fields[name].given?(obj)
51
47
  end
52
48
 
53
49
  def weak_given?(obj, name)
54
- fields[name]&.given?(obj)
50
+ fields.fetch(name, nil)&.given?(obj)
55
51
  end
56
52
 
57
53
  # TODO: use it
@@ -69,9 +65,8 @@ module EntitySchema
69
65
 
70
66
  private
71
67
 
72
- def guard_unknown_field!(name)
73
- return if field?(name)
74
- raise NameError, "Unknown field '#{name}' for `#{owner_name}`"
68
+ def new_strict_hash
69
+ Hash.new { |_, key| raise NameError, "Unknown field '#{key}' for `#{owner_name}`" }
75
70
  end
76
71
  end
77
72
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EntitySchema
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entity_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Captain Philipp
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-20 00:00:00.000000000 Z
11
+ date: 2018-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler