i18n-tasks 0.4.5 → 0.5.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.
- checksums.yaml +4 -4
- data/.travis.yml +0 -4
- data/CHANGES.md +7 -0
- data/README.md +10 -14
- data/i18n-tasks.gemspec +1 -1
- data/lib/i18n/tasks.rb +0 -2
- data/lib/i18n/tasks/base_task.rb +4 -2
- data/lib/i18n/tasks/commands.rb +14 -14
- data/lib/i18n/tasks/configuration.rb +10 -2
- data/lib/i18n/tasks/console_context.rb +73 -0
- data/lib/i18n/tasks/data.rb +0 -47
- data/lib/i18n/tasks/data/adapter/yaml_adapter.rb +6 -1
- data/lib/i18n/tasks/data/file_system_base.rb +1 -1
- data/lib/i18n/tasks/data/router/conservative_router.rb +5 -5
- data/lib/i18n/tasks/data/router/pattern_router.rb +2 -2
- data/lib/i18n/tasks/data/tree/node.rb +47 -36
- data/lib/i18n/tasks/data/tree/nodes.rb +0 -4
- data/lib/i18n/tasks/data/tree/siblings.rb +54 -9
- data/lib/i18n/tasks/data/tree/traversal.rb +62 -23
- data/lib/i18n/tasks/fill_tasks.rb +29 -21
- data/lib/i18n/tasks/ignore_keys.rb +1 -1
- data/lib/i18n/tasks/key_pattern_matching.rb +17 -0
- data/lib/i18n/tasks/missing_keys.rb +39 -44
- data/lib/i18n/tasks/plural_keys.rb +14 -1
- data/lib/i18n/tasks/reports/base.rb +28 -8
- data/lib/i18n/tasks/reports/spreadsheet.rb +9 -8
- data/lib/i18n/tasks/reports/terminal.rb +33 -29
- data/lib/i18n/tasks/scanners/base_scanner.rb +22 -14
- data/lib/i18n/tasks/scanners/pattern_scanner.rb +2 -1
- data/lib/i18n/tasks/unused_keys.rb +13 -13
- data/lib/i18n/tasks/used_keys.rb +39 -38
- data/lib/i18n/tasks/version.rb +1 -1
- data/spec/i18n_tasks_spec.rb +41 -40
- data/spec/locale_tree/siblings_spec.rb +26 -1
- data/spec/support/i18n_tasks_output_matcher.rb +4 -1
- data/spec/support/trees.rb +6 -1
- data/spec/used_keys_spec.rb +23 -15
- metadata +4 -11
- data/lib/i18n/tasks/file_structure.rb +0 -19
- data/lib/i18n/tasks/key.rb +0 -48
- data/lib/i18n/tasks/key/key_group.rb +0 -45
- data/lib/i18n/tasks/key/match_pattern.rb +0 -24
- data/lib/i18n/tasks/key/usages.rb +0 -12
- data/lib/i18n/tasks/key_group.rb +0 -68
- data/spec/key_group_spec.rb +0 -49
data/lib/i18n/tasks/used_keys.rb
CHANGED
@@ -2,51 +2,52 @@
|
|
2
2
|
require 'find'
|
3
3
|
require 'i18n/tasks/scanners/pattern_with_scope_scanner'
|
4
4
|
|
5
|
-
module I18n::Tasks
|
5
|
+
module I18n::Tasks
|
6
|
+
module UsedKeys
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
else
|
20
|
-
@used_keys ||= used_keys_group scanner.keys
|
21
|
-
end
|
8
|
+
# find all keys in the source (relative keys are absolutized)
|
9
|
+
# @option opts [false|true] :source_locations
|
10
|
+
# @option opts [String] :key_filter
|
11
|
+
# @return [Array<String>]
|
12
|
+
def used_tree(opts = {})
|
13
|
+
return scanner.with_key_filter(opts[:key_filter]) { used_tree(opts.except(:key_filter)) } if opts[:key_filter]
|
14
|
+
key_attrs = opts[:source_locations] ? scanner.keys_with_source_locations : scanner.keys
|
15
|
+
Data::Tree::Node.new(
|
16
|
+
key: 'used',
|
17
|
+
data: {key_filter: scanner.key_filter},
|
18
|
+
children: Data::Tree::Siblings.from_key_attr(key_attrs)
|
19
|
+
).to_siblings
|
22
20
|
end
|
23
|
-
end
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
def scanner
|
23
|
+
@scanner ||= begin
|
24
|
+
search_config = (config[:search] || {}).with_indifferent_access
|
25
|
+
class_name = search_config[:scanner] || '::I18n::Tasks::Scanners::PatternWithScopeScanner'
|
26
|
+
class_name.constantize.new search_config.merge(relative_roots: relative_roots)
|
27
|
+
end
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
search_config = (config[:search] || {}).with_indifferent_access
|
32
|
-
class_name = search_config[:scanner] || '::I18n::Tasks::Scanners::PatternWithScopeScanner'
|
33
|
-
class_name.constantize.new search_config.merge(relative_roots: relative_roots)
|
30
|
+
def used_key_names
|
31
|
+
@used_key_names ||= used_tree.key_names
|
34
32
|
end
|
35
|
-
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
# whether the key is used in the source
|
35
|
+
def used_key?(key)
|
36
|
+
used_key_names.include?(key)
|
37
|
+
end
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
# @return whether the key is potentially used in a code expression such as:
|
40
|
+
# t("category.#{category_key}")
|
41
|
+
def used_in_expr?(key)
|
42
|
+
!!(key =~ expr_key_re)
|
43
|
+
end
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
# keys in the source that end with a ., e.g. t("category.#{cat.i18n_key}") or t("category." + category.key)
|
46
|
+
def expr_key_re
|
47
|
+
@expr_key_re ||= begin
|
48
|
+
patterns = used_key_names.select { |k| key_expression?(k) }.map { |k| key_match_pattern(k) }
|
49
|
+
compile_key_pattern "{#{patterns * ','}}"
|
50
|
+
end
|
51
|
+
end
|
51
52
|
end
|
52
53
|
end
|
data/lib/i18n/tasks/version.rb
CHANGED
data/spec/i18n_tasks_spec.rb
CHANGED
@@ -27,7 +27,7 @@ describe 'i18n-tasks' do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
let(:expected_unused_keys) { %w(unused.a unused.numeric unused.plural) }
|
30
|
+
let(:expected_unused_keys) { %w(unused.a unused.numeric unused.plural).map { |k| %w(en es).map { |l| "#{l}.#{k}" } }.reduce(:+) }
|
31
31
|
describe 'unused' do
|
32
32
|
it 'detects unused' do
|
33
33
|
capture_stderr do
|
@@ -40,7 +40,8 @@ describe 'i18n-tasks' do
|
|
40
40
|
it 'removes unused' do
|
41
41
|
in_test_app_dir do
|
42
42
|
t = i18n_task
|
43
|
-
expected_unused_keys.
|
43
|
+
unused = expected_unused_keys.map { |k| k.split('.', 2)[1] }
|
44
|
+
unused.each do |key|
|
44
45
|
expect(t.key_value?(key, :en)).to be true
|
45
46
|
expect(t.key_value?(key, :es)).to be true
|
46
47
|
end
|
@@ -49,7 +50,7 @@ describe 'i18n-tasks' do
|
|
49
50
|
run_cmd :remove_unused
|
50
51
|
}
|
51
52
|
t.data.reload
|
52
|
-
|
53
|
+
unused.each do |key|
|
53
54
|
expect(t.key_value?(key, :en)).to be false
|
54
55
|
expect(t.key_value?(key, :es)).to be false
|
55
56
|
end
|
@@ -139,7 +140,7 @@ describe 'i18n-tasks' do
|
|
139
140
|
used.a 2
|
140
141
|
app/views/usages.html.slim:1 p = t 'used.a'
|
141
142
|
app/views/usages.html.slim:2 b = t 'used.a'
|
142
|
-
TXT
|
143
|
+
TXT
|
143
144
|
end
|
144
145
|
end
|
145
146
|
end
|
@@ -151,53 +152,53 @@ TXT
|
|
151
152
|
gen_data = ->(v) {
|
152
153
|
v_num = v.chars.map(&:ord).join('').to_i
|
153
154
|
{
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
155
|
+
'ca' => {'a' => v, 'b' => v, 'c' => v, 'd' => v, 'e' => "#{v}%{i}", 'f' => "#{v}%{i}"},
|
156
|
+
'cb' => {'a' => v, 'b' => "#{v}%{i}"},
|
157
|
+
'hash' => {
|
158
|
+
'pattern' => {'a' => v},
|
159
|
+
'pattern2' => {'a' => v},
|
160
|
+
},
|
161
|
+
'unused' => {'a' => v, 'numeric' => v_num, 'plural' => {'one' => v, 'other' => v}},
|
162
|
+
'ignore_unused' => {'a' => v},
|
163
|
+
'missing_in_es' => {'a' => v},
|
164
|
+
'missing_in_es_plural_1' => {'a' => {'one' => v, 'other' => v}},
|
165
|
+
'missing_in_es_plural_2' => {'a' => {'one' => v, 'other' => v}},
|
166
|
+
'same_in_es' => {'a' => v},
|
167
|
+
'ignore_eq_base_all' => {'a' => v},
|
168
|
+
'ignore_eq_base_es' => {'a' => v},
|
169
|
+
'blank_in_es' => {'a' => v},
|
170
|
+
'relative' => {
|
171
|
+
'index' => {
|
172
|
+
'title' => v,
|
173
|
+
'description' => v,
|
174
|
+
'summary' => v,
|
175
|
+
}
|
176
|
+
},
|
177
|
+
'numeric' => {'a' => v_num},
|
178
|
+
'plural' => {'a' => {'one' => v, 'other' => "%{count} #{v}s"}},
|
179
|
+
'devise' => {'a' => v},
|
180
|
+
'scoped' => {'x' => v},
|
181
|
+
'very' => {'scoped' => {'x' => v}},
|
182
|
+
'used' => {'a' => v}
|
182
183
|
}.tap { |r|
|
183
184
|
gen = r["bench"] = {}
|
184
185
|
BENCH_KEYS.times { |i| gen["key#{i}"] = v }
|
185
186
|
}
|
186
187
|
}
|
187
188
|
|
188
|
-
en_data
|
189
|
-
es_data
|
189
|
+
en_data = gen_data.('EN_TEXT')
|
190
|
+
es_data = gen_data.('ES_TEXT').except(
|
190
191
|
'missing_in_es', 'missing_in_es_plural_1', 'missing_in_es_plural_2')
|
191
|
-
es_data['same_in_es']['a']
|
192
|
-
es_data['blank_in_es']['a']
|
192
|
+
es_data['same_in_es']['a'] = 'EN_TEXT'
|
193
|
+
es_data['blank_in_es']['a'] = ''
|
193
194
|
es_data['ignore_eq_base_all']['a'] = 'EN_TEXT'
|
194
195
|
es_data['ignore_eq_base_es']['a'] = 'EN_TEXT'
|
195
196
|
|
196
197
|
fs = fixtures_contents.merge(
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
198
|
+
'config/locales/en.yml' => {'en' => en_data}.to_yaml,
|
199
|
+
'config/locales/es.yml' => {'es' => es_data}.to_yaml,
|
200
|
+
# test that our algorithms can scale to the order of {BENCH_KEYS} keys.
|
201
|
+
'vendor/heavy.file' => BENCH_KEYS.times.map { |i| "t('bench.key#{i}') " }.join
|
201
202
|
)
|
202
203
|
|
203
204
|
TestCodebase.setup fs
|
@@ -3,6 +3,18 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe 'Tree siblings / forest' do
|
5
5
|
|
6
|
+
context 'Node' do
|
7
|
+
it '::new with children' do
|
8
|
+
children = I18n::Tasks::Data::Tree::Siblings.from_key_attr([['a', value: 1]])
|
9
|
+
#require 'byebug'; byebug
|
10
|
+
node = I18n::Tasks::Data::Tree::Node.new(
|
11
|
+
key: 'fr',
|
12
|
+
children: children
|
13
|
+
)
|
14
|
+
expect(node.to_siblings.first.children.first.parent.key).to eq 'fr'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
6
18
|
context 'a tree' do
|
7
19
|
let(:a_hash) { {a: 1, b: {ba: 1, bb: 2}}.deep_stringify_keys }
|
8
20
|
|
@@ -22,9 +34,22 @@ describe 'Tree siblings / forest' do
|
|
22
34
|
end
|
23
35
|
|
24
36
|
it '#merge' do
|
25
|
-
a
|
37
|
+
a = build_tree(a_hash)
|
26
38
|
b_hash = {b: {bc: 1}, c: 1}.deep_stringify_keys
|
27
39
|
expect(a.merge(build_tree(b_hash)).to_hash).to eq(a_hash.deep_merge(b_hash))
|
28
40
|
end
|
41
|
+
|
42
|
+
it '#intersect' do
|
43
|
+
x = {a: 1, b: {ba: 1, bb: 2}}
|
44
|
+
y = {b: {ba: 1, bc: 3}, c: 1}
|
45
|
+
intersection = {b: {ba: 1}}.deep_stringify_keys
|
46
|
+
a = build_tree(x)
|
47
|
+
b = build_tree(y)
|
48
|
+
expect(a.intersect_keys(b, root: true).to_hash).to eq(intersection)
|
49
|
+
end
|
50
|
+
|
51
|
+
it '#select_keys' do
|
52
|
+
expect(build_tree(a: 1, b: 1).select_keys {|k, node| k == 'b'}.to_hash).to eq({'b' => 1})
|
53
|
+
end
|
29
54
|
end
|
30
55
|
end
|
@@ -11,9 +11,12 @@ RSpec::Matchers.define :be_i18n_keys do |expected|
|
|
11
11
|
row.gsub(/(?:\s|^)\|(?:\s|$)/, ' ').gsub(/\s+/, ' ').strip.split(' ').map(&:presence).compact
|
12
12
|
}
|
13
13
|
return [] if actual.empty?
|
14
|
-
if actual[0][1] =~ /[✗∅=]/
|
14
|
+
if actual[0][1] =~ /([✗∅=])/
|
15
15
|
locale_col = 0
|
16
16
|
key_col = 2
|
17
|
+
elsif actual[0].length == 3
|
18
|
+
locale_col = 0
|
19
|
+
key_col = 1
|
17
20
|
else
|
18
21
|
key_col = 0
|
19
22
|
end
|
data/spec/support/trees.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
module Trees
|
3
|
+
def expect_node_key_data(node, key, data)
|
4
|
+
expect(node.full_key(root: false)).to eq key
|
5
|
+
expect(node.data).to eq data
|
6
|
+
end
|
7
|
+
|
3
8
|
def build_tree(hash)
|
4
|
-
I18n::Tasks::Data::Tree::Siblings.from_nested_hash(hash)
|
9
|
+
I18n::Tasks::Data::Tree::Siblings.from_nested_hash(hash.deep_stringify_keys)
|
5
10
|
end
|
6
11
|
end
|
data/spec/used_keys_spec.rb
CHANGED
@@ -15,26 +15,34 @@ h1 = t 'b'
|
|
15
15
|
TestCodebase.teardown
|
16
16
|
end
|
17
17
|
|
18
|
-
it '#used_keys(
|
19
|
-
|
20
|
-
|
21
|
-
expect(
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
it '#used_keys(source_locations: true)' do
|
19
|
+
used = task.used_tree(source_locations: true)
|
20
|
+
leaves = used.leaves.to_a
|
21
|
+
expect(leaves.size).to eq 2
|
22
|
+
expect_node_key_data(
|
23
|
+
leaves[0],
|
24
|
+
'a',
|
25
|
+
source_locations:
|
26
|
+
[{pos: 6, line_num: 1, line_pos: 7, line: "div = t 'a'", path: 'a.html.slim'},
|
27
|
+
{pos: 18, line_num: 2, line_pos: 7, line: " p = t 'a'", path: 'a.html.slim'}]
|
25
28
|
)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
|
30
|
+
expect_node_key_data(
|
31
|
+
leaves[1],
|
32
|
+
'b',
|
33
|
+
source_locations:
|
34
|
+
[{pos: 29, line_num: 3, line_pos: 6, line: "h1 = t 'b'", path: 'a.html.slim'}]
|
29
35
|
)
|
30
36
|
end
|
31
37
|
|
32
|
-
it '#used_keys(
|
33
|
-
used_keys = task.
|
38
|
+
it '#used_keys(source_locations: true, key_filter: "b*")' do
|
39
|
+
used_keys = task.used_tree(key_filter: 'b*', source_locations: true)
|
34
40
|
expect(used_keys.size).to eq 1
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
expect_node_key_data(
|
42
|
+
used_keys.leaves.first,
|
43
|
+
'b',
|
44
|
+
source_locations:
|
45
|
+
[{pos: 29, line_num: 3, line_pos: 6, line: "h1 = t 'b'", path: 'a.html.slim'}]
|
38
46
|
)
|
39
47
|
end
|
40
48
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- glebm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: erubis
|
@@ -180,7 +180,7 @@ dependencies:
|
|
180
180
|
version: '0'
|
181
181
|
description: |2
|
182
182
|
|
183
|
-
i18n-tasks
|
183
|
+
i18n-tasks helps you find and manage missing and unused translations.
|
184
184
|
|
185
185
|
It scans calls such as `I18n.t('some.key')` and provides reports on key usage, missing, and unused keys.
|
186
186
|
It can also can pre-fill missing keys, including from Google Translate, and it can remove unused keys as well.
|
@@ -210,6 +210,7 @@ files:
|
|
210
210
|
- lib/i18n/tasks/commands.rb
|
211
211
|
- lib/i18n/tasks/commands_base.rb
|
212
212
|
- lib/i18n/tasks/configuration.rb
|
213
|
+
- lib/i18n/tasks/console_context.rb
|
213
214
|
- lib/i18n/tasks/data.rb
|
214
215
|
- lib/i18n/tasks/data/adapter/json_adapter.rb
|
215
216
|
- lib/i18n/tasks/data/adapter/yaml_adapter.rb
|
@@ -222,15 +223,9 @@ files:
|
|
222
223
|
- lib/i18n/tasks/data/tree/nodes.rb
|
223
224
|
- lib/i18n/tasks/data/tree/siblings.rb
|
224
225
|
- lib/i18n/tasks/data/tree/traversal.rb
|
225
|
-
- lib/i18n/tasks/file_structure.rb
|
226
226
|
- lib/i18n/tasks/fill_tasks.rb
|
227
227
|
- lib/i18n/tasks/google_translation.rb
|
228
228
|
- lib/i18n/tasks/ignore_keys.rb
|
229
|
-
- lib/i18n/tasks/key.rb
|
230
|
-
- lib/i18n/tasks/key/key_group.rb
|
231
|
-
- lib/i18n/tasks/key/match_pattern.rb
|
232
|
-
- lib/i18n/tasks/key/usages.rb
|
233
|
-
- lib/i18n/tasks/key_group.rb
|
234
229
|
- lib/i18n/tasks/key_pattern_matching.rb
|
235
230
|
- lib/i18n/tasks/logging.rb
|
236
231
|
- lib/i18n/tasks/missing_keys.rb
|
@@ -255,7 +250,6 @@ files:
|
|
255
250
|
- spec/fixtures/config/i18n-tasks.yml
|
256
251
|
- spec/google_translate_spec.rb
|
257
252
|
- spec/i18n_tasks_spec.rb
|
258
|
-
- spec/key_group_spec.rb
|
259
253
|
- spec/key_pattern_matching_spec.rb
|
260
254
|
- spec/locale_tree/siblings_spec.rb
|
261
255
|
- spec/pattern_scanner_spec.rb
|
@@ -307,7 +301,6 @@ test_files:
|
|
307
301
|
- spec/fixtures/config/i18n-tasks.yml
|
308
302
|
- spec/google_translate_spec.rb
|
309
303
|
- spec/i18n_tasks_spec.rb
|
310
|
-
- spec/key_group_spec.rb
|
311
304
|
- spec/key_pattern_matching_spec.rb
|
312
305
|
- spec/locale_tree/siblings_spec.rb
|
313
306
|
- spec/pattern_scanner_spec.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module I18n::Tasks::FileStructure
|
3
|
-
def identify(routes = data.config.read)
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
|
8
|
-
class NonLeafVisitor
|
9
|
-
def visit(node)
|
10
|
-
puts "non-leaf: #{node}"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class LeafVisitor
|
15
|
-
def visit(node)
|
16
|
-
puts "leaf: #{node}"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/lib/i18n/tasks/key.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
require 'i18n/tasks/key/key_group'
|
3
|
-
require 'i18n/tasks/key/match_pattern'
|
4
|
-
require 'i18n/tasks/key/usages'
|
5
|
-
|
6
|
-
module I18n
|
7
|
-
module Tasks
|
8
|
-
# Container for i18n key and its attributes
|
9
|
-
class Key
|
10
|
-
include ::I18n::Tasks::Key::KeyGroup
|
11
|
-
include ::I18n::Tasks::Key::MatchPattern
|
12
|
-
include ::I18n::Tasks::Key::Usages
|
13
|
-
|
14
|
-
attr_accessor :own_attr
|
15
|
-
|
16
|
-
# @param [Array<Key, Value>|Hash|String] key_or_attr
|
17
|
-
# @param [Hash] attr optional
|
18
|
-
def initialize(key_or_attr, own_attr = {})
|
19
|
-
@own_attr = if key_or_attr.is_a?(Array)
|
20
|
-
{key: key_or_attr[0], value: key_or_attr[1]}.merge(own_attr)
|
21
|
-
elsif key_or_attr.is_a?(Hash)
|
22
|
-
key_or_attr.merge(own_attr)
|
23
|
-
else
|
24
|
-
(own_attr || {}).merge(key: key_or_attr)
|
25
|
-
end
|
26
|
-
@own_attr[:key] = @own_attr[:key].to_s
|
27
|
-
end
|
28
|
-
|
29
|
-
def ==(other)
|
30
|
-
self.attr == other.attr
|
31
|
-
end
|
32
|
-
|
33
|
-
def inspect
|
34
|
-
"#<#{self.class.name}#{attr.inspect}>"
|
35
|
-
end
|
36
|
-
|
37
|
-
def key
|
38
|
-
@own_attr[:key]
|
39
|
-
end
|
40
|
-
|
41
|
-
alias to_s key
|
42
|
-
|
43
|
-
def value
|
44
|
-
@own_attr[:value]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|