nested_array 0.1.3 → 1.0.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/.byebug_history +18 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +20 -1
- data/bash/build/gem.sh +9 -0
- data/bash/test/gem.sh +11 -0
- data/lib/.byebug_history +10 -0
- data/lib/nested_array/nested.rb +306 -0
- data/lib/nested_array/version.rb +1 -1
- data/lib/nested_array.rb +5 -302
- data/nested_array.gemspec +3 -0
- metadata +50 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b4b7d671b1ccadd0304e5f389cdda7760b06c21065deb0188d2de0fefad7212
|
4
|
+
data.tar.gz: 66eb32ba69f6a5b8e5a5829d71fc2e017f4bf581ad25a48ccd98b71c6354c454
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0418b9d4c451ce95c594e60e9f7e4c00a75b912c2332eb96aefa2d7a7adf262cbd554120359602b5bda955ebef517746b29482c44638dbbc9ff18e26370521c8'
|
7
|
+
data.tar.gz: 3adc0751b0505803a3c7caa7fe6388a67fb31d4674c3e53d2c51cec71b4b59531f16fe9202f20924ca151d879d7a9b8e75bb80bc562a6441a1d85af5750c4a86
|
data/.byebug_history
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
c
|
2
|
+
fixture.first.deep_symbolize_keys
|
3
|
+
fixture.first
|
4
|
+
fixture.deep_symbolize_keys
|
5
|
+
fixture
|
6
|
+
fixture = JSON.parse File.read(fixture_path)
|
7
|
+
File.exist?(fixture_path)
|
8
|
+
fixture_path = Pathname.new(Dir.pwd).join("spec", "fixtures", "json", "#{name}.json")
|
9
|
+
name
|
10
|
+
Dir.pwd
|
11
|
+
b = a.join $0
|
12
|
+
a = Pathname.new Dir.pwd
|
13
|
+
$0
|
14
|
+
Dir.pwd
|
15
|
+
Pathname
|
16
|
+
Dir.entries(File.dirname(__FILE__)).reject{|e| e == '.' || e == '..'}.select{|e| File.directory? e}
|
17
|
+
File.dirname(__FILE__)
|
18
|
+
__FILE__
|
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,20 +1,39 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nested_array (0.
|
4
|
+
nested_array (1.0.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
awesome_print (1.8.0)
|
10
|
+
byebug (11.0.1)
|
11
|
+
diff-lcs (1.3)
|
9
12
|
rake (10.5.0)
|
13
|
+
rspec (3.9.0)
|
14
|
+
rspec-core (~> 3.9.0)
|
15
|
+
rspec-expectations (~> 3.9.0)
|
16
|
+
rspec-mocks (~> 3.9.0)
|
17
|
+
rspec-core (3.9.0)
|
18
|
+
rspec-support (~> 3.9.0)
|
19
|
+
rspec-expectations (3.9.0)
|
20
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
21
|
+
rspec-support (~> 3.9.0)
|
22
|
+
rspec-mocks (3.9.0)
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
+
rspec-support (~> 3.9.0)
|
25
|
+
rspec-support (3.9.0)
|
10
26
|
|
11
27
|
PLATFORMS
|
12
28
|
ruby
|
13
29
|
|
14
30
|
DEPENDENCIES
|
31
|
+
awesome_print (~> 1.8)
|
15
32
|
bundler (~> 2.0)
|
33
|
+
byebug (~> 11.0)
|
16
34
|
nested_array!
|
17
35
|
rake (~> 10.0)
|
36
|
+
rspec (~> 3.9)
|
18
37
|
|
19
38
|
BUNDLED WITH
|
20
39
|
2.0.1
|
data/bash/build/gem.sh
ADDED
data/bash/test/gem.sh
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -eu
|
4
|
+
|
5
|
+
cd "$(dirname "${0}")"
|
6
|
+
|
7
|
+
cd ../..
|
8
|
+
|
9
|
+
# rspec управляет загружаемыми гемами, поэтому сам rspec запускается НЕ `bundle exec rspec`, а просто `rspec`
|
10
|
+
rspec --format doc ./spec/array_spec.rb
|
11
|
+
rspec --format doc ./spec/nested_array_array_spec.rb
|
data/lib/.byebug_history
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
module NestedArray::Nested
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do |recipient|
|
9
|
+
|
10
|
+
NESTED_OPTIONS = {
|
11
|
+
# Имена полей для получения/записи информации, чувствительны к string/symbol
|
12
|
+
id: :id,
|
13
|
+
parent_id: :parent_id,
|
14
|
+
children: :children,
|
15
|
+
level: :level,
|
16
|
+
|
17
|
+
# Параметры для преобразования в nested
|
18
|
+
hashed: false,
|
19
|
+
add_level: false,
|
20
|
+
root_id: nil,
|
21
|
+
|
22
|
+
# Параметры для преобразования в html
|
23
|
+
tabulated: true,
|
24
|
+
inline: false,
|
25
|
+
tab: "\t",
|
26
|
+
ul: '<ul>',
|
27
|
+
_ul: '</ul>',
|
28
|
+
li: '<li>',
|
29
|
+
_li: '</li>',
|
30
|
+
|
31
|
+
# Параматры для "склеивания" вложенных структур
|
32
|
+
path_separator: '-=path_separator=-',
|
33
|
+
path_key: 'text',
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def each_nested options={}
|
38
|
+
options = NESTED_OPTIONS.merge options
|
39
|
+
level = 0
|
40
|
+
cache = []
|
41
|
+
cache[level] = self.clone
|
42
|
+
parents = []
|
43
|
+
parents[level] = nil
|
44
|
+
i = []
|
45
|
+
i[level] = 0
|
46
|
+
while level >= 0
|
47
|
+
node = cache[level][i[level]]
|
48
|
+
i[level]+= 1
|
49
|
+
if node != nil
|
50
|
+
|
51
|
+
yield(node.clone, parents.clone, level)
|
52
|
+
|
53
|
+
if !node[options[:children]].nil? && node[options[:children]].length > 0
|
54
|
+
level+= 1
|
55
|
+
parents[level] = node.clone
|
56
|
+
cache[level] = node[options[:children]]
|
57
|
+
i[level] = 0
|
58
|
+
end
|
59
|
+
else
|
60
|
+
parents[level] = nil
|
61
|
+
level-= 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def each_nested! options={}
|
68
|
+
options = NESTED_OPTIONS.merge options
|
69
|
+
level = 0
|
70
|
+
cache = []
|
71
|
+
cache[level] = self
|
72
|
+
parents = []
|
73
|
+
parents[level] = nil
|
74
|
+
i = []
|
75
|
+
i[level] = 0
|
76
|
+
while level >= 0
|
77
|
+
node = cache[level][i[level]]
|
78
|
+
i[level]+= 1
|
79
|
+
if node != nil
|
80
|
+
|
81
|
+
yield(node, parents, level)
|
82
|
+
|
83
|
+
if !node[options[:children]].nil? && node[options[:children]].length > 0
|
84
|
+
level+= 1
|
85
|
+
parents[level] = node
|
86
|
+
cache[level] = node[options[:children]]
|
87
|
+
i[level] = 0
|
88
|
+
end
|
89
|
+
else
|
90
|
+
parents[level] = nil
|
91
|
+
level-= 1
|
92
|
+
end
|
93
|
+
end
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_nested options={}
|
98
|
+
options = NESTED_OPTIONS.merge options
|
99
|
+
fields = {
|
100
|
+
id: options[:id],
|
101
|
+
parent_id: options[:parent_id],
|
102
|
+
level: options[:level],
|
103
|
+
children: options[:children],
|
104
|
+
}
|
105
|
+
fields.delete :level if !options[:add_level]
|
106
|
+
cache = {}
|
107
|
+
nested = options[:hashed] ? {} : []
|
108
|
+
# Перебираем элементы в любом порядке!
|
109
|
+
self.each do |value|
|
110
|
+
value = value.serializable_hash if !value.is_a? Hash
|
111
|
+
# 1. Если нет родителя текущего элемента, и текущий элемент не корневой, то:
|
112
|
+
# 1.1 создадим родителя
|
113
|
+
# 1.2 поместим в кэш
|
114
|
+
if !(cache.key? value[fields[:parent_id]]) && (value[fields[:parent_id]] != options[:root_id])
|
115
|
+
# 1.1
|
116
|
+
temp = {}
|
117
|
+
fields.each do |key, field|
|
118
|
+
case key
|
119
|
+
when :id
|
120
|
+
temp[field] = value[fields[:parent_id]]
|
121
|
+
when :children
|
122
|
+
# не создаём поле
|
123
|
+
else
|
124
|
+
temp[field] = nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
# 1.2
|
128
|
+
cache[value[fields[:parent_id]]] = temp
|
129
|
+
end
|
130
|
+
# 2. Если текущий элемент уже был создан, значит он был чьим-то родителем, тогда:
|
131
|
+
# 2.1 обновим в нем информацию
|
132
|
+
# 2.2 поместим в родителя
|
133
|
+
if cache.key? value[fields[:id]]
|
134
|
+
# 2.1
|
135
|
+
fields.each do |key, field|
|
136
|
+
case key
|
137
|
+
when :id, :children
|
138
|
+
# не обновляем информацию
|
139
|
+
else
|
140
|
+
cache[value[fields[:id]]][field] = value[field]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
value.keys.each do |field|
|
144
|
+
cache[value[fields[:id]]][field] = value[field] if !(field.in? fields)
|
145
|
+
end
|
146
|
+
# 2.2
|
147
|
+
# Если текущий элемент не корневой - поместим в родителя, беря его из кэш
|
148
|
+
if value[fields[:parent_id]] != options[:root_id]
|
149
|
+
cache[value[fields[:parent_id]]][fields[:children]] ||= options[:hashed] ? {} : []
|
150
|
+
if options[:hashed]
|
151
|
+
cache[value[fields[:parent_id]]][fields[:children]][value[fields[:id]]] = nested[value[fields[:id]]]
|
152
|
+
else
|
153
|
+
cache[value[fields[:parent_id]]][fields[:children]] << cache[value[fields[:id]]]
|
154
|
+
end
|
155
|
+
# иначе, текущий элемент корневой, поместим в nested
|
156
|
+
else
|
157
|
+
if options[:hashed]
|
158
|
+
nested[value[fields[:id]]] = cache[value[fields[:id]]]
|
159
|
+
else
|
160
|
+
nested << cache[value[fields[:id]]]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
# 3. Иначе, текущий элемент не создан, тогда:
|
164
|
+
# 3.1 создадим элемент
|
165
|
+
# 3.2 поместим в кэш
|
166
|
+
# 3.3 поместим в родителя
|
167
|
+
else
|
168
|
+
# 3.1
|
169
|
+
temp = {}
|
170
|
+
fields.each do |key, field|
|
171
|
+
case key
|
172
|
+
when :id
|
173
|
+
temp[field] = value[field]
|
174
|
+
when :parent_id
|
175
|
+
temp[field] = value[field]
|
176
|
+
when :children
|
177
|
+
# ничего не делаем
|
178
|
+
else
|
179
|
+
temp[field] = value[field]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
value.keys.each do |field|
|
183
|
+
temp[field] = value[field] if !(field.in? fields)
|
184
|
+
end
|
185
|
+
# 3.2
|
186
|
+
cache[value[fields[:id]]] = temp
|
187
|
+
# 3.3
|
188
|
+
# Если текущий элемент не корневой - поместим в родителя, беря его из кэш
|
189
|
+
if value[fields[:parent_id]] != options[:root_id]
|
190
|
+
cache[value[fields[:parent_id]]][fields[:children]] ||= options[:hashed] ? {} : []
|
191
|
+
if options[:hashed]
|
192
|
+
cache[value[fields[:parent_id]]][fields[:children]][value[fields[:id]]] = cache[value[fields[:id]]]
|
193
|
+
else
|
194
|
+
cache[value[fields[:parent_id]]][fields[:children]] << cache[value[fields[:id]]]
|
195
|
+
end
|
196
|
+
# иначе, текущий элемент корневой, поместим в nested
|
197
|
+
else
|
198
|
+
if options[:hashed]
|
199
|
+
nested[value[fields[:id]]] = cache[value[fields[:id]]]
|
200
|
+
else
|
201
|
+
nested << cache[value[fields[:id]]]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
if options[:add_level]
|
207
|
+
level = 0
|
208
|
+
cache = []
|
209
|
+
cache[level] = nested
|
210
|
+
i = []
|
211
|
+
i[level] = 0
|
212
|
+
while level >= 0
|
213
|
+
node = cache[level][i[level]]
|
214
|
+
i[level]+= 1
|
215
|
+
if node != nil
|
216
|
+
|
217
|
+
node[options[:level]] = level
|
218
|
+
|
219
|
+
if !node[options[:children]].nil? && node[options[:children]].length > 0
|
220
|
+
level+= 1
|
221
|
+
cache[level] = node[options[:children]]
|
222
|
+
i[level] = 0
|
223
|
+
end
|
224
|
+
else
|
225
|
+
level-= 1
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
nested
|
230
|
+
end
|
231
|
+
|
232
|
+
def nested_to_html options={}
|
233
|
+
options = NESTED_OPTIONS.merge options
|
234
|
+
html = ''
|
235
|
+
level = 0
|
236
|
+
cache = []
|
237
|
+
cache[level] = self.clone
|
238
|
+
parents = []
|
239
|
+
parents[level] = nil
|
240
|
+
i = []
|
241
|
+
i[level] = 0
|
242
|
+
while level >= 0
|
243
|
+
node = cache[level][i[level]]
|
244
|
+
i[level]+= 1
|
245
|
+
if node != nil
|
246
|
+
|
247
|
+
html+= options[:tab] * (level * 2 + 1) if options[:tabulated]
|
248
|
+
html+= options[:li]
|
249
|
+
html+= yield(node.clone, parents.clone, level)
|
250
|
+
|
251
|
+
if !node[:children].nil? && node[:children].length > 0
|
252
|
+
level+= 1
|
253
|
+
html+= "\n" if !options[:inline]
|
254
|
+
html+= options[:tab] * (level * 2) if options[:tabulated]
|
255
|
+
html+= options[:ul]
|
256
|
+
html+= "\n" if !options[:inline]
|
257
|
+
parents[level] = node.clone
|
258
|
+
cache[level] = node[:children]
|
259
|
+
i[level] = 0
|
260
|
+
else
|
261
|
+
html+= options[:_li]
|
262
|
+
html+= "\n" if !options[:inline]
|
263
|
+
end
|
264
|
+
else
|
265
|
+
parents[level] = nil
|
266
|
+
if level > 0
|
267
|
+
html+= options[:tab] * (level * 2) if options[:tabulated]
|
268
|
+
html+= options[:_ul]
|
269
|
+
html+= "\n" if !options[:inline]
|
270
|
+
html+= options[:tab] * (level * 2 - 1) if options[:tabulated]
|
271
|
+
html+= options[:_li]
|
272
|
+
html+= "\n" if !options[:inline]
|
273
|
+
end
|
274
|
+
level-= 1
|
275
|
+
end
|
276
|
+
end
|
277
|
+
html
|
278
|
+
end
|
279
|
+
|
280
|
+
# "Скеивание" вложенных структур
|
281
|
+
# ноды склеиваются если путь к ним одинаков;
|
282
|
+
# путь определяется из сложения Текстов (конфигурируемо через :path_key);
|
283
|
+
def concat_nested tree=nil, options={}
|
284
|
+
options = NESTED_OPTIONS.merge options
|
285
|
+
return self if tree.nil?
|
286
|
+
children_cache = {}
|
287
|
+
tree.each_nested options do |node, parents, level|
|
288
|
+
parent_path_names = parents.compact.map{|e| e[options[:path_key]]}
|
289
|
+
parent_path = parent_path_names.join(options[:path_separator])
|
290
|
+
path = parent_path_names.push(node[options[:path_key]]).join(options[:path_separator])
|
291
|
+
element = node
|
292
|
+
if !children_cache.keys.include? path
|
293
|
+
if parent_path == ''
|
294
|
+
array = self
|
295
|
+
else
|
296
|
+
array = children_cache[parent_path]
|
297
|
+
end
|
298
|
+
element[options[:children]] = []
|
299
|
+
array << element
|
300
|
+
children_cache[parent_path] = array
|
301
|
+
children_cache[path] = element[options[:children]]
|
302
|
+
end
|
303
|
+
end
|
304
|
+
self
|
305
|
+
end
|
306
|
+
end
|
data/lib/nested_array/version.rb
CHANGED
data/lib/nested_array.rb
CHANGED
@@ -1,309 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/all"
|
2
2
|
require "nested_array/version"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
class Error < StandardError
|
7
|
-
end
|
8
|
-
|
9
|
-
extend ActiveSupport::Concern
|
10
|
-
|
11
|
-
included do |recipient|
|
12
|
-
|
13
|
-
NESTED_OPTIONS = {
|
14
|
-
# Имена полей для получения/записи информации, чувствительны к string/symbol
|
15
|
-
id: :id,
|
16
|
-
parent_id: :pid,
|
17
|
-
children: :children,
|
18
|
-
level: :level,
|
19
|
-
|
20
|
-
# Параметры для преобразования в nested
|
21
|
-
hashed: false,
|
22
|
-
add_level: false,
|
23
|
-
root_id: nil,
|
4
|
+
require_relative "nested_array/nested"
|
24
5
|
|
25
|
-
|
26
|
-
tabulated: true,
|
27
|
-
inline: false,
|
28
|
-
tab: "\t",
|
29
|
-
ul: '<ul>',
|
30
|
-
_ul: '</ul>',
|
31
|
-
li: '<li>',
|
32
|
-
_li: '</li>',
|
33
|
-
|
34
|
-
# Параматры для "склеивания" вложенных структур
|
35
|
-
path_separator: '-=path_separator=-',
|
36
|
-
path_key: 'text',
|
37
|
-
}
|
38
|
-
end
|
39
|
-
|
40
|
-
def each_nested options={}
|
41
|
-
options = NESTED_OPTIONS.merge options
|
42
|
-
level = 0
|
43
|
-
cache = []
|
44
|
-
cache[level] = self.clone
|
45
|
-
parents = []
|
46
|
-
parents[level] = nil
|
47
|
-
i = []
|
48
|
-
i[level] = 0
|
49
|
-
while level >= 0
|
50
|
-
node = cache[level][i[level]]
|
51
|
-
i[level]+= 1
|
52
|
-
if node != nil
|
53
|
-
|
54
|
-
yield(node.clone, parents.clone, level)
|
55
|
-
|
56
|
-
if !node[options[:children]].nil? && node[options[:children]].length > 0
|
57
|
-
level+= 1
|
58
|
-
parents[level] = node.clone
|
59
|
-
cache[level] = node[options[:children]]
|
60
|
-
i[level] = 0
|
61
|
-
end
|
62
|
-
else
|
63
|
-
parents[level] = nil
|
64
|
-
level-= 1
|
65
|
-
end
|
66
|
-
end
|
67
|
-
self
|
68
|
-
end
|
69
|
-
|
70
|
-
def each_nested! options={}
|
71
|
-
options = NESTED_OPTIONS.merge options
|
72
|
-
level = 0
|
73
|
-
cache = []
|
74
|
-
cache[level] = self
|
75
|
-
parents = []
|
76
|
-
parents[level] = nil
|
77
|
-
i = []
|
78
|
-
i[level] = 0
|
79
|
-
while level >= 0
|
80
|
-
node = cache[level][i[level]]
|
81
|
-
i[level]+= 1
|
82
|
-
if node != nil
|
83
|
-
|
84
|
-
yield(node, parents, level)
|
85
|
-
|
86
|
-
if !node[options[:children]].nil? && node[options[:children]].length > 0
|
87
|
-
level+= 1
|
88
|
-
parents[level] = node
|
89
|
-
cache[level] = node[options[:children]]
|
90
|
-
i[level] = 0
|
91
|
-
end
|
92
|
-
else
|
93
|
-
parents[level] = nil
|
94
|
-
level-= 1
|
95
|
-
end
|
96
|
-
end
|
97
|
-
self
|
98
|
-
end
|
99
|
-
|
100
|
-
def to_nested options={}
|
101
|
-
options = NESTED_OPTIONS.merge options
|
102
|
-
fields = {
|
103
|
-
id: options[:id],
|
104
|
-
parent_id: options[:parent_id],
|
105
|
-
level: options[:level],
|
106
|
-
children: options[:children],
|
107
|
-
}
|
108
|
-
fields.delete :level if !options[:add_level]
|
109
|
-
cache = {}
|
110
|
-
nested = options[:hashed] ? {} : []
|
111
|
-
# Перебираем элементы в любом порядке!
|
112
|
-
self.each do |value|
|
113
|
-
value = value.serializable_hash if !value.is_a? Hash
|
114
|
-
# 1. Если нет родителя текущего элемента, и текущий элемент не корневой, то:
|
115
|
-
# 1.1 создадим родителя
|
116
|
-
# 1.2 поместим в кэш
|
117
|
-
if !(cache.key? value[fields[:parent_id]]) && (value[fields[:parent_id]] != options[:root_id])
|
118
|
-
# 1.1
|
119
|
-
temp = {}
|
120
|
-
fields.each do |key, field|
|
121
|
-
case key
|
122
|
-
when :id
|
123
|
-
temp[field] = value[fields[:parent_id]]
|
124
|
-
when :children
|
125
|
-
# не создаём поле
|
126
|
-
else
|
127
|
-
temp[field] = nil
|
128
|
-
end
|
129
|
-
end
|
130
|
-
# 1.2
|
131
|
-
cache[value[fields[:parent_id]]] = temp
|
132
|
-
end
|
133
|
-
# 2. Если текущий элемент уже был создан, значит он был чьим-то родителем, тогда:
|
134
|
-
# 2.1 обновим в нем информацию
|
135
|
-
# 2.2 поместим в родителя
|
136
|
-
if cache.key? value[fields[:id]]
|
137
|
-
# 2.1
|
138
|
-
fields.each do |key, field|
|
139
|
-
case key
|
140
|
-
when :id, :children
|
141
|
-
# не обновляем информацию
|
142
|
-
else
|
143
|
-
cache[value[fields[:id]]][field] = value[field]
|
144
|
-
end
|
145
|
-
end
|
146
|
-
value.keys.each do |field|
|
147
|
-
cache[value[fields[:id]]][field] = value[field] if !(field.in? fields)
|
148
|
-
end
|
149
|
-
# 2.2
|
150
|
-
# Если текущий элемент не корневой - поместим в родителя, беря его из кэш
|
151
|
-
if value[fields[:parent_id]] != options[:root_id]
|
152
|
-
cache[value[fields[:parent_id]]][fields[:children]] ||= options[:hashed] ? {} : []
|
153
|
-
if options[:hashed]
|
154
|
-
cache[value[fields[:parent_id]]][fields[:children]][value[fields[:id]]] = nested[value[fields[:id]]]
|
155
|
-
else
|
156
|
-
cache[value[fields[:parent_id]]][fields[:children]] << cache[value[fields[:id]]]
|
157
|
-
end
|
158
|
-
# иначе, текущий элемент корневой, поместим в nested
|
159
|
-
else
|
160
|
-
if options[:hashed]
|
161
|
-
nested[value[fields[:id]]] = cache[value[fields[:id]]]
|
162
|
-
else
|
163
|
-
nested << cache[value[fields[:id]]]
|
164
|
-
end
|
165
|
-
end
|
166
|
-
# 3. Иначе, текущий элемент не создан, тогда:
|
167
|
-
# 3.1 создадим элемент
|
168
|
-
# 3.2 поместим в кэш
|
169
|
-
# 3.3 поместим в родителя
|
170
|
-
else
|
171
|
-
# 3.1
|
172
|
-
temp = {}
|
173
|
-
fields.each do |key, field|
|
174
|
-
case key
|
175
|
-
when :id
|
176
|
-
temp[field] = value[field]
|
177
|
-
when :parent_id
|
178
|
-
temp[field] = value[field]
|
179
|
-
when :children
|
180
|
-
# ничего не делаем
|
181
|
-
else
|
182
|
-
temp[field] = value[field]
|
183
|
-
end
|
184
|
-
end
|
185
|
-
value.keys.each do |field|
|
186
|
-
temp[field] = value[field] if !(field.in? fields)
|
187
|
-
end
|
188
|
-
# 3.2
|
189
|
-
cache[value[fields[:id]]] = temp
|
190
|
-
# 3.3
|
191
|
-
# Если текущий элемент не корневой - поместим в родителя, беря его из кэш
|
192
|
-
if value[fields[:parent_id]] != options[:root_id]
|
193
|
-
cache[value[fields[:parent_id]]][fields[:children]] ||= options[:hashed] ? {} : []
|
194
|
-
if options[:hashed]
|
195
|
-
cache[value[fields[:parent_id]]][fields[:children]][value[fields[:id]]] = cache[value[fields[:id]]]
|
196
|
-
else
|
197
|
-
cache[value[fields[:parent_id]]][fields[:children]] << cache[value[fields[:id]]]
|
198
|
-
end
|
199
|
-
# иначе, текущий элемент корневой, поместим в nested
|
200
|
-
else
|
201
|
-
if options[:hashed]
|
202
|
-
nested[value[fields[:id]]] = cache[value[fields[:id]]]
|
203
|
-
else
|
204
|
-
nested << cache[value[fields[:id]]]
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
if options[:add_level]
|
210
|
-
level = 0
|
211
|
-
cache = []
|
212
|
-
cache[level] = nested
|
213
|
-
i = []
|
214
|
-
i[level] = 0
|
215
|
-
while level >= 0
|
216
|
-
node = cache[level][i[level]]
|
217
|
-
i[level]+= 1
|
218
|
-
if node != nil
|
219
|
-
|
220
|
-
node[options[:level]] = level
|
221
|
-
|
222
|
-
if !node[options[:children]].nil? && node[options[:children]].length > 0
|
223
|
-
level+= 1
|
224
|
-
cache[level] = node[options[:children]]
|
225
|
-
i[level] = 0
|
226
|
-
end
|
227
|
-
else
|
228
|
-
level-= 1
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
nested
|
233
|
-
end
|
234
|
-
|
235
|
-
def nested_to_html options={}
|
236
|
-
options = NESTED_OPTIONS.merge options
|
237
|
-
html = ''
|
238
|
-
level = 0
|
239
|
-
cache = []
|
240
|
-
cache[level] = self.clone
|
241
|
-
parents = []
|
242
|
-
parents[level] = nil
|
243
|
-
i = []
|
244
|
-
i[level] = 0
|
245
|
-
while level >= 0
|
246
|
-
node = cache[level][i[level]]
|
247
|
-
i[level]+= 1
|
248
|
-
if node != nil
|
249
|
-
|
250
|
-
html+= options[:tab] * (level * 2 + 1) if options[:tabulated]
|
251
|
-
html+= options[:li]
|
252
|
-
html+= yield(node.clone, parents.clone, level)
|
6
|
+
module NestedArray
|
253
7
|
|
254
|
-
|
255
|
-
level+= 1
|
256
|
-
html+= "\n" if !options[:inline]
|
257
|
-
html+= options[:tab] * (level * 2) if options[:tabulated]
|
258
|
-
html+= options[:ul]
|
259
|
-
html+= "\n" if !options[:inline]
|
260
|
-
parents[level] = node.clone
|
261
|
-
cache[level] = node[:children]
|
262
|
-
i[level] = 0
|
263
|
-
else
|
264
|
-
html+= options[:_li]
|
265
|
-
html+= "\n" if !options[:inline]
|
266
|
-
end
|
267
|
-
else
|
268
|
-
parents[level] = nil
|
269
|
-
if level > 0
|
270
|
-
html+= options[:tab] * (level * 2) if options[:tabulated]
|
271
|
-
html+= options[:_ul]
|
272
|
-
html+= "\n" if !options[:inline]
|
273
|
-
html+= options[:tab] * (level * 2 - 1) if options[:tabulated]
|
274
|
-
html+= options[:_li]
|
275
|
-
html+= "\n" if !options[:inline]
|
276
|
-
end
|
277
|
-
level-= 1
|
278
|
-
end
|
279
|
-
end
|
280
|
-
html
|
281
|
-
end
|
8
|
+
class Array < ::Array
|
282
9
|
|
283
|
-
|
284
|
-
# ноды склеиваются если путь к ним одинаков;
|
285
|
-
# путь определяется из сложения Текстов (конфигурируемо через :path_key);
|
286
|
-
def concat_nested tree=nil, options={}
|
287
|
-
options = NESTED_OPTIONS.merge options
|
288
|
-
return self if tree.nil?
|
289
|
-
children_cache = {}
|
290
|
-
tree.each_nested options do |node, parents, level|
|
291
|
-
parent_path_names = parents.compact.map{|e| e[options[:path_key]]}
|
292
|
-
parent_path = parent_path_names.join(options[:path_separator])
|
293
|
-
path = parent_path_names.push(node[options[:path_key]]).join(options[:path_separator])
|
294
|
-
element = node
|
295
|
-
if !children_cache.keys.include? path
|
296
|
-
if parent_path == ''
|
297
|
-
array = self
|
298
|
-
else
|
299
|
-
array = children_cache[parent_path]
|
300
|
-
end
|
301
|
-
element[options[:children]] = []
|
302
|
-
array << element
|
303
|
-
children_cache[parent_path] = array
|
304
|
-
children_cache[path] = element[options[:children]]
|
305
|
-
end
|
306
|
-
end
|
307
|
-
self
|
10
|
+
include NestedArray::Nested
|
308
11
|
end
|
309
12
|
end
|
data/nested_array.gemspec
CHANGED
@@ -38,4 +38,7 @@ Gem::Specification.new do |spec|
|
|
38
38
|
|
39
39
|
spec.add_development_dependency "bundler", "~> 2.0"
|
40
40
|
spec.add_development_dependency "rake", "~> 10.0"
|
41
|
+
spec.add_development_dependency "rspec", "~> 3.9"
|
42
|
+
spec.add_development_dependency "awesome_print", "~> 1.8"
|
43
|
+
spec.add_development_dependency "byebug", "~> 11.0"
|
41
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nested_array
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zlatov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,48 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.9'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: awesome_print
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '11.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '11.0'
|
41
83
|
description:
|
42
84
|
email:
|
43
85
|
- zlatov@ya.ru
|
@@ -45,16 +87,22 @@ executables: []
|
|
45
87
|
extensions: []
|
46
88
|
extra_rdoc_files: []
|
47
89
|
files:
|
90
|
+
- ".byebug_history"
|
48
91
|
- ".gitignore"
|
92
|
+
- ".rspec"
|
49
93
|
- ".ruby-version"
|
50
94
|
- Gemfile
|
51
95
|
- Gemfile.lock
|
52
96
|
- LICENSE.txt
|
53
97
|
- README.md
|
54
98
|
- Rakefile
|
99
|
+
- bash/build/gem.sh
|
100
|
+
- bash/test/gem.sh
|
55
101
|
- bin/console
|
56
102
|
- bin/setup
|
103
|
+
- lib/.byebug_history
|
57
104
|
- lib/nested_array.rb
|
105
|
+
- lib/nested_array/nested.rb
|
58
106
|
- lib/nested_array/version.rb
|
59
107
|
- nested_array.gemspec
|
60
108
|
homepage: https://github.com/Zlatov/nested_array
|