i18n-tasks 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +9 -0
- data/README.md +46 -36
- data/Rakefile +2 -2
- data/lib/i18n/tasks/base_task.rb +2 -0
- data/lib/i18n/tasks/commands.rb +55 -35
- data/lib/i18n/tasks/commands_base.rb +36 -9
- data/lib/i18n/tasks/configuration.rb +14 -13
- data/lib/i18n/tasks/console_context.rb +0 -1
- data/lib/i18n/tasks/data.rb +2 -2
- data/lib/i18n/tasks/data/adapter/json_adapter.rb +6 -2
- data/lib/i18n/tasks/data/file_formats.rb +19 -4
- data/lib/i18n/tasks/data/file_system_base.rb +1 -1
- data/lib/i18n/tasks/data/tree/node.rb +11 -37
- data/lib/i18n/tasks/data/tree/nodes.rb +6 -2
- data/lib/i18n/tasks/data/tree/siblings.rb +53 -29
- data/lib/i18n/tasks/data/tree/traversal.rb +4 -2
- data/lib/i18n/tasks/fill_tasks.rb +5 -2
- data/lib/i18n/tasks/ignore_keys.rb +1 -1
- data/lib/i18n/tasks/locale_pathname.rb +1 -1
- data/lib/i18n/tasks/logging.rb +2 -0
- data/lib/i18n/tasks/missing_keys.rb +74 -31
- data/lib/i18n/tasks/plural_keys.rb +4 -3
- data/lib/i18n/tasks/reports/base.rb +8 -5
- data/lib/i18n/tasks/reports/spreadsheet.rb +15 -3
- data/lib/i18n/tasks/reports/terminal.rb +62 -23
- data/lib/i18n/tasks/scanners/base_scanner.rb +4 -2
- data/lib/i18n/tasks/scanners/relative_keys.rb +21 -0
- data/lib/i18n/tasks/split_key.rb +39 -0
- data/lib/i18n/tasks/used_keys.rb +1 -1
- data/lib/i18n/tasks/version.rb +1 -1
- data/spec/fixtures/app/views/index.html.slim +2 -0
- data/spec/i18n_tasks_spec.rb +19 -5
- data/spec/locale_pathname_spec.rb +24 -0
- data/spec/locale_tree/siblings_spec.rb +41 -4
- data/spec/split_key_spec.rb +27 -0
- data/spec/support/i18n_tasks_output_matcher.rb +7 -13
- data/spec/support/trees.rb +4 -0
- data/templates/config/i18n-tasks.yml +82 -0
- data/templates/rspec/i18n_spec.rb +18 -0
- metadata +10 -3
- data/lib/i18n/tasks/relative_keys.rb +0 -19
data/lib/i18n/tasks/data.rb
CHANGED
@@ -9,14 +9,18 @@ module I18n::Tasks
|
|
9
9
|
|
10
10
|
# @return [Hash] locale tree
|
11
11
|
def parse(str, opts)
|
12
|
-
JSON.parse(str, opts
|
12
|
+
JSON.parse(str, parse_opts(opts))
|
13
13
|
end
|
14
14
|
|
15
15
|
# @return [String]
|
16
16
|
def dump(tree, opts)
|
17
|
-
JSON.generate(tree, opts
|
17
|
+
JSON.generate(tree, parse_opts(opts))
|
18
18
|
end
|
19
19
|
|
20
|
+
private
|
21
|
+
def parse_opts(opts)
|
22
|
+
opts.try(:symbolize_keys) || {}
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
@@ -13,6 +13,16 @@ module I18n
|
|
13
13
|
self.class.adapter_for(path)
|
14
14
|
end
|
15
15
|
|
16
|
+
def adapter_by_name(path)
|
17
|
+
self.class.adapter_by_name(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def adapter_dump(tree, adapter_info)
|
21
|
+
adapter_name, adapter_pattern, adapter = adapter_info
|
22
|
+
adapter_options = (config[adapter_name] || {})[:write]
|
23
|
+
adapter.dump(tree, adapter_options)
|
24
|
+
end
|
25
|
+
|
16
26
|
protected
|
17
27
|
|
18
28
|
def load_file(path)
|
@@ -24,9 +34,7 @@ module I18n
|
|
24
34
|
def write_tree(path, tree)
|
25
35
|
::FileUtils.mkpath(File.dirname path)
|
26
36
|
::File.open(path, 'w') { |f|
|
27
|
-
|
28
|
-
adapter_options = (config[adapter_name] || {})[:write]
|
29
|
-
f.write(adapter.dump(tree.to_hash, adapter_options))
|
37
|
+
f.write(adapter_dump(tree.to_hash, adapter_for(path)))
|
30
38
|
}
|
31
39
|
end
|
32
40
|
|
@@ -38,10 +46,17 @@ module I18n
|
|
38
46
|
end
|
39
47
|
|
40
48
|
def adapter_for(path)
|
41
|
-
@fn_patterns.detect { |(
|
49
|
+
@fn_patterns.detect { |(_name, pattern, _adapter)|
|
42
50
|
::File.fnmatch(pattern, path)
|
43
51
|
} or raise CommandError.new("Adapter not found for #{path}. Registered adapters: #{@fn_patterns.inspect}")
|
44
52
|
end
|
53
|
+
|
54
|
+
def adapter_by_name(name)
|
55
|
+
name = name.to_s
|
56
|
+
@fn_patterns.detect { |(adapter_name, _pattern, _adapter)|
|
57
|
+
adapter_name.to_s == name
|
58
|
+
} or raise CommandError.new("Adapter with name #{name.inspect} not found. Registered adapters: #{@fn_patterns.inspect}")
|
59
|
+
end
|
45
60
|
end
|
46
61
|
end
|
47
62
|
end
|
@@ -111,7 +111,7 @@ module I18n::Tasks
|
|
111
111
|
[path.freeze, load_file(path) || {}]
|
112
112
|
end.map do |path, data|
|
113
113
|
Data::Tree::Siblings.from_nested_hash(data).tap do |s|
|
114
|
-
s.leaves { |x| x.data
|
114
|
+
s.leaves { |x| x.data.update(path: path, locale: locale) }
|
115
115
|
end
|
116
116
|
end.reduce(:merge!) || Tree::Siblings.null
|
117
117
|
end
|
@@ -20,28 +20,19 @@ module I18n::Tasks::Data::Tree
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def derive(new_attr = {})
|
23
|
-
|
24
|
-
node.children = new_attr[:children] || @children.try(:derive, parent: node)
|
25
|
-
node
|
26
|
-
end
|
27
|
-
|
28
|
-
def key=(value)
|
29
|
-
value = value.try(:to_s)
|
30
|
-
if @key != value
|
31
|
-
dirty!
|
32
|
-
parent.try(:children).try(:key_renamed, value, @key)
|
33
|
-
@key = value
|
34
|
-
end
|
23
|
+
self.class.new(attributes.merge(new_attr))
|
35
24
|
end
|
36
25
|
|
37
26
|
def children=(children)
|
27
|
+
@children = case children
|
28
|
+
when Siblings
|
29
|
+
children.parent == self ? children : children.derive(parent: self)
|
30
|
+
when NilClass
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
Siblings.new(nodes: children, parent: self)
|
34
|
+
end
|
38
35
|
dirty!
|
39
|
-
if Siblings === children || children.nil?
|
40
|
-
@children = children
|
41
|
-
@children.parent = self if @children
|
42
|
-
else
|
43
|
-
@children = Siblings.new(nodes: children, parent: self)
|
44
|
-
end
|
45
36
|
end
|
46
37
|
|
47
38
|
def each(&block)
|
@@ -88,19 +79,6 @@ module I18n::Tasks::Data::Tree
|
|
88
79
|
@data.present?
|
89
80
|
end
|
90
81
|
|
91
|
-
# do not use directly. use parent.append(node) instead
|
92
|
-
def parent=(value)
|
93
|
-
return if @parent == value
|
94
|
-
@parent.children.remove!(self) if @parent.try(:children) && @parent.children != value.children
|
95
|
-
@parent = value
|
96
|
-
dirty!
|
97
|
-
@parent
|
98
|
-
end
|
99
|
-
|
100
|
-
def siblings
|
101
|
-
parent.children
|
102
|
-
end
|
103
|
-
|
104
82
|
def get(key)
|
105
83
|
children.get(key)
|
106
84
|
end
|
@@ -151,11 +129,7 @@ module I18n::Tasks::Data::Tree
|
|
151
129
|
end
|
152
130
|
|
153
131
|
def to_siblings
|
154
|
-
|
155
|
-
parent.children
|
156
|
-
else
|
157
|
-
Siblings.new(nodes: [self])
|
158
|
-
end
|
132
|
+
parent.try(:children) || Siblings.new(nodes: [self])
|
159
133
|
end
|
160
134
|
|
161
135
|
def to_hash
|
@@ -201,7 +175,7 @@ module I18n::Tasks::Data::Tree
|
|
201
175
|
def from_key_value(key, value)
|
202
176
|
Node.new(key: key.try(:to_s)).tap do |node|
|
203
177
|
if value.is_a?(Hash)
|
204
|
-
node.children = Siblings.from_nested_hash(value
|
178
|
+
node.children = Siblings.from_nested_hash(value)
|
205
179
|
else
|
206
180
|
node.value = value
|
207
181
|
end
|
@@ -23,8 +23,12 @@ module I18n::Tasks::Data::Tree
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def derive(new_attr = {})
|
26
|
-
attr = attributes.merge(new_attr)
|
27
|
-
|
26
|
+
attr = attributes.except(:nodes, :parent).merge(new_attr)
|
27
|
+
if self.parent
|
28
|
+
new_attr[:parent] ||= Node.null
|
29
|
+
end
|
30
|
+
node_attr = new_attr.slice(:parent)
|
31
|
+
attr[:nodes] ||= @list.map { |node| node.derive(node_attr) }
|
28
32
|
self.class.new(attr)
|
29
33
|
end
|
30
34
|
|
@@ -11,29 +11,31 @@ module I18n::Tasks::Data::Tree
|
|
11
11
|
|
12
12
|
def initialize(opts = {})
|
13
13
|
super(nodes: opts[:nodes])
|
14
|
-
@
|
15
|
-
@parent
|
16
|
-
|
14
|
+
@parent = opts[:parent] || first.try(:parent)
|
15
|
+
@list.map! { |node| node.parent == @parent ? node : node.derive(parent: @parent) }
|
16
|
+
@key_to_node = @list.inject({}) { |h, node| h[node.key] = node; h }
|
17
17
|
end
|
18
18
|
|
19
19
|
def attributes
|
20
20
|
super.merge(parent: @parent)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def rename_key(key, new_key)
|
24
|
+
node = key_to_node.delete(key)
|
25
|
+
replace_node! node, node.derive(key: new_key)
|
26
|
+
self
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
29
|
+
def replace_node!(node, new_node)
|
30
|
+
@list[@list.index(node)] = new_node
|
31
|
+
key_to_node[new_node.key] = new_node
|
32
32
|
end
|
33
33
|
|
34
|
+
include SplitKey
|
35
|
+
|
34
36
|
# @return [Node] by full key
|
35
37
|
def get(full_key)
|
36
|
-
first_key, rest = full_key
|
38
|
+
first_key, rest = split_key(full_key, 2)
|
37
39
|
node = key_to_node[first_key]
|
38
40
|
if rest && node
|
39
41
|
node = node.children.try(:get, rest)
|
@@ -45,20 +47,25 @@ module I18n::Tasks::Data::Tree
|
|
45
47
|
|
46
48
|
# add or replace node by full key
|
47
49
|
def set(full_key, node)
|
48
|
-
|
49
|
-
|
50
|
+
raise 'value should be a I18n::Tasks::Data::Tree::Node' unless node.is_a?(Node)
|
51
|
+
key_part, rest = split_key(full_key, 2)
|
52
|
+
child = key_to_node[key_part]
|
53
|
+
|
50
54
|
if rest
|
51
55
|
unless child
|
52
|
-
child = Node.new(key: key_part)
|
56
|
+
child = Node.new(key: key_part, parent: parent, children: [])
|
53
57
|
append! child
|
54
58
|
end
|
55
|
-
child.children
|
59
|
+
unless child.children
|
60
|
+
warn_add_children_to_leaf child
|
61
|
+
child.children = []
|
62
|
+
end
|
56
63
|
child.children.set rest, node
|
57
|
-
dirty!
|
58
64
|
else
|
59
65
|
remove! child if child
|
60
66
|
append! node
|
61
67
|
end
|
68
|
+
dirty!
|
62
69
|
node
|
63
70
|
end
|
64
71
|
|
@@ -74,12 +81,11 @@ module I18n::Tasks::Data::Tree
|
|
74
81
|
end
|
75
82
|
|
76
83
|
def append!(nodes)
|
77
|
-
nodes.
|
78
|
-
raise "
|
79
|
-
key_to_node[node.key] = node
|
80
|
-
node.parent = parent
|
84
|
+
nodes = nodes.map do |node|
|
85
|
+
raise "already has a child with key '#{node.key}'" if key_to_node.key?(node.key)
|
86
|
+
key_to_node[node.key] = (node.parent == parent ? node : node.derive(parent: parent))
|
81
87
|
end
|
82
|
-
super
|
88
|
+
super(nodes)
|
83
89
|
self
|
84
90
|
end
|
85
91
|
|
@@ -95,7 +101,14 @@ module I18n::Tasks::Data::Tree
|
|
95
101
|
next if our == node
|
96
102
|
our.value = node.value if node.leaf?
|
97
103
|
our.data.merge!(node.data) if node.data?
|
98
|
-
|
104
|
+
if node.children?
|
105
|
+
if our.children
|
106
|
+
our.children.merge!(node.children)
|
107
|
+
else
|
108
|
+
warn_add_children_to_leaf our
|
109
|
+
our.children = node.children
|
110
|
+
end
|
111
|
+
end
|
99
112
|
else
|
100
113
|
key_to_node[node.key] = node.derive(parent: parent)
|
101
114
|
end
|
@@ -109,12 +122,22 @@ module I18n::Tasks::Data::Tree
|
|
109
122
|
derive.merge!(nodes)
|
110
123
|
end
|
111
124
|
|
112
|
-
def
|
113
|
-
|
114
|
-
|
125
|
+
def set_root_key(new_key, data = nil)
|
126
|
+
return self if empty?
|
127
|
+
rename_key first.key, new_key
|
128
|
+
leaves { |node| node.data.merge! data } if data
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def warn_add_children_to_leaf(node)
|
135
|
+
::I18n::Tasks::Logging.log_warn "'#{node.full_key}' was a leaf, now has children (value <- scope conflict)"
|
115
136
|
end
|
116
137
|
|
117
138
|
class << self
|
139
|
+
include SplitKey
|
140
|
+
|
118
141
|
def null
|
119
142
|
new
|
120
143
|
end
|
@@ -124,14 +147,15 @@ module I18n::Tasks::Data::Tree
|
|
124
147
|
parse_parent_opt!(opts)
|
125
148
|
forest = Siblings.new(opts)
|
126
149
|
block.call(forest) if block
|
127
|
-
forest.parent.children = forest
|
150
|
+
# forest.parent.children = forest
|
151
|
+
forest
|
128
152
|
end
|
129
153
|
|
130
154
|
def from_key_attr(key_attrs, opts = {}, &block)
|
131
155
|
build_forest(opts) { |forest|
|
132
156
|
key_attrs.each { |(full_key, attr)|
|
133
157
|
raise "Invalid key #{full_key.inspect}" if full_key.end_with?('.')
|
134
|
-
node = Node.new(attr.merge(key: full_key
|
158
|
+
node = Node.new(attr.merge(key: split_key(full_key).last))
|
135
159
|
block.call(full_key, node) if block
|
136
160
|
forest[full_key] = node
|
137
161
|
}
|
@@ -141,7 +165,7 @@ module I18n::Tasks::Data::Tree
|
|
141
165
|
def from_key_names(keys, opts = {}, &block)
|
142
166
|
build_forest(opts) { |forest|
|
143
167
|
keys.each { |full_key|
|
144
|
-
node = Node.new(key: full_key
|
168
|
+
node = Node.new(key: split_key(full_key).last)
|
145
169
|
block.call(full_key, node) if block
|
146
170
|
forest[full_key] = node
|
147
171
|
}
|
@@ -162,7 +186,7 @@ module I18n::Tasks::Data::Tree
|
|
162
186
|
def from_flat_pairs(pairs)
|
163
187
|
Siblings.new.tap do |siblings|
|
164
188
|
pairs.each { |full_key, value|
|
165
|
-
siblings[full_key] = Node.new(key: full_key.
|
189
|
+
siblings[full_key] = Node.new(key: split_key(full_key).last, value: value)
|
166
190
|
}
|
167
191
|
end
|
168
192
|
end
|
@@ -64,8 +64,10 @@ module I18n::Tasks::Data::Tree
|
|
64
64
|
keys(opts).map { |key, node| [key, node.value] }
|
65
65
|
end
|
66
66
|
|
67
|
-
def root_key_values
|
68
|
-
keys(root: false).map { |key, node| [node.root.key, key, node.value]}
|
67
|
+
def root_key_values(sort = false)
|
68
|
+
result = keys(root: false).map { |key, node| [node.root.key, key, node.value]}
|
69
|
+
result.sort! { |a, b| a[0] != b[0] ? a[0] <=> b[0] : a[1] <=> b[1] } if sort
|
70
|
+
result
|
69
71
|
end
|
70
72
|
|
71
73
|
#-- modify / derive
|
@@ -5,9 +5,12 @@ module I18n::Tasks
|
|
5
5
|
value = opts[:value] || ''
|
6
6
|
base = opts[:base_locale] || base_locale
|
7
7
|
locales_for_update(opts).each do |locale|
|
8
|
-
m =
|
8
|
+
m = missing_keys(locales: [locale], base_locale: base).keys { |key, node|
|
9
9
|
node.value = value.respond_to?(:call) ? value.call(key, locale, node) : value
|
10
|
-
|
10
|
+
if node.data.key?(:path)
|
11
|
+
# set path hint for the router
|
12
|
+
node.data.update path: LocalePathname.replace_locale(node.data[:path], node.data[:locale], locale), locale: locale
|
13
|
+
end
|
11
14
|
}
|
12
15
|
data[locale] = data[locale].merge! m
|
13
16
|
end
|
@@ -7,7 +7,7 @@ module I18n::Tasks::IgnoreKeys
|
|
7
7
|
key =~ ignore_pattern(ignore_type, locale)
|
8
8
|
end
|
9
9
|
|
10
|
-
# @param type [:missing, :unused, :eq_base] type
|
10
|
+
# @param type [nil, :missing, :unused, :eq_base] type
|
11
11
|
# @param locale [String] only when type is :eq_base
|
12
12
|
# @return [Regexp] a regexp that matches all the keys ignored for the type (and locale)
|
13
13
|
def ignore_pattern(type, locale = nil)
|
data/lib/i18n/tasks/logging.rb
CHANGED
@@ -2,55 +2,98 @@
|
|
2
2
|
module I18n::Tasks
|
3
3
|
module MissingKeys
|
4
4
|
def missing_keys_types
|
5
|
-
@missing_keys_types ||= [:
|
5
|
+
@missing_keys_types ||= [:used, :diff]
|
6
6
|
end
|
7
7
|
|
8
|
-
# @param [:
|
8
|
+
# @param [:missing_used, :missing_diff] type (default nil)
|
9
9
|
# @return [Siblings]
|
10
10
|
def missing_keys(opts = {})
|
11
11
|
locales = Array(opts[:locales]).presence || self.locales
|
12
|
-
types = Array(opts[:
|
12
|
+
types = (Array(opts[:types]).presence || missing_keys_types).map(&:to_s)
|
13
|
+
validate_missing_types! types
|
14
|
+
base = opts[:base_locale] || base_locale
|
15
|
+
tree = Data::Tree::Siblings.new
|
13
16
|
|
14
|
-
types.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
types.each do |type|
|
18
|
+
tree.merge! send(:"missing_#{type}_forest", locales, base)
|
19
|
+
end
|
20
|
+
tree
|
21
|
+
end
|
22
|
+
|
23
|
+
def eq_base_keys(opts = {})
|
24
|
+
locales = Array(opts[:locales]).presence || self.locales
|
25
|
+
(locales - [base_locale]).inject(Data::Tree::Siblings.new) { |tree, locale|
|
26
|
+
tree.merge! equal_values_tree(locale, base_locale)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def missing_diff_forest(locales, base = base_locale)
|
31
|
+
tree = Data::Tree::Siblings.new
|
32
|
+
# present in base but not locale
|
33
|
+
(locales - [base]).each { |locale|
|
34
|
+
tree.merge! missing_diff_tree(locale, base)
|
35
|
+
}
|
36
|
+
if locales.include?(base)
|
37
|
+
# present in locale but not base
|
38
|
+
(self.locales - [base]).each { |locale|
|
39
|
+
tree.merge! missing_diff_tree(base, locale).set_root_key(base)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
tree
|
43
|
+
end
|
44
|
+
|
45
|
+
def missing_used_forest(locales, base = base_locale)
|
46
|
+
if locales.include?(base)
|
47
|
+
missing_used_tree(base)
|
48
|
+
else
|
49
|
+
Data::Tree::Siblings.new
|
50
|
+
end
|
24
51
|
end
|
25
52
|
|
26
|
-
def missing_tree(locale, compared_to
|
53
|
+
def missing_tree(locale, compared_to)
|
27
54
|
if locale == compared_to
|
28
|
-
|
29
|
-
set_locale_tree_type used_tree.select_keys { |key, node|
|
30
|
-
!(key_expression?(key) || key_value?(key, locale) || ignore_key?(key, :missing))
|
31
|
-
}, locale, :missing_from_base
|
55
|
+
missing_used_tree locale
|
32
56
|
else
|
33
|
-
|
34
|
-
collapse_plural_nodes! set_locale_tree_type data[compared_to].select_keys { |key, node|
|
35
|
-
!key_value?(key, locale) && !ignore_key?(key, :missing)
|
36
|
-
}, locale, :missing_from_locale
|
57
|
+
missing_diff_tree locale, compared_to
|
37
58
|
end
|
38
59
|
end
|
39
60
|
|
40
|
-
|
61
|
+
# keys present in compared_to, but not in locale
|
62
|
+
def missing_diff_tree(locale, compared_to = base_locale)
|
63
|
+
data[compared_to].select_keys { |key, _node|
|
64
|
+
locale_key_missing?(locale, key)
|
65
|
+
}.set_root_key(locale, type: :missing_diff).tap { |t| collapse_plural_nodes!(t) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# keys used in the code missing translations in locale
|
69
|
+
def missing_used_tree(locale)
|
70
|
+
used_tree.select_keys { |key, _node|
|
71
|
+
!key_expression?(key) && locale_key_missing?(locale, key)
|
72
|
+
}.set_root_key(locale, type: :missing_used)
|
73
|
+
end
|
74
|
+
|
75
|
+
def equal_values_tree(locale, compare_to = base_locale)
|
41
76
|
base = data[compare_to].first.children
|
42
|
-
|
77
|
+
data[locale].select_keys(root: false) { |key, node|
|
43
78
|
other_node = base[key]
|
44
79
|
other_node && node.value == other_node.value && !ignore_key?(key, :eq_base, locale)
|
45
|
-
}
|
80
|
+
}.set_root_key(locale, type: :eq_base)
|
46
81
|
end
|
47
82
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
83
|
+
def locale_key_missing?(locale, key)
|
84
|
+
!key_value?(key, locale) && !ignore_key?(key, :missing)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def validate_missing_types!(types)
|
90
|
+
valid_types = missing_keys_types.map(&:to_s)
|
91
|
+
types = types.map(&:to_s)
|
92
|
+
invalid_types = types - valid_types
|
93
|
+
if invalid_types.present?
|
94
|
+
raise CommandError.new("Unknown types: #{invalid_types * ', '}. Valid types are: #{valid_types * ', '}.")
|
95
|
+
end
|
96
|
+
true
|
54
97
|
end
|
55
98
|
end
|
56
99
|
end
|