datory 1.0.0.rc1 → 1.0.0.rc3

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
  SHA256:
3
- metadata.gz: 9a373fdef28cc23b1fede6c3c3405e92ca888b832792122bde0c9a2758aab365
4
- data.tar.gz: 962d0fc90e6a130d249800d982176ece5b7e85226979e4e6a94c2a306b1b7a4d
3
+ metadata.gz: 8562a68170d39d6d97a80eceae372d7f043cbb08db2890faa2d6d22a792748bf
4
+ data.tar.gz: 89ef0b5c9a73289a3567e01202a9a83beeaefee6db2f084168c6e755da4e3044
5
5
  SHA512:
6
- metadata.gz: 947b785c440d6fef3672dc82cb25eb8c59e256f881974f32dc50673fe626274d0723b0b8e09c1c24ba4c6714b77eabfbf0a83a3399794dd41b8ef2039426ec3c
7
- data.tar.gz: 9984cdcd0c95f0b3e5de163fe84b46e2275ce7e61c6764fcfcb38e0696832d9922f8313108ec2ae6505a18543ca36ac8c8a87d67cfa4d2f205cd41953aabc59b
6
+ metadata.gz: 3c6ed842a16e265979fc1d5ebc4b517390884bac7118500d39cc48d6b180c7c842b08cadfdf853db111b2a56a8c016cbcbf9654d4b290272399f461d9eec48ba
7
+ data.tar.gz: 6428856321dd65efb127aca09955e5e34eb1d3cff3cdc2f8da0fd669e4556582ecef976919b60f6808ce84a602a9dc60f332ffcc42b0421c613b0dc43d1ff429
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <a href="https://github.com/servactory/datory/releases"><img src="https://img.shields.io/github/release-date/servactory/datory" alt="Release Date"></a>
4
4
  </p>
5
5
 
6
- ## Documentation
6
+ ## Documentation (soon)
7
7
 
