traitorous 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -1
- data/Rakefile +4 -3
- data/VERSION +1 -1
- data/lib/traitorous/converter/identity.rb +22 -0
- data/lib/traitorous/converter/method_keyed_uniform_hash.rb +43 -0
- data/lib/traitorous/converter/model.rb +26 -3
- data/lib/traitorous/equality.rb +30 -0
- data/lib/traitorous.rb +21 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51c87b262becc747a334dce20c4b0f149de698d4
|
4
|
+
data.tar.gz: 384664790edbfbbcbc95043b7f4cc3fbe78c78e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27cecb8725cfe6914c81e26ae45cc2e5f9669228e01f3c139d4e02a309af4763918c45a22e75bd9453b9fbd8254c70248ed3f0ed4a0c7eb5e10e9626cedd47ba
|
7
|
+
data.tar.gz: 052ece595a8928766a34eaede53b690981834db33cbedeb2215f940e3d354d2b165118e7e3a2403ff179ecc7d538103c7edf0aa8f645539269c13825627b841e
|
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
# Traitorous
|
1
|
+
# Traitorous [![Gem Version](https://badge.fury.io/rb/traitorous.svg)](http://badge.fury.io/rb/traitorous)
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/anithri/traitorous.svg)](https://travis-ci.org/anithri/traitorous)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/anithri/traitorous/badges/gpa.svg)](https://codeclimate.com/github/anithri/traitorous)
|
5
|
+
[![Inline docs](http://inch-ci.org/github/anithri/traitorous.svg?branch=master)](http://inch-ci.org/github/anithri/traitorous)
|
5
6
|
|
6
7
|
This is a simple trait based system that emphasizes reading in and out data
|
7
8
|
structures, using an plugin Converter system. Each trait defined has a
|
@@ -85,6 +86,18 @@ puts Area.new(area.export) == area
|
|
85
86
|
# true
|
86
87
|
```
|
87
88
|
|
89
|
+
## Roadmap
|
90
|
+
|
91
|
+
1. Add better documentation
|
92
|
+
2. better testing of deep constructions
|
93
|
+
3. Additional Converters
|
94
|
+
a. DefaultValueDynamic that stores code to run upon input or output
|
95
|
+
b. VariableArray that uses a sub-type in the opts to location the correct
|
96
|
+
class to instantiate instead of always using a uniform class
|
97
|
+
c. Validations?
|
98
|
+
d. translations?
|
99
|
+
e. class specific (Date, CreditCard)
|
100
|
+
|
88
101
|
## Development
|
89
102
|
|
90
103
|
I use Guard to automate testing. It won't affect anything execpt the disk space
|
data/Rakefile
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
|
2
|
+
require 'rake/version_task'
|
3
3
|
require 'rspec/core/rake_task'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
Rake::VersionTask.new do |task|
|
6
|
+
task.with_git_tag = true
|
7
|
+
end
|
7
8
|
RSpec::Core::RakeTask.new(:spec)
|
8
9
|
|
9
10
|
task :default => :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -1,10 +1,32 @@
|
|
1
1
|
module Traitorous
|
2
2
|
module Converter
|
3
|
+
# The Identity converter is used as a simple default which performs the
|
4
|
+
# jobs of a Converter without changing the inputs at all.
|
5
|
+
#
|
6
|
+
# This converter can be used when you have simple data (strings, dates,
|
7
|
+
# numbers, hashes and arrays of the same) that doesn't need to be inflated
|
8
|
+
# into an object and needs no changes to be safely stored as the same.
|
3
9
|
class Identity
|
10
|
+
# do_export is called in order to take an existing piece of data and
|
11
|
+
# prepare it to be written to a simpler data structure.
|
12
|
+
#
|
13
|
+
# The Identity converter exports the same data it is passed without
|
14
|
+
# changing them at all.
|
15
|
+
#
|
16
|
+
# @params data [Object] the data object passed in to be exported
|
17
|
+
# @return [Object] exports data to a form simple enough to save as JSON
|
4
18
|
def do_export(data)
|
5
19
|
data
|
6
20
|
end
|
7
21
|
|
22
|
+
# do_import is called in order to take some opts and to turn them into
|
23
|
+
# instantiated objects, arrays, or other types of transformation
|
24
|
+
#
|
25
|
+
# The Identity converter imports the same opts it is passed without
|
26
|
+
# changing them at all.
|
27
|
+
#
|
28
|
+
# @params opts [Object] the options to be imported
|
29
|
+
# @return [Object] opts
|
8
30
|
def do_import(opts)
|
9
31
|
opts
|
10
32
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Traitorous
|
2
|
+
module Converter
|
3
|
+
# MethodKeyedUniformedHash is meant to take an array of a simple data
|
4
|
+
# structures and convert each into a uniform class, and then will call a
|
5
|
+
# key_method on that class and use it as the key in the returned hash.
|
6
|
+
#
|
7
|
+
# Exported data will be converted into an array calling do_export on each
|
8
|
+
# element
|
9
|
+
class MethodKeyedUniformHash
|
10
|
+
attr_accessor :key_method, :uniform_class
|
11
|
+
# @param key_method [Symbol] the method to call on the uniform_class instance
|
12
|
+
# to generate the key in the returned hash
|
13
|
+
# @param uniform_class [Class, #new] the class to instantiate with each
|
14
|
+
# element of the do_import array
|
15
|
+
def initialize(key_method, uniform_class)
|
16
|
+
@key_method = key_method
|
17
|
+
@uniform_class = uniform_class
|
18
|
+
end
|
19
|
+
|
20
|
+
# The import instantiates each element of the array as an instance of
|
21
|
+
# the uniform_class, the key is determined by calling key_method on the
|
22
|
+
# instance and then they are joined to the result hash as a key,
|
23
|
+
# instance pair.
|
24
|
+
# @param arr_data [Array] the array of data to instantiate
|
25
|
+
# @return [Hash] hash containing key, instance pairs
|
26
|
+
def do_import(arr_data)
|
27
|
+
out = {}
|
28
|
+
arr_data.each do |elem_data|
|
29
|
+
obj = uniform_class.new(elem_data)
|
30
|
+
out[obj.send(key_method)] = obj
|
31
|
+
end
|
32
|
+
out
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param hsh_data [Hash<obj,#export>] keys are ignored
|
36
|
+
# @return Array each element of the values of hsh_data has #export called
|
37
|
+
# on it.
|
38
|
+
def do_export(hsh_data)
|
39
|
+
hsh_data.values.map{|instance| instance.export }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,16 +1,39 @@
|
|
1
1
|
module Traitorous
|
2
2
|
module Converter
|
3
|
+
# The Model converter is used a a simple way to instantiate an object from
|
4
|
+
# the model_class using the imported opts, and which will call .export on
|
5
|
+
# the data.
|
6
|
+
#
|
7
|
+
# This converter can be used when you have a set of opts that you can pass
|
8
|
+
# to a classes .new command in order to instantiate an object.
|
3
9
|
class Model
|
10
|
+
# @param model_klass [Class,#new] class to instantiate when importing
|
4
11
|
def initialize(model_klass)
|
5
12
|
@model_klass = model_klass
|
6
13
|
end
|
7
|
-
|
8
|
-
|
9
|
-
|
14
|
+
|
15
|
+
# do_export is called in order to take an existing piece of data and
|
16
|
+
# prepare it to be written to a simpler data structure.
|
17
|
+
#
|
18
|
+
# The model converter exports the data by calling .export on it
|
19
|
+
#
|
20
|
+
# @params data [Object] the data object passed in to be exported
|
21
|
+
# @return [Object] result of data.export
|
10
22
|
def do_export(data)
|
11
23
|
data.export
|
12
24
|
end
|
13
25
|
|
26
|
+
# do_import is called in order to take some opts and to turn them into
|
27
|
+
# instantiated objects, arrays, or other types of transformation
|
28
|
+
#
|
29
|
+
# The model converter imports the opts by instantiating a model_class
|
30
|
+
# object with it.
|
31
|
+
#
|
32
|
+
# @params opts [Object] the options to be exported
|
33
|
+
# @return [Object] result of model_klass.new(opts)
|
34
|
+
def do_import(opts)
|
35
|
+
@model_klass.new(opts)
|
36
|
+
end
|
14
37
|
end
|
15
38
|
end
|
16
39
|
end
|
data/lib/traitorous/equality.rb
CHANGED
@@ -1,7 +1,31 @@
|
|
1
1
|
require 'traitorous'
|
2
2
|
module Traitorous
|
3
|
+
# Provides a mechanism to test equality of objects that implement a traits hash.
|
4
|
+
# This is an iffy concept, and if I didn't happen to be using a Coordinate
|
5
|
+
# object in te project this was extracted from it probably wouldn't be a part
|
6
|
+
#
|
7
|
+
# For this module to work it makes a set of assumptions.
|
8
|
+
# 1. The base assumption of the types of objects created using Traitorous is
|
9
|
+
# that they are easily expressed in text.
|
10
|
+
# 2. That the aggregate of the traits equality means the 2 are equal
|
11
|
+
# 3. If a trait is an Array, each element of the array is tested against the 2nd,
|
12
|
+
# and vice versa.
|
13
|
+
# 4. all other equality is tested using ==
|
14
|
+
# 5. nested objects should also implement equality to facilitate the
|
15
|
+
# comparisons of deeply nested structures
|
16
|
+
#
|
17
|
+
# Further expansions might call for the converter to assume an equality guise
|
3
18
|
module Equality
|
19
|
+
|
20
|
+
# Override the normal :== method to compare each trait individually when
|
21
|
+
# testing equality.
|
22
|
+
#
|
23
|
+
# Coordinate.new(x: 1, y: 2) == Coordinate.new(x:1, y: 2)
|
24
|
+
|
25
|
+
# @param other_val [#traits] target of comparison
|
26
|
+
# @return Boolean if all traits values match return true.
|
4
27
|
def ==(other_val)
|
28
|
+
return false unless self.class == other_val.class
|
5
29
|
traits.keys.all? do |trait_name|
|
6
30
|
orig_trait = self.send(trait_name.intern)
|
7
31
|
other_trait = other_val.send(trait_name.intern)
|
@@ -9,6 +33,12 @@ module Traitorous
|
|
9
33
|
end
|
10
34
|
end
|
11
35
|
|
36
|
+
# compare the equality of 2 arrays, and I'm not sure this is the best way to
|
37
|
+
# do the comparisons.
|
38
|
+
# @params alpha [Array] first array
|
39
|
+
# @params beta [Array] second array
|
40
|
+
# @return [Boolean] true if every element in 1 array is equal(==) to an
|
41
|
+
# element in the 2nd and vice versa (order doesn't matter, should it?)
|
12
42
|
def array_equality(alpha, beta)
|
13
43
|
return false unless (alpha.is_a?(Array) && beta.is_a?(Array))
|
14
44
|
alpha.all?{|a| beta.any?{|b| a == b}}
|
data/lib/traitorous.rb
CHANGED
@@ -1,18 +1,38 @@
|
|
1
1
|
require 'active_support/core_ext/hash/indifferent_access'
|
2
2
|
|
3
3
|
module Traitorous
|
4
|
+
|
5
|
+
# Use the HashWithIndifferentAccess from the activesupport gem.
|
4
6
|
HASH = HashWithIndifferentAccess
|
5
7
|
|
8
|
+
# Read the VERSION file in gem root to set version number.
|
6
9
|
VERSION = File.read('VERSION')
|
7
10
|
|
11
|
+
# The converter namespace is used to store Converter classes.
|
12
|
+
# Each Converter may take initializer arguments, to allow specific classes or
|
13
|
+
# values to be defined, and 2 methods: :do_import and :do_export.
|
14
|
+
# do_import is meant to take the data, and use the initial data to combine to
|
15
|
+
# build objects or other data structures.
|
8
16
|
module Converter
|
17
|
+
# The purpose of the converters are to facilitate the importation of simple
|
18
|
+
# JSON or YAML data and import that data into an arbitrarily nested tree
|
19
|
+
# of objects. And then to take those object and be able to export that data
|
20
|
+
# in a simple form ready to save.
|
21
|
+
# opts = {some: 'deep', data: ['structures']}
|
22
|
+
# r = Mission.new(opts)
|
23
|
+
# Mission.new(r.export) == r
|
9
24
|
require 'traitorous/converter/identity'
|
10
25
|
require 'traitorous/converter/default_value_static'
|
11
26
|
require 'traitorous/converter/model'
|
12
27
|
require 'traitorous/converter/uniform_array'
|
28
|
+
require 'traitorous/converter/method_keyed_uniform_hash'
|
29
|
+
# if no other converter is declared, use the identity converter which
|
30
|
+
# merely pass through the data passed to it.
|
13
31
|
DEFAULT_CONVERTER = Converter::Identity.new
|
14
32
|
end
|
33
|
+
|
15
34
|
require 'traitorous/equality'
|
35
|
+
|
16
36
|
module ClassMethods
|
17
37
|
attr_accessor :traits
|
18
38
|
|
@@ -30,6 +50,7 @@ module Traitorous
|
|
30
50
|
end
|
31
51
|
|
32
52
|
def initialize(opts = {})
|
53
|
+
raise "No traits have been defined for #{self.class}" unless self.class.traits
|
33
54
|
@opts = HASH.new(opts)
|
34
55
|
traits.each_pair do |new_trait, trait_opts|
|
35
56
|
converter = trait_opts[:converter]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: traitorous
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- scott m parrish
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/traitorous.rb
|
105
105
|
- lib/traitorous/converter/default_value_static.rb
|
106
106
|
- lib/traitorous/converter/identity.rb
|
107
|
+
- lib/traitorous/converter/method_keyed_uniform_hash.rb
|
107
108
|
- lib/traitorous/converter/model.rb
|
108
109
|
- lib/traitorous/converter/uniform_array.rb
|
109
110
|
- lib/traitorous/equality.rb
|