Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,13 @@ some_object.age
# => Schema::Attribute::TypeError
```

## Schema::DataStructure
## Building from Hash Data

The `DataStructure` module is a specialization of `Schema` that augments the receiver with operations that are useful when implementing typical applicative code.

When `Schema::DataStructure` is included in a class, the class method `build` is defined on the class.

The `build` method allows the class to be constructed from a hash of values whose keys correspond to the object's attribute names.
The `Schema` module includes a `build` class method that allows construction from a hash of values whose keys correspond to the object's attribute names.

```ruby
class SomeClass
include Schema::DataStructure
include Schema

attribute :name, String
attribute :amount, Numeric
Expand Down Expand Up @@ -336,22 +332,22 @@ A message that has nested objects that aren't just primitive values requires spe

### Input Data

A Schema::DataStructure that implements the `transform_read(data)` method can intercept the input data that the class is constructed with. The data can be modified and customized by this method, and the object's attributes can be manipulated.
A Schema that implements the `transform_read(data)` method can intercept the input data that the class is constructed with. The data can be modified and customized by this method, and the object's attributes can be manipulated.

Note that the read stage of construction of a data structure from hash data happens before the input hash's attributes are assigned to the object.

To affect changes to the input data, the `transform_read` method implementation must directly modify the hash data that the method receives as an argument.

```ruby
class Address
include Schema::DataStructure
include Schema

attribute :city, String
attribute :state, String
end

class SomeClass
include Schema::DataStructure
include Schema

attribute :name, String
attribute :address, Address
Expand All @@ -367,22 +363,22 @@ The `transform_read` method is also aliased to `transform_in`.

### Output Data

A Schema::DataStructure that implements the `transform_write(data)` method can intercept the output data that the object outputs when either `to_h` or `attributes` is invoked. The data can be modified and customized by this method.
A Schema that implements the `transform_write(data)` method can intercept the output data that the object outputs when either `to_h` or `attributes` is invoked. The data can be modified and customized by this method.

Note that the write stage of converting a data structure to a hash happens after the object's attributes have been converted to a hash but just before the hash data is returned to the receiver.

To affect changes to the output data, the `transform_write` method implementation must directly modify the hash data that the method receives as an argument. Changes made to the argument have no effect on the state of the data structure object itself.

```ruby
class Address
include Schema::DataStructure
include Schema

attribute :city, String
attribute :state, String
end

class SomeClass
include Schema::DataStructure
include Schema

attribute :name, String
attribute :address, Address
Expand Down Expand Up @@ -441,7 +437,7 @@ some_object.raw_attributes

### Shallow Copy

A shallow copy duplicate of a `Schema::DataStructure` instance can be be created using the `dup` method.
A shallow copy duplicate of a `Schema` instance can be be created using the `dup` method.

```ruby
class SomeClass
Expand Down Expand Up @@ -472,7 +468,7 @@ duplicate.name

### Deep Copy

The `dup` method doesn't create a deep copy by default. A duplicate of an instance of `Schema::DataStructure` whose attributes have references to instances of complex types rather than just simple primitives will share the references to those complex types with the original instance.
The `dup` method doesn't create a deep copy by default. A duplicate of an instance of `Schema` whose attributes have references to instances of complex types rather than just simple primitives will share the references to those complex types with the original instance.

As with the [transformation](#intercepting-and-modifying-input-and-output-data) of attributes, deep copy behavior can be implemented by implementing the `transform_read` and `transform_write` methods in order to replace attribute values that are instances of complex types with entirely new instances.

Expand Down
1 change: 0 additions & 1 deletion lib/schema/controls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@
require 'schema/controls/attribute'
require 'schema/controls/schema'
require 'schema/controls/schema/different'
require 'schema/controls/data_structure'
require 'schema/controls/comparison'
require 'schema/controls/comparison/entry'
130 changes: 0 additions & 130 deletions lib/schema/controls/data_structure.rb

This file was deleted.

101 changes: 101 additions & 0 deletions lib/schema/controls/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,107 @@ module Validator
end
end
end

module ExtraAttributes
def self.data
{
:some_attribute => Schema.some_attribute,
:some_other_attribute => some_other_attribute
}
end

def self.some_other_attribute
Attribute::Value.some_other_attribute
end

class Example
include ::Schema
attribute :some_attribute
end
end


module ConfigureDependencies
def self.example
Example.build
end

class Example
include ::Schema

attr_accessor :some_dependency

def configure
self.some_dependency = :set
end
end
end

module ReadAndWrite
def self.example
example = Example.new
example.some_attribute = Schema.some_attribute
example
end

class Example
include ::Schema

attribute :some_attribute

def transform_read(data)
data[:some_attribute] = 'some read value'
end

def transform_write(data)
data[:some_attribute] = 'some written value'
end
end

module Data
def self.example
{
some_attribute: Schema.some_attribute
}
end
end

module InAndOutAliases
def self.example
example = Example.new
example.some_attribute = Schema.some_attribute
example
end

class Example
include ::Schema

attribute :some_attribute

def transform_in(data)
data[:some_attribute] = 'some read value'
end

def transform_out(data)
data[:some_attribute] = 'some written value'
end
end
end
end

module TransformReadFail
Error = Class.new(RuntimeError)

class Example < Schema::Example
include ::Schema

attribute :some_attribute

def transform_read(data)
raise Error
end
end
end
end
end
end
53 changes: 1 addition & 52 deletions lib/schema/data_structure.rb
Original file line number Diff line number Diff line change
@@ -1,61 +1,10 @@
module Schema
module DataStructure
def self.included(cls)
warn "Schema::DataStructure is deprecated. Use Schema directly instead."
cls.class_exec do
include TemplateMethod
include Schema
extend Build

template_method :configure
template_method :configure_dependencies do
configure
end

template_method :transform_read do |data|
transform_in(data)
end
template_method :transform_in
end
end

module Build
def build(data=nil, strict=nil)
data ||= {}
strict ||= false

new.tap do |instance|
if not data.empty?
instance.transform_read(data)
set_attributes(instance, data, strict)
end

instance.configure_dependencies
end
end

def set_attributes(instance, data, strict)
begin
SetAttributes.(instance, data, strict: strict)
rescue SetAttributes::Assign::Error => e
raise Schema::Error, e.message
end
end
end

def deep_copy
data = to_h
self.class.build(data)
end
alias :dup :deep_copy

def clone
duplicate = deep_copy

if frozen?
duplicate.freeze
end

duplicate
end
end
end
Loading