8
8
  See [datory.servactory.com](https://datory.servactory.com) for documentation.
9
9
 
@@ -15,6 +15,54 @@ See [datory.servactory.com](https://datory.servactory.com) for documentation.
15
15
  gem "datory"
16
16
  ```
17
17
 
18
+ ### Usage
19
+
20
+ #### Serialize
21
+
22
+ ```ruby
23
+ user = User.find(...)
24
+
25
+ UserDto.serialize(user)
26
+ ```
27
+
28
+ #### Deserialize
29
+
30
+ ```ruby
31
+ UserDto.deserialize(json)
32
+ ```
33
+
34
+ #### Examples
35
+
36
+ ```ruby
37
+ class UserDto < Datory::Base
38
+ string :id
39
+ string :firstname, as: :first_name
40
+ string :lastname, as: :last_name
41
+ string :email
42
+ string :birthDate, as: :birth_date, output: ->(value:) { value.to_s }
43
+
44
+ one :login, include: UserLoginDto
45
+
46
+ many :addresses, include: UserAddressDto
47
+
48
+ string :phone
49
+ string :website
50
+
51
+ one :company, include: UserCompanyDto
52
+ end
53
+ ```
54
+
55
+ ```ruby
56
+ class UserLoginDto < Datory::Base
57
+ string :uuid
58
+ string :username
59
+ string :password
60
+ string :md5
61
+ string :sha1
62
+ string :registered
63
+ end
64
+ ```
65
+
18
66
  ## Contributing
19
67
 
20
68
  This project is intended to be a safe, welcoming space for collaboration.
@@ -4,27 +4,15 @@ module Datory
4
4
  module Attributes
5
5
  class Collection
6
6
  extend Forwardable
7
- def_delegators :@collection, :<<, :each, :map, :merge # :filter, :each, :map, :flat_map, :to_h, :merge, :find
7
+ def_delegators :@collection, :<<, :each, :map, :to_h, :merge
8
8
 
9
9
  def initialize(collection = Set.new)
10
10
  @collection = collection
11
11
  end
12
12
 
13
- # def only(*names)
14
- # Collection.new(filter { |input| names.include?(input.internal_name) })
15
- # end
16
-
17
- # def except(*names)
18
- # Collection.new(filter { |input| !names.include?(input.internal_name) })
19
- # end
20
-
21
13
  def names
22
14
  map(&:name)
23
15
  end
24
-
25
- # def find_by(name:)
26
- # find { |input| input.internal_name == name }
27
- # end
28
16
  end
29
17
  end
30
18
  end
@@ -29,6 +29,11 @@ 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(type: Symbol)
34
+ attribute(name, **options)
35
+ end
36
+
32
37
  def string(name, **options)
33
38
  options = options.merge(type: String)
34
39
  attribute(name, **options)
@@ -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(:as, 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,85 @@
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(:as, attribute.name)
25
+
26
+ input attribute.name,
27
+ as: input_internal_name,
28
+ type: attribute.options.fetch(:type),
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
+ type = attribute.options.fetch(:type, nil)
36
+
37
+ if [Set, Array].include?(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: (
46
+ if (type = attribute.options.fetch(:consists_of, false)) == Hash
47
+ Datory::Result
48
+ else
49
+ type
50
+ end
51
+ ),
52
+ type: if (type = attribute.options.fetch(:type)) == Hash
53
+ Datory::Result
54
+ else
55
+ type
56
+ end
57
+
58
+ make :"assign_#{input_internal_name}_output"
59
+
60
+ define_method(:"assign_#{input_internal_name}_output") do
61
+ outputs.public_send(:"#{input_internal_name}=", inputs.public_send(input_internal_name))
62
+ end
63
+ end
64
+
65
+ # output :model, type: Class
66
+
67
+ # make :assign_model_name
68
+
69
+ # def assign_model_name
70
+ # model_class_name_array = self.class.name.split("::")
71
+ # model_class_name_array.pop
72
+ # model_class_name = model_class_name_array.join("::")
73
+ # model_class = model_class_name.constantize
74
+ #
75
+ # outputs.model = model_class
76
+ # end
77
+ end
78
+
79
+ @model_class.const_set(ServiceBuilder::SERVICE_CLASS_NAME, class_sample)
80
+ end
81
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
82
+ end
83
+ end
84
+ end
85
+ 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
@@ -4,41 +4,21 @@ module Datory
4
4
  module Context
5
5
  module Callable
6
6
  def serialize(model)
7
- hash = {}
8
-
9
- collection_of_attributes.each do |attribute|
10
- internal_name = attribute.options.fetch(:as, attribute.name)
11
- include_class = attribute.options.fetch(:include, nil)
12
- output_formatter = attribute.options.fetch(:output, nil)
13
-
14
- value = model.public_send(internal_name)
15
-
16
- value =
17
- if include_class.present?
18
- type = attribute.options.fetch(:type, nil)
19
-
20
- if [Set, Array].include?(type)
21
- value.map { |item| include_class.serialize(item) }
22
- else
23
- include_class.serialize(value)
24
- end
25
- elsif output_formatter.is_a?(Proc)
26
- output_formatter.call(value: value)
27
- elsif [Date, Time, DateTime].include?(value.class)
28
- value.to_s
29
- else
30
- value
31
- end
32
-
33
- hash[attribute.name] = value
34
- end
35
-
36
- hash
7
+ Datory::Attributes::Serialization::Serializator.serialize(
8
+ model: model,
9
+ collection_of_attributes: collection_of_attributes
10
+ )
37
11
  end
38
12
 
39
13
  def deserialize(json)
40
- hash = JSON.parse(json.to_json)
41
- build(**hash)
14
+ if [Set, Array].include?(json.class)
15
+ json.map do |json_item|
16
+ deserialize(json_item)
17
+ end
18
+ else
19
+ hash = JSON.parse(json.to_json)
20
+ build(**hash)
21
+ end
42
22
  end
43
23
 
44
24
  # def build!(attributes = {})
@@ -5,7 +5,7 @@ module Datory
5
5
  MAJOR = 1
6
6
  MINOR = 0
7
7
  PATCH = 0
8
- PRE = "rc1"
8
+ PRE = "rc3"
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.rc1
4
+ version: 1.0.0.rc3
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