Converter 1.0.2.0 → 1.0.3.0
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.
- data/lib/Converter.rb +61 -78
- metadata +1 -1
data/lib/Converter.rb
CHANGED
@@ -4,125 +4,108 @@ module Converter
|
|
4
4
|
def self.included(base)
|
5
5
|
base.extend(ClassConverter)
|
6
6
|
end
|
7
|
+
|
8
|
+
def convert_to target_class
|
9
|
+
Converter.convert self, target_class
|
10
|
+
end
|
7
11
|
|
8
|
-
# Create new Target_Type instance according to Conversion definition
|
12
|
+
# Create new Target_Type instance according to the Conversion definition
|
13
|
+
# one of the classes (source.class or target_type) should include Converter module
|
9
14
|
# @param [Any Class] source instance to copy from
|
10
15
|
# @param [class] target_type the result type
|
11
|
-
# @return instance of target_type with data from source
|
16
|
+
# @return instance of target_type with data converted from source
|
12
17
|
def self.convert(source, target_type, hash = {})
|
13
|
-
#
|
14
|
-
if(
|
15
|
-
return
|
18
|
+
# Check if the object has already been converted (Circular pointing)
|
19
|
+
if(converted_object = hash[source])
|
20
|
+
return converted_object
|
16
21
|
end
|
17
22
|
|
18
23
|
# Create new target instance
|
19
24
|
hash[source] = target = target_type.new
|
20
|
-
|
25
|
+
|
21
26
|
# Gets source Conversion definition
|
22
|
-
|
27
|
+
# Check which one includes Converter module
|
28
|
+
convertable_object = get_convertable_object source, target
|
29
|
+
conversion_metadatas = convertable_object.class.class_eval { @attribute_converter}
|
23
30
|
|
24
31
|
# update each accessor on the target according to the attr_converters
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
# Get the conversion definition for the current accessor if exists
|
29
|
-
if convert_property = conversion_properties[var_name]
|
30
|
-
target_property_name = convert_property.target_property_name.to_s.concat('=').to_sym
|
31
|
-
|
32
|
-
# Convert from one type to another (by default doesn't do anything)
|
33
|
-
if convert_property.convert_block.parameters.count == 1
|
34
|
-
target_value = convert_property.convert_block.call(source.send(var_name))
|
35
|
-
else
|
36
|
-
target_value = convert_property.convert_block.call(source.send(var_name), hash)
|
37
|
-
end
|
38
|
-
|
39
|
-
target.send(target_property_name, target_value)
|
40
|
-
end
|
32
|
+
conversion_metadatas.values.each do |conversion_metadata|
|
33
|
+
convert_one_attribute source, target, conversion_metadata, source == convertable_object, hash
|
41
34
|
end
|
42
35
|
|
43
36
|
target
|
44
37
|
end
|
45
38
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
39
|
+
private
|
40
|
+
def self.get_convertable_object source, target
|
41
|
+
if source.class.included_modules.include? Converter
|
42
|
+
source
|
43
|
+
elsif target.class.included_modules.include? Converter
|
44
|
+
target
|
45
|
+
else
|
46
|
+
raise ArgumentError.new "One of the given classes should include Converter module"
|
47
|
+
end
|
54
48
|
end
|
55
49
|
|
56
|
-
|
57
|
-
|
50
|
+
def self.convert_one_attribute source, target, conversion_metadata, is_source_convertable, hash
|
51
|
+
source_attribute_name = is_source_convertable ? conversion_metadata.convertable_attribute_name : conversion_metadata.poro_attribute_name
|
52
|
+
convert_block = is_source_convertable ? conversion_metadata.convert_from_convertable_block : conversion_metadata.convert_from_poro_block
|
53
|
+
target_attribute_name = is_source_convertable ? conversion_metadata.poro_attribute_name : conversion_metadata.convertable_attribute_name
|
54
|
+
target_attribute_name = target_attribute_name.to_s.concat('=').to_sym
|
58
55
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
var_name_trimmed = var_name.to_s.delete('=').to_sym
|
65
|
-
|
66
|
-
# Get the conversion definition for the current accessor if exists
|
67
|
-
if convert_property = conversion_properties[var_name_trimmed]
|
68
|
-
target_property_name = convert_property.target_property_name
|
69
|
-
|
70
|
-
# Convert from one type to another (by default doesn't do anything)
|
71
|
-
if convert_property.convert_back_block.parameters.count == 1
|
72
|
-
source_value = convert_property.convert_back_block.call(target.send(target_property_name))
|
73
|
-
else
|
74
|
-
source_value = convert_property.convert_back_block.call(target.send(target_property_name), hash)
|
75
|
-
end
|
76
|
-
|
77
|
-
source.send(var_name, source_value)
|
56
|
+
# Convert from one type to another (by default doesn't do anything)
|
57
|
+
if convert_block.parameters.count == 1
|
58
|
+
target_value = convert_block.call(source.send(source_attribute_name))
|
59
|
+
else
|
60
|
+
target_value = convert_block.call(source.send(source_attribute_name), hash)
|
78
61
|
end
|
62
|
+
|
63
|
+
target.send(target_attribute_name, target_value)
|
79
64
|
end
|
80
65
|
|
81
|
-
|
82
|
-
end
|
66
|
+
public
|
83
67
|
|
84
68
|
# This module add class extension of attr_converter
|
85
69
|
module ClassConverter
|
86
70
|
# Create an attr_accessor and map this attribute as convertable ,
|
87
71
|
# this means that this attribute will be converted when calling to Convert/
|
88
|
-
# @param [symbol]
|
89
|
-
# @param [symbol]
|
90
|
-
# @param [block] convert_block block that convert the
|
91
|
-
# @param [block] convert_back_block block that convert the
|
92
|
-
def attr_converter(
|
72
|
+
# @param [symbol] convertable_attribute_name class attribute name
|
73
|
+
# @param [symbol] poro_attribute_name the attribute name of a poro class (plain old ruby object)
|
74
|
+
# @param [block] convert_block block that convert between the convetable attribute class and the poro attribute class
|
75
|
+
# @param [block] convert_back_block block that convert between the poro attribute class and the convetable attribute class
|
76
|
+
def attr_converter(convertable_attribute_name, poro_attribute_name = nil, convert_block = nil, convert_back_block = nil)
|
93
77
|
# Set default values for nil arguments
|
94
|
-
|
78
|
+
poro_attribute_name ||= convertable_attribute_name
|
95
79
|
@attribute_converter ||= {}
|
96
80
|
|
97
81
|
if convert_block.class == Symbol
|
98
|
-
|
99
|
-
|
100
|
-
convert_block = lambda { |
|
101
|
-
convert_back_block = lambda { |
|
82
|
+
convertable_type = convert_block.to_s
|
83
|
+
poro_type = convert_back_block.to_s
|
84
|
+
convert_block = lambda { |source, hash| Converter.convert(source, eval(poro_type), hash) }
|
85
|
+
convert_back_block = lambda { |source, hash| Converter.convert(source, eval(convertable_type), hash) }
|
102
86
|
else
|
103
|
-
convert_block ||= lambda { |source
|
104
|
-
convert_back_block ||= lambda { |
|
87
|
+
convert_block ||= lambda { |source| source }
|
88
|
+
convert_back_block ||= lambda { |source| source }
|
105
89
|
end
|
106
90
|
|
107
|
-
|
108
91
|
# Create new ConversionMetadata
|
109
|
-
@attribute_converter[
|
110
|
-
attr_accessor
|
92
|
+
@attribute_converter[convertable_attribute_name] =ConversionMetadata.new(convertable_attribute_name, poro_attribute_name, convert_block, convert_back_block)
|
93
|
+
attr_accessor convertable_attribute_name
|
111
94
|
end
|
112
95
|
end
|
113
96
|
|
114
97
|
# Represent conversion data of one property to another
|
115
98
|
class ConversionMetadata
|
116
|
-
def initialize(
|
117
|
-
@
|
118
|
-
@
|
119
|
-
@
|
120
|
-
@
|
99
|
+
def initialize(convertable_attribute_name, poro_attribute_name, convert_from_convertable_block, convert_from_poro_block)
|
100
|
+
@convertable_attribute_name = convertable_attribute_name
|
101
|
+
@poro_attribute_name = poro_attribute_name
|
102
|
+
@convert_from_convertable_block = convert_from_convertable_block
|
103
|
+
@convert_from_poro_block = convert_from_poro_block
|
121
104
|
end
|
122
105
|
|
123
|
-
attr_accessor :
|
124
|
-
attr_accessor :
|
125
|
-
attr_accessor :
|
126
|
-
attr_accessor :
|
106
|
+
attr_accessor :convertable_attribute_name
|
107
|
+
attr_accessor :poro_attribute_name
|
108
|
+
attr_accessor :convert_from_convertable_block
|
109
|
+
attr_accessor :convert_from_poro_block
|
127
110
|
end
|
128
111
|
end
|