datory 1.0.0.rc2 → 1.0.0.rc4

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: dad592cd7b60ed42e5e729fc785dfcb148abff2e4966194563d943f9e3f66f60
4
- data.tar.gz: 9bffee76ef163ac26529c4a163afa2e1a9cea42da6619381b85d7cd2b5187290
3
+ metadata.gz: 5ca68aea305e426d629f97a3d8940e016a933e4298e56b7ab7d3f9e495fb515d
4
+ data.tar.gz: 3589f41e040965dacdbaa9f22d197c837afd96f6a5d34e6b32b93e2043ce2391
5
5
  SHA512:
6
- metadata.gz: fe6407e48e97f7e2f462e52cc7aba7a1726171f02e9fcd1d774bb36c9b04047abdf7218a3eede1b99023fe38f16d80b7bbec224313ffc229e3695b8bdc6126e3
7
- data.tar.gz: ae3835273961a84951d232afccf50851cade4f9efb5f89c44d8d7cdf55b3804ff6ba983580d4025aa4f6fd28fd4f695d1941fb74833015d3a88852712d4332fa
6
+ metadata.gz: 4b08dcadef0150c3183c5ae1458fdd4de9ddf9a1dd6303c5b7dfa1e104f7c4581826c4876660628879a432263ac4cc87de728d2948a3167dc1dd20c83b6bf176
7
+ data.tar.gz: a19f50f5e2bfe11d3092292ea2e641f546ba78bd2b2eb8efb50769f42d47753c9a6edd46460a6391b4e389c6dcd662cbaf5510f80aa7fd66ab9cf0f3233bb5f0
data/README.md CHANGED
@@ -36,10 +36,10 @@ UserDto.deserialize(json)
36
36
  ```ruby
37
37
  class UserDto < Datory::Base
38
38
  string :id
39
- string :firstname, as: :first_name
40
- string :lastname, as: :last_name
39
+ string :firstname, to: :first_name
40
+ string :lastname, to: :last_name
41
41
  string :email
42
- string :birthDate, as: :birth_date, output: ->(value:) { value.to_s }
42
+ string :birthDate, to: :birth_date, output: ->(value:) { value.to_s }
43
43
 
44
44
  one :login, include: UserLoginDto
45
45
 
@@ -29,42 +29,47 @@ module Datory
29
29
  collection_of_attributes << Attribute.new(name, **options)
30
30
  end
31
31
 
32
+ def symbol(name, **options)
33
+ options = options.merge(from: Symbol)
34
+ attribute(name, **options)
35
+ end
36
+
32
37
  def string(name, **options)
33
- options = options.merge(type: String)
38
+ options = options.merge(from: String)
34
39
  attribute(name, **options)
35
40
  end
36
41
 
37
42
  def integer(name, **options)
38
- options = options.merge(type: Integer)
43
+ options = options.merge(from: Integer)
39
44
  attribute(name, **options)
40
45
  end
41
46
 
42
47
  def float(name, **options)
43
- options = options.merge(type: Float)
48
+ options = options.merge(from: Float)
44
49
  attribute(name, **options)
45
50
  end
46
51
 
47
52
  def date(name, **options)
48
- options = options.merge(type: Date)
53
+ options = options.merge(from: Date)
49
54
  attribute(name, **options)
50
55
  end
51
56
 
52
57
  def time(name, **options)
53
- options = options.merge(type: Time)
58
+ options = options.merge(from: Time)
54
59
  attribute(name, **options)
55
60
  end
56
61
 
57
62
  def datetime(name, **options)
58
- options = options.merge(type: DateTime)
63
+ options = options.merge(from: DateTime)
59
64
  attribute(name, **options)
60
65
  end
61
66
 
62
- def one(name, include:, as: nil)
63
- attribute(name, as: as.presence || name, type: Hash, include: include)
67
+ def one(name, include:, to: nil)
68
+ attribute(name, to: to.presence || name, from: Hash, include: include)
64
69
  end
65
70
 
66
- def many(name, include:, as: nil)
67
- attribute(name, as: as.presence || name, type: Array, consists_of: Hash, include: include)
71
+ def many(name, include:, to: nil)
72
+ attribute(name, to: to.presence || name, from: Array, consists_of: Hash, include: include)
68
73
  end
69
74
 
70
75
  def collection_of_attributes
@@ -0,0 +1,52 @@
1
+ module Datory
2
+ module Attributes
3
+ module Serialization
4
+ class Serializator
5
+ def self.serialize(model:, collection_of_attributes:)
6
+ new(collection_of_attributes: collection_of_attributes).serialize(model: model)
7
+ end
8
+
9
+ def initialize(collection_of_attributes:)
10
+ @collection_of_attributes = collection_of_attributes
11
+ end
12
+
13
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
14
+ def serialize(model:)
15
+ if [Set, Array].include?(model.class)
16
+ model.map do |nested_model|
17
+ serialize(model: nested_model)
18
+ end
19
+ else
20
+ @collection_of_attributes.to_h do |attribute|
21
+ internal_name = attribute.options.fetch(:to, attribute.name)
22
+ include_class = attribute.options.fetch(:include, nil)
23
+ output_formatter = attribute.options.fetch(:output, nil)
24
+
25
+ value = model.public_send(internal_name)
26
+
27
+ value =
28
+ if include_class.present?
29
+ type = attribute.options.fetch(:type, nil)
30
+
31
+ if [Set, Array].include?(type)
32
+ value.map { |item| include_class.serialize(item) }
33
+ else
34
+ include_class.serialize(value)
35
+ end
36
+ elsif output_formatter.is_a?(Proc)
37
+ output_formatter.call(value: value)
38
+ elsif [Date, Time, DateTime].include?(value.class)
39
+ value.to_s
40
+ else
41
+ value
42
+ end
43
+
44
+ [attribute.name, value]
45
+ end
46
+ end
47
+ end
48
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datory
4
+ module Attributes
5
+ module Tools
6
+ class ServiceBuilder
7
+ SERVICE_CLASS_NAME = "Builder"
8
+
9
+ def self.build!(...)
10
+ new(...).build!
11
+ end
12
+
13
+ def initialize(context, incoming_attributes, collection_of_attributes)
14
+ @context = context
15
+ @incoming_attributes = incoming_attributes
16
+ @collection_of_attributes = collection_of_attributes
17
+ end
18
+
19
+ def build!
20
+ ServiceFactory.create(@context.class, @collection_of_attributes)
21
+
22
+ builder_class.call!(**@incoming_attributes)
23
+ end
24
+
25
+ private
26
+
27
+ def builder_class
28
+ "#{@context.class.name}::#{SERVICE_CLASS_NAME}".constantize
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datory
4
+ module Attributes
5
+ module Tools
6
+ class ServiceFactory
7
+ def self.create(...)
8
+ new(...).create
9
+ end
10
+
11
+ def initialize(model_class, collection_of_attributes)
12
+ @model_class = model_class
13
+ @collection_of_attributes = collection_of_attributes
14
+ end
15
+
16
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
17
+ def create
18
+ return if @model_class.const_defined?(ServiceBuilder::SERVICE_CLASS_NAME)
19
+
20
+ collection_of_attributes = @collection_of_attributes
21
+
22
+ class_sample = Class.new(Datory::Service::Builder) do
23
+ collection_of_attributes.each do |attribute| # rubocop:disable Metrics/BlockLength
24
+ input_internal_name = attribute.options.fetch(:to, attribute.name)
25
+
26
+ input attribute.name,
27
+ as: input_internal_name,
28
+ type: attribute.options.fetch(:from),
29
+ required: attribute.options.fetch(:required, true),
30
+ consists_of: attribute.options.fetch(:consists_of, false),
31
+ prepare: (lambda do |value:|
32
+ include_class = attribute.options.fetch(:include, nil)
33
+ return value unless include_class.present?
34
+
35
+ from_type = attribute.options.fetch(:from, nil)
36
+
37
+ if [Set, Array].include?(from_type)
38
+ value.map { |item| include_class.build(**item) }
39
+ else
40
+ include_class.build(**value)
41
+ end
42
+ end)
43
+
44
+ output input_internal_name,
45
+ consists_of: if (consists_of_type = attribute.options.fetch(:consists_of, false)) == Hash
46
+ Datory::Result
47
+ else
48
+ consists_of_type
49
+ end,
50
+ type: if (from_type = attribute.options.fetch(:from)) == Hash
51
+ Datory::Result
52
+ elsif (option_as = attribute.options.fetch(:as, nil)).present?
53
+ option_as
54
+ else
55
+ from_type
56
+ end
57
+
58
+ make :"assign_#{input_internal_name}_output"
59
+
60
+ define_method(:"assign_#{input_internal_name}_output") do
61
+ value = inputs.public_send(input_internal_name)
62
+
63
+ option_as = attribute.options.fetch(:as, nil)
64
+
65
+ if [Date, Time, DateTime].include?(option_as)
66
+ value = option_as.parse(value)
67
+ elsif option_as == String
68
+ value = value.to_s
69
+ elsif option_as == Integer
70
+ value = value.to_i
71
+ elsif option_as == Float
72
+ value = value.to_f
73
+ end
74
+
75
+ outputs.public_send(:"#{input_internal_name}=", value)
76
+ end
77
+ end
78
+
79
+ # output :model, type: Class
80
+
81
+ # make :assign_model_name
82
+
83
+ # def assign_model_name
84
+ # model_class_name_array = self.class.name.split("::")
85
+ # model_class_name_array.pop
86
+ # model_class_name = model_class_name_array.join("::")
87
+ # model_class = model_class_name.constantize
88
+ #
89
+ # outputs.model = model_class
90
+ # end
91
+ end
92
+
93
+ @model_class.const_set(ServiceBuilder::SERVICE_CLASS_NAME, class_sample)
94
+ end
95
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
96
+ end
97
+ end
98
+ end
99
+ end
@@ -3,76 +3,12 @@
3
3
  module Datory
4
4
  module Attributes
5
5
  module Workspace
6
- class ServiceFactory
7
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
8
- def self.create(model_class, class_name, collection_of_attributes)
9
- return if model_class.const_defined?(class_name)
10
-
11
- class_sample = Class.new(Datory::Service::Builder) do
12
- collection_of_attributes.each do |attribute| # rubocop:disable Metrics/BlockLength
13
- input_internal_name = attribute.options.fetch(:as, attribute.name)
14
-
15
- input attribute.name,
16
- as: input_internal_name,
17
- type: attribute.options.fetch(:type),
18
- required: attribute.options.fetch(:required, true),
19
- consists_of: attribute.options.fetch(:consists_of, false),
20
- prepare: (lambda do |value:|
21
- include_class = attribute.options.fetch(:include, nil)
22
- return value unless include_class.present?
23
-
24
- type = attribute.options.fetch(:type, nil)
25
-
26
- if [Set, Array].include?(type)
27
- value.map { |item| include_class.build(**item) }
28
- else
29
- include_class.build(**value)
30
- end
31
- end)
32
-
33
- output input_internal_name,
34
- consists_of: (
35
- if (type = attribute.options.fetch(:consists_of, false)) == Hash
36
- Datory::Result
37
- else
38
- type
39
- end
40
- ),
41
- type: if (type = attribute.options.fetch(:type)) == Hash
42
- Datory::Result
43
- else
44
- type
45
- end
46
-
47
- make :"assign_#{input_internal_name}_output"
48
-
49
- define_method(:"assign_#{input_internal_name}_output") do
50
- outputs.public_send(:"#{input_internal_name}=", inputs.public_send(input_internal_name))
51
- end
52
- end
53
- end
54
-
55
- model_class.const_set(class_name, class_sample)
56
- end
57
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
58
- end
59
-
60
6
  private
61
7
 
62
8
  def build!(incoming_attributes:, collection_of_attributes:, **)
63
9
  super
64
10
 
65
- builder_class_name = "GBuilder"
66
-
67
- ServiceFactory.create(self.class, builder_class_name, collection_of_attributes)
68
-
69
- builder_class = "#{self.class.name}::#{builder_class_name}".constantize
70
-
71
- builder_class.call!(**incoming_attributes)
72
-
73
- # Tools::Unnecessary.find!(self, attributes, collection_of_attributes)
74
- # Tools::Rules.check!(self, collection_of_attributes)
75
- # Tools::Validation.validate!(self, attributes, collection_of_attributes)
11
+ Tools::ServiceBuilder.build!(self, incoming_attributes, collection_of_attributes)
76
12
  end
77
13
  end
78
14
  end
@@ -3,42 +3,12 @@
3
3
  module Datory
4
4
  module Context
5
5
  module Callable
6
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
7
6
  def serialize(model)
8
- if [Set, Array].include?(model.class)
9
- model.map do |model_item|
10
- serialize(model_item)
11
- end
12
- else
13
- collection_of_attributes.to_h do |attribute|
14
- internal_name = attribute.options.fetch(:as, attribute.name)
15
- include_class = attribute.options.fetch(:include, nil)
16
- output_formatter = attribute.options.fetch(:output, nil)
17
-
18
- value = model.public_send(internal_name)
19
-
20
- value =
21
- if include_class.present?
22
- type = attribute.options.fetch(:type, nil)
23
-
24
- if [Set, Array].include?(type)
25
- value.map { |item| include_class.serialize(item) }
26
- else
27
- include_class.serialize(value)
28
- end
29
- elsif output_formatter.is_a?(Proc)
30
- output_formatter.call(value: value)
31
- elsif [Date, Time, DateTime].include?(value.class)
32
- value.to_s
33
- else
34
- value
35
- end
36
-
37
- [attribute.name, value]
38
- end
39
- end
7
+ Datory::Attributes::Serialization::Serializator.serialize(
8
+ model: model,
9
+ collection_of_attributes: collection_of_attributes
10
+ )
40
11
  end
41
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
42
12
 
43
13
  def deserialize(json)
44
14
  if [Set, Array].include?(json.class)
@@ -5,7 +5,7 @@ module Datory
5
5
  MAJOR = 1
6
6
  MINOR = 0
7
7
  PATCH = 0
8
- PRE = "rc2"
8
+ PRE = "rc4"
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
11
11
  end
data/lib/datory.rb CHANGED
@@ -4,7 +4,7 @@ require "zeitwerk"
4
4
 
5
5
  require "active_support/all"
6
6
 
7
- require "uri"
7
+ require "servactory"
8
8
 
9
9
  loader = Zeitwerk::Loader.for_gem
10
10
  loader.inflector.inflect(
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datory
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc2
4
+ version: 1.0.0.rc4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Sokolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-21 00:00:00.000000000 Z
11
+ date: 2024-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -48,16 +48,16 @@ dependencies:
48
48
  name: servactory
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - ">="
51
+ - - '='
52
52
  - !ruby/object:Gem::Version
53
- version: '2.4'
53
+ version: 2.5.0.rc2
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - ">="
58
+ - - '='
59
59
  - !ruby/object:Gem::Version
60
- version: '2.4'
60
+ version: 2.5.0.rc2
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: zeitwerk
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -199,6 +199,9 @@ files:
199
199
  - lib/datory/attributes/attribute.rb
200
200
  - lib/datory/attributes/collection.rb
201
201
  - lib/datory/attributes/dsl.rb
202
+ - lib/datory/attributes/serialization/serializator.rb
203
+ - lib/datory/attributes/tools/service_builder.rb
204
+ - lib/datory/attributes/tools/service_factory.rb
202
205
  - lib/datory/attributes/workspace.rb
203
206
  - lib/datory/base.rb
204
207
  - lib/datory/context/callable.rb