libis-workflow-mongoid 2.0.2 → 2.0.3
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.
- checksums.yaml +4 -4
- data/Gemfile +0 -1
- data/lib/libis/workflow/mongoid/base.rb +42 -3
- data/lib/libis/workflow/mongoid/job.rb +25 -3
- data/lib/libis/workflow/mongoid/run.rb +9 -4
- data/lib/libis/workflow/mongoid/version.rb +1 -1
- data/lib/libis/workflow/mongoid/work_item_base.rb +16 -4
- data/lib/libis/workflow/mongoid/workflow.rb +25 -3
- data/lib/map_with_indifferent_access.rb +20 -0
- data/lib/map_with_indifferent_access/list.rb +867 -0
- data/lib/map_with_indifferent_access/map.rb +833 -0
- data/lib/map_with_indifferent_access/normalization.rb +92 -0
- data/lib/map_with_indifferent_access/normalization/deep_normalizer.rb +104 -0
- data/lib/map_with_indifferent_access/values.rb +39 -0
- data/lib/map_with_indifferent_access/version.rb +3 -0
- data/lib/map_with_indifferent_access/wraps_collection.rb +152 -0
- data/libis-workflow-mongoid.gemspec +0 -1
- data/spec/items/test_dir_item.rb +1 -1
- data/spec/items/test_file_item.rb +3 -3
- data/spec/tasks/camelize_name.rb +1 -1
- data/spec/workflow_spec.rb +2 -2
- metadata +10 -2
@@ -0,0 +1,92 @@
|
|
1
|
+
require "map_with_indifferent_access/normalization/deep_normalizer"
|
2
|
+
|
3
|
+
module MapWithIndifferentAccess
|
4
|
+
module Normalization
|
5
|
+
class << self
|
6
|
+
# Deeply normalizes `Hash`-like and `Array`-like hash entry
|
7
|
+
# values and array items, preserving all of the existing key
|
8
|
+
# values (`String`, `Symbol`, or otherwise) from the inner
|
9
|
+
# collections.
|
10
|
+
#
|
11
|
+
# @see DeepNormalizer#call
|
12
|
+
def deeply_normalize(obj)
|
13
|
+
deep_basic_normalizer.call( obj )
|
14
|
+
end
|
15
|
+
|
16
|
+
# Deeply coerces keys to `Symbol` type.
|
17
|
+
#
|
18
|
+
# @see DeepNormalizer#call
|
19
|
+
def deeply_symbolize_keys(obj)
|
20
|
+
deep_key_symbolizer.call( obj )
|
21
|
+
end
|
22
|
+
|
23
|
+
# Deeply coerces keys to `String` type.
|
24
|
+
#
|
25
|
+
# @see DeepNormalizer#call
|
26
|
+
def deeply_stringify_keys(obj)
|
27
|
+
deep_key_stringifier.call( obj )
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def deep_basic_normalizer
|
33
|
+
@deep_basic_normalizer ||= DeepNormalizer.new( NullKeyStrategy )
|
34
|
+
end
|
35
|
+
|
36
|
+
def deep_key_symbolizer
|
37
|
+
@deep_key_symbolizer ||= DeepNormalizer.new( SymbolizationKeyStrategy )
|
38
|
+
end
|
39
|
+
|
40
|
+
def deep_key_stringifier
|
41
|
+
@deep_key_stringifier ||= DeepNormalizer.new( StringificationKeyStrategy )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module KeyStrategy
|
46
|
+
def self.needs_coercion?(key)
|
47
|
+
raise NotImplementedError, "Including-module responsibility"
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.coerce(key)
|
51
|
+
raise NotImplementedError, "Including-module responsibility"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module NullKeyStrategy
|
56
|
+
extend Normalization::KeyStrategy
|
57
|
+
|
58
|
+
def self.needs_coercion?(key)
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.coerce(key)
|
63
|
+
key
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module SymbolizationKeyStrategy
|
68
|
+
extend Normalization::KeyStrategy
|
69
|
+
|
70
|
+
def self.needs_coercion?(key)
|
71
|
+
!( Symbol === key )
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.coerce(key)
|
75
|
+
key.to_s.to_sym
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module StringificationKeyStrategy
|
80
|
+
extend Normalization::KeyStrategy
|
81
|
+
|
82
|
+
def self.needs_coercion?(key)
|
83
|
+
!( String === key )
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.coerce(key)
|
87
|
+
key.to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module MapWithIndifferentAccess
|
2
|
+
module Normalization
|
3
|
+
|
4
|
+
class DeepNormalizer
|
5
|
+
attr_reader :strategy
|
6
|
+
|
7
|
+
# Initializes a new DeepNormalizer with a given object that
|
8
|
+
# extends {KeyStrategy}.
|
9
|
+
def initialize(strategy)
|
10
|
+
@strategy = strategy
|
11
|
+
end
|
12
|
+
|
13
|
+
# Given an `Array`-like or `Hash`-like object, returns a
|
14
|
+
# similar object with keys coerced according to the
|
15
|
+
# target {DeepNormalizer}'s strategy.
|
16
|
+
# Given an object that is not `Array`-like or `Hash`-like,
|
17
|
+
# then the given object is returned.
|
18
|
+
#
|
19
|
+
# During this process, any hash entry values or array
|
20
|
+
# items that are instances of
|
21
|
+
# {Map} or {List} are replaced with `Hash` or `Array`
|
22
|
+
# deconstructions respectively. If a {Map} or {List} is
|
23
|
+
# given, then the same type of object is returned.
|
24
|
+
#
|
25
|
+
# If a `Hash` or an object that resonds to `#to_hash` and
|
26
|
+
# `#each_pair` is given, then a `Hash` is returned. The
|
27
|
+
# same applies to each `Hash`/{Map} entry value or
|
28
|
+
# `Array`/{List} item that is traversed.
|
29
|
+
#
|
30
|
+
# If an `Array` or an object that resonds to `#to_ary` is
|
31
|
+
# given, then an `Array` is returned. The same applies to
|
32
|
+
# each `Hash`/{Map} entry value or `Array`/{List} item that
|
33
|
+
# is traversed.
|
34
|
+
#
|
35
|
+
# If any keys, `Hash` entry values, or `Array` items are
|
36
|
+
# replaced, then a new object is returned that includes
|
37
|
+
# those replacements. Otherwise, the given object is
|
38
|
+
# returned. In either case, the contents of `obj` are not
|
39
|
+
# modified.
|
40
|
+
def call(obj)
|
41
|
+
if WrapsCollection === obj
|
42
|
+
coerced_inner_col = recursively_coerce( obj )
|
43
|
+
Values.externalize( coerced_inner_col )
|
44
|
+
else
|
45
|
+
recursively_coerce( obj )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def recursively_coerce(obj)
|
52
|
+
if ::Hash === obj
|
53
|
+
coerce_hash( obj )
|
54
|
+
elsif Map === obj
|
55
|
+
coerce_hash( obj.inner_map )
|
56
|
+
elsif ::Array === obj
|
57
|
+
coerce_array( obj )
|
58
|
+
elsif List === obj
|
59
|
+
coerce_array( obj.inner_array )
|
60
|
+
elsif obj.respond_to?(:to_hash) && obj.respond_to?(:each_pair)
|
61
|
+
coerce_hash( obj.to_hash )
|
62
|
+
elsif obj.respond_to?(:to_ary)
|
63
|
+
coerce_array( obj.to_ary )
|
64
|
+
else
|
65
|
+
obj
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def coerce_hash(obj)
|
70
|
+
does_need_key_coercion = obj.each_key.any?{ |key|
|
71
|
+
strategy.needs_coercion?( key )
|
72
|
+
}
|
73
|
+
result = does_need_key_coercion ? {} : obj
|
74
|
+
|
75
|
+
obj.each_pair do |(key,value)|
|
76
|
+
key = strategy.coerce( key ) if strategy.needs_coercion?( key )
|
77
|
+
new_value = recursively_coerce( value )
|
78
|
+
if result.equal?( obj )
|
79
|
+
unless new_value.equal?( value )
|
80
|
+
result = obj.dup
|
81
|
+
result[ key ] = new_value
|
82
|
+
end
|
83
|
+
else
|
84
|
+
result[ key ] = new_value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
result
|
88
|
+
end
|
89
|
+
|
90
|
+
def coerce_array( obj )
|
91
|
+
result = obj
|
92
|
+
obj.each_with_index do |item,i|
|
93
|
+
new_item = recursively_coerce(item)
|
94
|
+
unless new_item.equal?( item )
|
95
|
+
result = obj.dup if result.equal?( obj )
|
96
|
+
result[ i ] = new_item
|
97
|
+
end
|
98
|
+
end
|
99
|
+
result
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module MapWithIndifferentAccess
|
2
|
+
|
3
|
+
module Values
|
4
|
+
|
5
|
+
class << self
|
6
|
+
# Converts `obj` to a {Map} or {List} if possible, otherwise
|
7
|
+
# returns `obj`.
|
8
|
+
#
|
9
|
+
# @return [Map, List, Object]
|
10
|
+
def externalize(obj)
|
11
|
+
(
|
12
|
+
Map.try_convert( obj ) ||
|
13
|
+
List.try_convert( obj ) ||
|
14
|
+
obj
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
alias >> externalize
|
19
|
+
|
20
|
+
# Converts `obj`, which might be a {Map} or {List} to a
|
21
|
+
# `Hash` or `Array` if possible. Returns `obj` if no
|
22
|
+
# conversion is possible.
|
23
|
+
#
|
24
|
+
# @return [Hash, Array, Object]
|
25
|
+
def internalize(obj)
|
26
|
+
(
|
27
|
+
Map.try_deconstruct( obj ) ||
|
28
|
+
List.try_deconstruct( obj ) ||
|
29
|
+
obj
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
alias << internalize
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module MapWithIndifferentAccess
|
4
|
+
|
5
|
+
module WrapsCollection
|
6
|
+
extend Forwardable
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
# The encapsulated collection object.
|
10
|
+
attr_reader :inner_collection
|
11
|
+
|
12
|
+
# @!method length
|
13
|
+
# The number of entries in the collection.
|
14
|
+
#
|
15
|
+
# @return [Fixnum]
|
16
|
+
# @see #size
|
17
|
+
|
18
|
+
# @!method size
|
19
|
+
# The number of entries in the collection.
|
20
|
+
#
|
21
|
+
# @return [Fixnum]
|
22
|
+
# @see #length
|
23
|
+
|
24
|
+
# @!method empty?
|
25
|
+
# Returns `true` if the collection contains no entries.
|
26
|
+
#
|
27
|
+
# Returns `false` if the collection contains 1 or more
|
28
|
+
# entries.
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
31
|
+
|
32
|
+
# @!method _frozen?
|
33
|
+
# Returns true when the target object (the wrapper) is
|
34
|
+
# frozen.
|
35
|
+
#
|
36
|
+
# There are some cases in which this returns `false` when
|
37
|
+
# {#frozen?} would return `true`.
|
38
|
+
#
|
39
|
+
# @return [Boolean]
|
40
|
+
# @see #frozen?
|
41
|
+
|
42
|
+
# Using `class_eval` to hide the aliasing from YARD, so it
|
43
|
+
# does not document this alias to the implementation
|
44
|
+
# inherited from `Object` as an alias to the subsequent
|
45
|
+
# override.
|
46
|
+
class_eval 'alias _frozen? frozen?', __FILE__, __LINE__
|
47
|
+
|
48
|
+
# @!method tainted?
|
49
|
+
# Reflects the tainted-ness of its #inner_collection.
|
50
|
+
# @return [Boolean]
|
51
|
+
|
52
|
+
# @!method untrusted?
|
53
|
+
# Reflects the untrusted-ness of its #inner_collection.
|
54
|
+
# @return [Boolean]
|
55
|
+
|
56
|
+
# @!method frozen?
|
57
|
+
# Reflects the frozen-ness of its {#inner_collection}.
|
58
|
+
#
|
59
|
+
# Returns `true` when the {#inner_collection} is frozen (
|
60
|
+
# and the target/wrapper might be frozen or not).
|
61
|
+
#
|
62
|
+
# Returns `false` when the {#inner_collection} is not
|
63
|
+
# frozen (and neither is the target/wrapper).
|
64
|
+
#
|
65
|
+
# When the {#inner_collection} is frozen, but the target
|
66
|
+
# object is not, then the target behaves as if frozen in
|
67
|
+
# most ways, but some of the restrictions that Ruby applies
|
68
|
+
# to truly frozen (such as preventing instance methods from
|
69
|
+
# being dynamically added to the object) do not apply.
|
70
|
+
#
|
71
|
+
# @return [Boolean]
|
72
|
+
# @see #_frozen?
|
73
|
+
|
74
|
+
# @!method hash
|
75
|
+
# Compute a hash-code for this collection wrapper. Two
|
76
|
+
# wrappers with the same type and the same
|
77
|
+
# {#inner_collection} content will have the same hash code
|
78
|
+
# (and will match using {#eql?}).
|
79
|
+
#
|
80
|
+
# @return [Fixnum]
|
81
|
+
|
82
|
+
def_delegators(
|
83
|
+
:inner_collection,
|
84
|
+
:length,
|
85
|
+
:size,
|
86
|
+
:empty?,
|
87
|
+
:tainted?,
|
88
|
+
:untrusted?,
|
89
|
+
:frozen?,
|
90
|
+
:hash,
|
91
|
+
)
|
92
|
+
|
93
|
+
# @!method taint
|
94
|
+
# Causes the target's #inner_collection to be tainted.
|
95
|
+
|
96
|
+
# @!method untaint
|
97
|
+
# Causes the target's #inner_collection to be untainted.
|
98
|
+
|
99
|
+
# @!method untrust
|
100
|
+
# Causes the target's #inner_collection to be untrusted.
|
101
|
+
|
102
|
+
# @!method trust
|
103
|
+
# Causes the target's {#inner_collection} to be trusted.
|
104
|
+
|
105
|
+
[:taint, :untaint, :untrust, :trust ].each do |method_name|
|
106
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
107
|
+
def #{method_name}
|
108
|
+
inner_collection.#{method_name}
|
109
|
+
self
|
110
|
+
end
|
111
|
+
EOS
|
112
|
+
end
|
113
|
+
|
114
|
+
# Removes all entries from the target's {#inner_collection}.
|
115
|
+
def clear
|
116
|
+
inner_collection.clear
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
# Freezes both the target map and its {#inner_collection}
|
121
|
+
# object.
|
122
|
+
def freeze
|
123
|
+
super
|
124
|
+
inner_collection.freeze
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns `true` for another instance of the same class as
|
129
|
+
# the target where the target's {#inner_collection} is
|
130
|
+
# `#eql?` to the given object's {#inner_collection}. Returns
|
131
|
+
# `false` otherwise.
|
132
|
+
#
|
133
|
+
# @return [Boolean]
|
134
|
+
def eql?(other)
|
135
|
+
self.class == other.class &&
|
136
|
+
self.inner_collection.eql?( other.inner_collection )
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def initialize_dup(orig)
|
142
|
+
super
|
143
|
+
@inner_collection = inner_collection.dup
|
144
|
+
end
|
145
|
+
|
146
|
+
def initialize_clone(orig)
|
147
|
+
super
|
148
|
+
@inner_collection = inner_collection.clone
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
data/spec/items/test_dir_item.rb
CHANGED
@@ -15,15 +15,15 @@ class TestFileItem < TestItem
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def name
|
18
|
-
self.properties[
|
18
|
+
self.properties[:name] || super
|
19
19
|
end
|
20
20
|
|
21
21
|
def filesize
|
22
|
-
properties[
|
22
|
+
properties[:size]
|
23
23
|
end
|
24
24
|
|
25
25
|
def fixity_check(checksum)
|
26
|
-
properties[
|
26
|
+
properties[:checksum] == checksum
|
27
27
|
end
|
28
28
|
|
29
29
|
end
|
data/spec/tasks/camelize_name.rb
CHANGED
data/spec/workflow_spec.rb
CHANGED
@@ -190,8 +190,8 @@ STR
|
|
190
190
|
item = run.items.first
|
191
191
|
expect(item.nil?).to eq false
|
192
192
|
expect(item.is_a? TestDirItem).to eq true
|
193
|
-
expect(item.properties[
|
194
|
-
expect(item.properties[
|
193
|
+
expect(item.properties[:name]).to eq 'Items'
|
194
|
+
expect(item.properties[:ingest_failed]).to eq false
|
195
195
|
end
|
196
196
|
|
197
197
|
it 'move item in relation' do
|