Skip to content
11 changes: 11 additions & 0 deletions examples/usual/example1/season.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,22 @@ class Season < Datory::Base
# uuid! :serialId, to: :serial_id

integer! :number
string! :code

# many! :episodes, include: Episode

date! :premieredOn, to: :premiered_on
date? :endedOn, to: :ended_on

# deserialize
getter :code do |attributes:|
"s#{attributes.fetch(:number)}"
end

# serialize
setter :code do |attributes:|
"s#{attributes.fetch(:number)}"
end
end
end
end
11 changes: 11 additions & 0 deletions examples/usual/example2/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,24 @@ class Product < Datory::Base
uuid! :id

string! :title
string! :formattedTitle, to: :formatted_title

money! :price
money? :discount

integer! :quantity, min: 1, max: 10

duration? :installmentDuration, to: :installment_duration

# deserialize
getter :formattedTitle do |attributes:|
"The New #{attributes.fetch(:title)} (from getter)"
end

# serialize
setter :formatted_title do |attributes:|
"The New #{attributes.fetch(:title)} (from setter)"
end
end
end
end
16 changes: 16 additions & 0 deletions examples/usual/example3/language.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Language < Datory::Base
uuid! :id

string! :name
string? :fullName, to: :full_name

# TODO: Need to prepare this example:
# {
Expand All @@ -32,6 +33,21 @@ class Language < Datory::Base
one? :lastEOLVersion, to: :last_eol, include: Version

many? :previousVersions, to: :previous, include: Version

# deserialize
getter :fullName do |**|
nil
end

# serialize
setter :full_name do |attributes:|
language_name = attributes.fetch(:name)
current_version_name = attributes.dig(:current, :name)

next language_name if current_version_name.blank?

"#{language_name} (#{current_version_name})"
end
end
end
end
4 changes: 4 additions & 0 deletions lib/datory/attributes/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def internal_names
map { |attribute| attribute.to.name }
end

def external_names
map { |attribute| attribute.from.name }
end

def include_class_exist?
@include_class_exist ||= filter do |attribute| # rubocop:disable Performance/Count
include_class = attribute.to.include_class
Expand Down
5 changes: 4 additions & 1 deletion lib/datory/attributes/descriptor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ def describe(service_class_name:, collection_of_attributes:) # rubocop:disable M
row << attribute.from.type
row << attribute.to.name
row << attribute.to.type
row << (include_class if include_class <= Datory::Base) if collection_of_attributes.include_class_exist?

if collection_of_attributes.include_class_exist? && !include_class.nil?
row << (include_class if include_class.respond_to?(:<=) && include_class <= Datory::Base)
end

rows << row
end
Expand Down
29 changes: 23 additions & 6 deletions lib/datory/attributes/serialization/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ def self.to_hash(...)
new.to_hash(...)
end

def prepare(data)
def prepare(data, collection_of_attributes)
if data.is_a?(Hash)
build(data.deep_dup)
build(collection_of_attributes, data.deep_dup)
else
data
end
Expand All @@ -28,17 +28,34 @@ def to_hash(data)
end
end

def build(attributes = {}) # rubocop:disable Metrics/MethodLength
attributes.each do |key, value|
private

def define_setter(key, value)
self.class.send(:attr_accessor, key)

instance_variable_set(:"@#{key}", value)

self
end

def build(collection_of_attributes, attributes = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
additional_attributes = collection_of_attributes.internal_names.difference(attributes.keys).to_h do |key|
[key, nil]
end

attributes.merge(additional_attributes).each do |key, value|
self.class.send(:attr_accessor, key)

instance_variable_set(:"@#{key}", value)

if value.is_a?(Array)
value.map! { |item| Datory::Attributes::Serialization::Model.prepare(item) }
value.map! { |item| Datory::Attributes::Serialization::Model.prepare(item, collection_of_attributes) }
instance_variable_set(:"@#{key}", value)
elsif value.is_a?(Hash)
instance_variable_set(:"@#{key}", Datory::Attributes::Serialization::Model.prepare(value))
instance_variable_set(
:"@#{key}",
Datory::Attributes::Serialization::Model.prepare(value, collection_of_attributes)
)
else
instance_variable_set(:"@#{key}", value)
end
Expand Down
4 changes: 2 additions & 2 deletions lib/datory/attributes/workspace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Attributes
module Workspace
private

def serialize(model:, collection_of_attributes:)
def serialize(model:, collection_of_attributes:, **)
super

return nil if model.nil? # NOTE: When `one` is optional and not passed
Expand All @@ -18,7 +18,7 @@ def serialize(model:, collection_of_attributes:)
)
end

def deserialize(incoming_attributes:, collection_of_attributes:)
def deserialize(incoming_attributes:, collection_of_attributes:, **)
super

Deserialization::ServiceBuilder.build!(self, incoming_attributes, collection_of_attributes)
Expand Down
2 changes: 2 additions & 0 deletions lib/datory/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Datory
class Base
include Info::DSL
include Context::DSL
include Getters::DSL
include Setters::DSL
include Attributes::DSL
end
end
17 changes: 13 additions & 4 deletions lib/datory/context/callable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def serialize(model) # rubocop:disable Metrics/MethodLength
end
else
context = send(:new, _datory_to_model: false)
model = Datory::Attributes::Serialization::Model.prepare(model)
model = Datory::Attributes::Serialization::Model.prepare(model, collection_of_attributes)
_serialize(context, model)
end
rescue Datory::Service::Exceptions::Input,
Expand All @@ -23,7 +23,7 @@ def serialize(model) # rubocop:disable Metrics/MethodLength
raise Datory::Exceptions::SerializationError.new(message: e.message)
end

def deserialize(data) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
def deserialize(data) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity
prepared_data =
if data.is_a?(Datory::Base)
Datory::Attributes::Serialization::Model.to_hash(data)
Expand All @@ -40,6 +40,13 @@ def deserialize(data) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
else
context = send(:new, _datory_to_model: false)

additional_attributes =
collection_of_attributes.external_names.difference(prepared_data.symbolize_keys.keys).to_h do |key|
[key, nil]
end

prepared_data = prepared_data.merge(additional_attributes)

_deserialize(context, **prepared_data)
end
rescue Datory::Service::Exceptions::Input,
Expand Down Expand Up @@ -96,15 +103,17 @@ def _serialize(context, model)
context.send(
:_serialize,
model: model,
collection_of_attributes: collection_of_attributes
collection_of_attributes: collection_of_attributes,
collection_of_setters: collection_of_setters
)
end

def _deserialize(context, **attributes)
context.send(
:_deserialize,
incoming_attributes: attributes.symbolize_keys,
collection_of_attributes: collection_of_attributes
collection_of_attributes: collection_of_attributes,
collection_of_getters: collection_of_getters
)
end

Expand Down
18 changes: 14 additions & 4 deletions lib/datory/context/workspace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ module Context
module Workspace
private

def define_setter(key, value)
self.class.send(:attr_accessor, key)

instance_variable_set(:"@#{key}", value)

self
end

def merge!(attributes)
attributes.each do |key, value|
instance_variable_set(:"@#{key}", value)
Expand All @@ -19,17 +27,19 @@ def keys
instance_variables.map { |instance_variable| instance_variable.to_s.sub(/^@/, "").to_sym }
end

def _serialize(model:, collection_of_attributes:)
def _serialize(model:, collection_of_attributes:, collection_of_setters:)
serialize(
model: model,
collection_of_attributes: collection_of_attributes
collection_of_attributes: collection_of_attributes,
collection_of_setters: collection_of_setters
)
end

def _deserialize(incoming_attributes:, collection_of_attributes:)
def _deserialize(incoming_attributes:, collection_of_attributes:, collection_of_getters:)
deserialize(
incoming_attributes: incoming_attributes,
collection_of_attributes: collection_of_attributes
collection_of_attributes: collection_of_attributes,
collection_of_getters: collection_of_getters
)
end

Expand Down
14 changes: 14 additions & 0 deletions lib/datory/getters/collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Datory
module Getters
class Collection
extend Forwardable
def_delegators :@collection, :<<, :each, :merge

def initialize(collection = Set.new)
@collection = collection
end
end
end
end
30 changes: 30 additions & 0 deletions lib/datory/getters/dsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Datory
module Getters
module DSL
def self.included(base)
base.extend(ClassMethods)
base.include(Workspace)
end

module ClassMethods
def inherited(child)
super

child.send(:collection_of_getters).merge(collection_of_getters)
end

private

def getter(name)
collection_of_getters << Getter.new(name, ->(attributes:) { yield(attributes: attributes) })
end

def collection_of_getters
@collection_of_getters ||= Collection.new
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/datory/getters/getter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Datory
module Getters
class Getter
attr_reader :name, :block

def initialize(name, block)
@name = name
@block = block
end
end
end
end
17 changes: 17 additions & 0 deletions lib/datory/getters/workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module Datory
module Getters
module Workspace
private

def deserialize(incoming_attributes:, collection_of_attributes:, collection_of_getters:)
super

collection_of_getters.each do |getter|
incoming_attributes.merge!(getter.name => getter.block.call(attributes: incoming_attributes))
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/datory/setters/collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Datory
module Setters
class Collection
extend Forwardable
def_delegators :@collection, :<<, :each, :merge

def initialize(collection = Set.new)
@collection = collection
end
end
end
end
30 changes: 30 additions & 0 deletions lib/datory/setters/dsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Datory
module Setters
module DSL
def self.included(base)
base.extend(ClassMethods)
base.include(Workspace)
end

module ClassMethods
def inherited(child)
super

child.send(:collection_of_setters).merge(collection_of_setters)
end

private

def setter(name)
collection_of_setters << Setter.new(name, ->(attributes:) { yield(attributes: attributes) })
end

def collection_of_setters
@collection_of_setters ||= Collection.new
end
end
end
end
end
Loading