nested_array 2.3.0 → 3.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/.gitignore +0 -1
- data/.rspec +4 -1
- data/.rubocop.yml +125 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +41 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +35 -14
- data/README-ru-old.md +333 -0
- data/README-ru.md +451 -139
- data/README.md +510 -30
- data/TODO.md +6 -20
- data/doc/images/2.1.3.1.png +0 -0
- data/doc/images/2.1.3.2.png +0 -0
- data/doc/images/2.2.1.1.png +0 -0
- data/doc/images/2.2.1.2.png +0 -0
- data/doc/images/2.2.1.3-1.png +0 -0
- data/doc/images/2.2.1.3-2.png +0 -0
- data/doc/images/2.2.1.4-1.png +0 -0
- data/doc/images/2.2.1.4-2.png +0 -0
- data/doc/images/2.2.1.5.png +0 -0
- data/doc/images/2.2.2.1.png +0 -0
- data/doc/images/2.2.2.2.png +0 -0
- data/doc/images/2.2.2.3.png +0 -0
- data/doc/images/2.2.2.4.png +0 -0
- data/doc/images/2.2.3.1.png +0 -0
- data/doc/images/2.2.3.2.png +0 -0
- data/doc/images/2.2.3.3.png +0 -0
- data/lib/nested_array/nested.rb +228 -179
- data/lib/nested_array/version.rb +1 -1
- data/lib/nested_array.rb +4 -4
- data/vendor/assets/stylesheets/nested_array.scss +92 -0
- metadata +23 -8
- data/test.old/Gemfile +0 -5
- data/test.old/Gemfile.lock +0 -34
- data/test.old/bash/run/bundle.sh +0 -9
- data/test.old/bash/run/test.sh +0 -9
- data/test.old/test.rb +0 -42
data/README.md
CHANGED
@@ -1,56 +1,536 @@
|
|
1
|
-
#
|
1
|
+
# nested_array
|
2
2
|
|
3
|
-
|
3
|
+
🎉 Congratulations! Version 3.0 has been released.
|
4
|
+
|
5
|
+
Gem `nested_array` allows you to convert a flat data array with a tree structure
|
6
|
+
into a nested array. It also helps to display trees by forming HTML layout or
|
7
|
+
pseudo-graphics.
|
8
|
+
|
9
|
+
The tree structure must be described using the Adjacency List pattern, that is, each node has an ancestor.
|
10
|
+
|
11
|
+
__Select language README.md__
|
12
|
+
|
13
|
+
- en [English](README.md)
|
14
|
+
- ru [Русский](README-ru.md)
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
## <a id="Оглавление"></a>Table of contents
|
20
|
+
- [Installation](#1)
|
21
|
+
- [Usage](#2)
|
22
|
+
- [Converting data using the `.to_nested` method](#2.1)
|
23
|
+
- [Source data – hash array](#2.1.1)
|
24
|
+
- [Source data – ActiveRecord array](#2.1.2)
|
25
|
+
- [`.to_nested` method options](#2.1.3)
|
26
|
+
- [`root_id: id`](#2.1.3.1)
|
27
|
+
- [`branch_id: id`](#2.1.3.2)
|
28
|
+
- [Displaying tree structures](#2.2)
|
29
|
+
- [As multi-level lists](#2.2.1)
|
30
|
+
- [Bulleted and numbered lists `<ul>`, `<ol>`](#2.2.1.1)
|
31
|
+
- [Using your own templates to display a list](#2.2.1.2)
|
32
|
+
- [Changing the template depending on node data](#2.2.1.3)
|
33
|
+
- [Dropdown list based on `<details></details>` tag](#2.2.1.4)
|
34
|
+
- [Formation and output of your own templates based on changing the node level `node.level`](#2.2.1.5)
|
35
|
+
- [Pseudo-graphic output](#2.2.2)
|
36
|
+
- [Adding pseudo-graphics before the model name using the `nested_to_options` method](#2.2.2.1)
|
37
|
+
- [Thin pseudographics](#2.2.2.2)
|
38
|
+
- [Own pseudographics](#2.2.2.3)
|
39
|
+
- [Increase indentation in own pseudographics](#2.2.2.4)
|
40
|
+
- [In html forms](#2.2.3)
|
41
|
+
- [With the `form.select` helper](#2.2.3.1)
|
42
|
+
- [With `form.select` and `options_for_select` helpers](#2.2.3.2)
|
43
|
+
- [Dropdown list with radio buttons `form.radio_button`](#2.2.3.3)
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
## <a id="1"></a>Installation [↑](#Оглавление "To the table of contents")
|
49
|
+
|
50
|
+
1. Add a line to your application's Gemfile:
|
4
51
|
|
5
52
|
```ruby
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
53
|
+
# Working with tree arrays
|
54
|
+
gem "nested_array", "~> 3.0"
|
55
|
+
```
|
56
|
+
|
57
|
+
And do `bundle install`.
|
58
|
+
|
59
|
+
2. If you plan to use modest CSS gem styles, add to
|
60
|
+
the _app/assets/stylesheets/application.scss_ file:
|
61
|
+
|
62
|
+
```css
|
63
|
+
/* Displaying Tree Arrays */
|
64
|
+
@import "nested_array";
|
65
|
+
```
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
## <a id="2"></a>Usage [↑](#Оглавление "To the table of contents")
|
71
|
+
|
72
|
+
### <a id="2.1"></a>Converting data using the `.to_nested` method [↑](#Оглавление "To the table of contents")
|
73
|
+
|
74
|
+
#### <a id="2.1.1"></a>Source data – hash array [↑](#Оглавление "To the table of contents")
|
75
|
+
|
76
|
+
Let's say we have a hash array:
|
77
|
+
|
78
|
+
```rb
|
79
|
+
flat = [
|
80
|
+
{'id' => 3, 'parent_id' => nil},
|
81
|
+
{'id' => 2, 'parent_id' => 1},
|
82
|
+
{'id' => 1, 'parent_id' => nil}
|
10
83
|
]
|
11
|
-
|
84
|
+
```
|
85
|
+
|
86
|
+
Where each hash is a tree node, `id` is the node identifier, `parent_id` is a
|
87
|
+
pointer to the parent node.
|
88
|
+
|
89
|
+
It is necessary to convert it into an array in which there will be root nodes
|
90
|
+
(`'parent_id' => nil`), and child nodes placed in the `children` field.
|
91
|
+
|
92
|
+
```rb
|
93
|
+
nested = flat.to_nested
|
94
|
+
puts nested.pretty_inspect
|
95
|
+
```
|
96
|
+
|
97
|
+
This will output:
|
98
|
+
|
99
|
+
```
|
100
|
+
[#<OpenStruct id=3, parent_id=nil, level=0, origin={"id"=>3, "parent_id"=>nil}>,
|
101
|
+
#<OpenStruct id=1, parent_id=nil, level=0, children=[#<OpenStruct id=2, parent_id=1, level=1, origin={"id"=>2, "parent_id"=>1}>], origin={"id"=>1, "parent_id"=>nil}>]
|
102
|
+
```
|
103
|
+
|
104
|
+
As a result, nodes are `OpenStruct` objects with initial fields `id`, `parent_id` and additional fields `level`, `origin` and `children`.
|
105
|
+
|
106
|
+
ActiveRecord objects can also serve as source nodes.
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
#### <a id="2.1.2"></a>Source data – ActiveRecord array [↑](#Оглавление "To the table of contents")
|
112
|
+
|
113
|
+
```rb
|
114
|
+
catalogs = Catalog.all.to_a
|
115
|
+
nested = catalogs.to_nested
|
116
|
+
puts nested.pretty_inspect
|
117
|
+
```
|
118
|
+
|
119
|
+
This will output:
|
120
|
+
|
121
|
+
```
|
12
122
|
[
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
123
|
+
#<OpenStruct id=1, parent_id=nil, level=0, origin=#<Catalog id: 1, name: "Computer Components", parent_id: nil>, children=[
|
124
|
+
#<OpenStruct id=11, parent_id=1, level=1, origin=#<Catalog id: 11, name: "External Components", parent_id: 1>, children=[
|
125
|
+
#<OpenStruct id=111, parent_id=11, level=2, origin=#<Catalog id: 111, name: "Hard Drives", parent_id: 11>>,
|
126
|
+
#<OpenStruct id=112, parent_id=11, level=2, origin=#<Catalog id: 112, name: "Sound Cards", parent_id: 11>>,
|
127
|
+
#<OpenStruct id=113, parent_id=11, level=2, origin=#<Catalog id: 113, name: "KVM Switches", parent_id: 11>>,
|
128
|
+
#<OpenStruct id=114, parent_id=11, level=2, origin=#<Catalog id: 114, name: "Optical Drives", parent_id: 11>>
|
129
|
+
]>,
|
130
|
+
#<OpenStruct id=12, parent_id=1, level=1, origin=#<Catalog id: 12, name: "Internal Components", parent_id: 1>>
|
131
|
+
]>,
|
132
|
+
#<OpenStruct id=2, parent_id=nil, level=0, origin=#<Catalog id: 2, name: "Monitors", parent_id: nil>>,
|
133
|
+
#<OpenStruct id=3, parent_id=nil, level=0, origin=#<Catalog id: 3, name: "Servers", parent_id: nil>>,
|
134
|
+
#<OpenStruct id=4, parent_id=nil, level=0, origin=#<Catalog id: 4, name: "Networking Products", parent_id: nil>>
|
17
135
|
]
|
18
136
|
```
|
19
137
|
|
138
|
+
<sub>The `.to_nested` method uses the `object.serializable_hash` method to get a list of the object's fields.</sub>
|
20
139
|
|
21
|
-
## Installation
|
22
140
|
|
23
|
-
Add this line to your application's Gemfile:
|
24
141
|
|
25
|
-
|
26
|
-
|
27
|
-
|
142
|
+
|
143
|
+
#### <a id="2.1.3"></a>`.to_nested` method options [↑](#Оглавление "To the table of contents")
|
144
|
+
|
145
|
+
##### <a id="2.1.3.1"></a>`root_id: id` [↑](#Оглавление "To the table of contents")
|
146
|
+
|
147
|
+
`root_id: 1` — take children of node with `id` equal to `1`.
|
148
|
+
|
149
|
+
```erb
|
150
|
+
<% catalogs_of_1 = Catalog.all.to_a.to_nested(root_id: 1) %>
|
151
|
+
<ul>
|
152
|
+
<% catalogs_of_1.each_nested do |node, origin| %>
|
153
|
+
<%= node.before -%>
|
154
|
+
<%= origin.name -%> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
155
|
+
<%= node.after -%>
|
156
|
+
<% end %>
|
157
|
+
</ul>
|
158
|
+
```
|
159
|
+
|
160
|
+
Will output a multi-level bulleted list of descendants of node #1:
|
161
|
+
|
162
|
+

|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
##### <a id="2.1.3.2"></a>`branch_id: id` [↑](#Оглавление "To the table of contents")
|
168
|
+
|
169
|
+
`branch_id: 1` — take the node with `id` equal to `1` and all its descendants.
|
170
|
+
|
171
|
+
```erb
|
172
|
+
<% catalogs_from_1 = Catalog.all.to_a.to_nested(branch_id: 1) %>
|
173
|
+
<ul>
|
174
|
+
<% catalogs_from_1.each_nested do |node, origin| %>
|
175
|
+
<%= node.before -%>
|
176
|
+
<%= origin.name -%> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
177
|
+
<%= node.after -%>
|
178
|
+
<% end %>
|
179
|
+
</ul>
|
180
|
+
```
|
181
|
+
|
182
|
+
Will output node #1 and its descendants:
|
183
|
+
|
184
|
+

|
185
|
+
|
186
|
+
|
187
|
+
### <a id="2.2"></a>Displaying tree structures [↑](#Оглавление "To the table of contents")
|
188
|
+
|
189
|
+
#### <a id="2.2.1"></a>As multi-level lists [↑](#Оглавление "To the table of contents")
|
190
|
+
|
191
|
+
##### <a id="2.2.1.1"></a>Bulleted and numbered lists `<ul>`, `<ol>` [↑](#Оглавление "To the table of contents")
|
192
|
+
|
193
|
+
```erb
|
194
|
+
<ul>
|
195
|
+
<% @catalogs.to_a.to_nested.each_nested do |node, origin| %>
|
196
|
+
<%= node.before %>
|
197
|
+
<%= link_to origin.name, origin %> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
198
|
+
<%= node.after %>
|
199
|
+
<% end %>
|
200
|
+
</ul>
|
201
|
+
|
202
|
+
<ol>
|
203
|
+
<% @catalogs.to_a.to_nested.each_nested ul: '<ol>', _ul: '</ol>' do |node, origin| %>
|
204
|
+
<%= node.before %>
|
205
|
+
<%= link_to origin.name, origin %> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
206
|
+
<%= node.after %>
|
207
|
+
<% end %>
|
208
|
+
</ol>
|
209
|
+
```
|
210
|
+
|
211
|
+

|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
|
216
|
+
##### <a id="2.2.1.2"></a>Using your own templates to display a list [↑](#Оглавление "To the table of contents")
|
217
|
+
|
218
|
+
Instead of `<ul><li>`/`<ol><li>`
|
219
|
+
|
220
|
+
```erb
|
221
|
+
<% content_for :head do %>
|
222
|
+
<style>
|
223
|
+
/* Vertical node padding */
|
224
|
+
div.li { margin: .5em 0; }
|
225
|
+
/* Level indentation (children) */
|
226
|
+
div.ul { margin-left: 2em; }
|
227
|
+
</style>
|
228
|
+
<% end %>
|
229
|
+
|
230
|
+
<div class="ul">
|
231
|
+
<%# Overriding opening and closing template tags. %>
|
232
|
+
<% @catalogs.to_a.to_nested.each_nested(
|
233
|
+
ul: '<div class="ul">',
|
234
|
+
_ul: '</div>',
|
235
|
+
li: '<div class="li">',
|
236
|
+
_li: '</div>'
|
237
|
+
) do |node, origin| %>
|
238
|
+
<%= node.before -%>
|
239
|
+
<%= origin.name -%> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
240
|
+
<%= node.after -%>
|
241
|
+
<% end %>
|
242
|
+
</div>
|
243
|
+
```
|
244
|
+
|
245
|
+

|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
|
250
|
+
|
251
|
+
##### <a id="2.2.1.3"></a>Changing the template depending on node data [↑](#Оглавление "To the table of contents")
|
252
|
+
|
253
|
+
To change the output patterns depending on the node data, we can check the node
|
254
|
+
fields `node.li` and `node.ul`. If the fields are not empty, then instead of
|
255
|
+
displaying their contents, substitute your own dynamic html.
|
256
|
+
|
257
|
+
Output of available node templates (`node.li`, `node.ul` and `node._`):
|
258
|
+
|
259
|
+
```erb
|
260
|
+
<ul>
|
261
|
+
<% @catalogs.to_a.to_nested.each_nested do |node, origin| %>
|
262
|
+
<%= node.li -%>
|
263
|
+
<%= origin.name -%> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
264
|
+
<%= node.ul -%>
|
265
|
+
<%= node._ -%>
|
266
|
+
<% end %>
|
267
|
+
</ul>
|
268
|
+
```
|
269
|
+
|
270
|
+

|
271
|
+
|
272
|
+
Replacing templates with dynamic html:
|
273
|
+
|
274
|
+
```erb
|
275
|
+
<% content_for :head do %>
|
276
|
+
<style>
|
277
|
+
li.level-0 {color: red;}
|
278
|
+
li.level-1 {color: green;}
|
279
|
+
li.level-2 {color: blue;}
|
280
|
+
li.has_children {font-weight: bold;}
|
281
|
+
ul.big {border: solid 1px gray;}
|
282
|
+
</style>
|
283
|
+
<% end %>
|
284
|
+
|
285
|
+
<ul>
|
286
|
+
<% @catalogs.to_a.to_nested.each_nested do |node, origin| %>
|
287
|
+
<li class="level-<%= node.level %> <%= 'has_children' if node.is_has_children %>">
|
288
|
+
<%= origin.name %> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
289
|
+
<% if node.ul.present? %>
|
290
|
+
<ul class="<%= 'big' if node.children.length > 2 %>">
|
291
|
+
<% end %>
|
292
|
+
<%= node._ -%>
|
293
|
+
<% end %>
|
294
|
+
</ul>
|
295
|
+
```
|
296
|
+
|
297
|
+

|
298
|
+
|
299
|
+
It's worth noting that the `node.li` field is always present in a node, unlike
|
300
|
+
`node.ul`.
|
301
|
+
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
##### <a id="2.2.1.4"></a>Dropdown list based on `<details></details>` tag [↑](#Оглавление "To the table of contents")
|
306
|
+
|
307
|
+
```erb
|
308
|
+
<ul class="nested_array-details">
|
309
|
+
<% @catalogs.to_a.to_nested.each_nested details: true do |node, origin| %>
|
310
|
+
<%= node.before %>
|
311
|
+
<%= origin.name %> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
312
|
+
<%= node.after %>
|
313
|
+
<% end %>
|
314
|
+
</ul>
|
28
315
|
```
|
29
316
|
|
30
|
-
|
317
|
+

|
318
|
+
|
319
|
+
By default, sublevels are hidden; you can control the display of sublevels by passing an option to the node method: `node.after(open: ...)`:
|
320
|
+
|
321
|
+
```erb
|
322
|
+
<ul class="nested_array-details">
|
323
|
+
<% @catalogs.to_a.to_nested.each_nested details: true do |node, origin| %>
|
324
|
+
<%= node.before %>
|
325
|
+
<%= origin.name %> <small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
326
|
+
<%= node.after(open: node.is_has_children) %>
|
327
|
+
<% end %>
|
328
|
+
</ul>
|
329
|
+
```
|
330
|
+
|
331
|
+

|
332
|
+
|
333
|
+
|
31
334
|
|
32
|
-
Or install it yourself as `gem install nested_array`.
|
33
335
|
|
34
|
-
|
336
|
+
##### <a id="2.2.1.5"></a>Formation and output of your own templates based on changing the node level `node.level` [↑](#Оглавление "To the table of contents")
|
35
337
|
|
36
|
-
```
|
37
|
-
|
38
|
-
|
39
|
-
|
338
|
+
```erb
|
339
|
+
<% content_for :head do %>
|
340
|
+
<style>
|
341
|
+
div.children {margin-left: 1em;}
|
342
|
+
div.node {position: relative;}
|
343
|
+
div.node::before {
|
344
|
+
position: absolute;
|
345
|
+
content: "";
|
346
|
+
width: 0px;
|
347
|
+
height: 0px;
|
348
|
+
border-top: 5px solid transparent;
|
349
|
+
border-bottom: 5px solid transparent;
|
350
|
+
border-left: 8.66px solid red;
|
351
|
+
left: -9px;
|
352
|
+
top: 3px;
|
353
|
+
}
|
354
|
+
</style>
|
355
|
+
<% end %>
|
356
|
+
|
357
|
+
<div class="children">
|
358
|
+
<% prev_level = nil %>
|
359
|
+
<% @catalogs.to_a.to_nested.each_nested do |node, origin| %>
|
360
|
+
|
361
|
+
<%# Has the level increased? - open the sublevel. %>
|
362
|
+
<% if prev_level.present? && prev_level < node.level %>
|
363
|
+
<div class="children">
|
364
|
+
<% end %>
|
365
|
+
|
366
|
+
<%# Same level? — we simply close the previous one. %>
|
367
|
+
<% if prev_level.present? && prev_level == node.level %>
|
368
|
+
</div>
|
369
|
+
<% end %>
|
370
|
+
|
371
|
+
<%# Has the level dropped? - closing the previous one is difficult. %>
|
372
|
+
<% if prev_level.present? && prev_level > node.level %>
|
373
|
+
<% (prev_level - node.level).times do |t| %>
|
374
|
+
</div>
|
375
|
+
</div>
|
376
|
+
<% end %>
|
377
|
+
</div>
|
378
|
+
<% end %>
|
379
|
+
|
380
|
+
<%# Our node. %>
|
381
|
+
<div class="node">
|
382
|
+
<%= origin.name %>
|
383
|
+
|
384
|
+
<% prev_level = node.level %>
|
385
|
+
<% end %>
|
386
|
+
|
387
|
+
<%# Taking into account the previous level when exiting the cycle (Level has decreased). %>
|
388
|
+
<% if !prev_level.nil? %>
|
389
|
+
<% prev_level.times do |t| %>
|
390
|
+
</div>
|
391
|
+
</div>
|
392
|
+
<% end %>
|
393
|
+
</div>
|
394
|
+
<% end %>
|
395
|
+
</div>
|
396
|
+
```
|
397
|
+
|
398
|
+

|
399
|
+
|
400
|
+
|
401
|
+
|
402
|
+
|
403
|
+
#### <a id="2.2.2"></a>Pseudo-graphic output [↑](#Оглавление "To the table of contents")
|
404
|
+
|
405
|
+
##### <a id="2.2.2.1"></a>Adding pseudo-graphics before the model name using the `nested_to_options` method [↑](#Оглавление "To the table of contents")
|
406
|
+
|
407
|
+
```erb
|
408
|
+
<% options = @catalogs.to_a.to_nested.nested_to_options(:name, :id) %>
|
409
|
+
<pre><code><%= options.pluck(0).join($/) %>
|
410
|
+
</code></pre>
|
411
|
+
```
|
412
|
+
|
413
|
+

|
414
|
+
|
415
|
+
|
416
|
+
|
417
|
+
|
418
|
+
##### <a id="2.2.2.2"></a>Thin pseudographics [↑](#Оглавление "To the table of contents")
|
419
|
+
|
420
|
+
```erb
|
421
|
+
<% options = @catalogs.to_a.to_nested.nested_to_options(:name, :id, thin_pseudographic: true) %>
|
422
|
+
<pre><code><%= options.pluck(0).join($/) %>
|
423
|
+
</code></pre>
|
424
|
+
```
|
425
|
+
|
426
|
+

|
427
|
+
|
428
|
+
|
429
|
+
|
430
|
+
|
431
|
+
##### <a id="2.2.2.3"></a>Own pseudographics [↑](#Оглавление "To the table of contents")
|
432
|
+
|
433
|
+
```erb
|
434
|
+
<% options = @catalogs.to_a.to_nested.nested_to_options(:name, :id, pseudographics: %w(┬ ─ ❇ ├ └ │)) %>
|
435
|
+
<pre><code><%= options.pluck(0).join($/).html_safe %>
|
436
|
+
</code></pre>
|
437
|
+
```
|
438
|
+
|
439
|
+

|
440
|
+
|
441
|
+
|
442
|
+
|
443
|
+
|
444
|
+
##### <a id="2.2.2.4"></a>Increase indentation in own pseudographics [↑](#Оглавление "To the table of contents")
|
445
|
+
|
446
|
+
```erb
|
447
|
+
<% options = @catalogs.to_a.to_nested.nested_to_options(:name, :id, pseudographics: ['─┬', '──', '─ ', ' ├', ' └', ' ', ' │']) %>
|
448
|
+
<pre><code><%= options.pluck(0).join($/).html_safe %>
|
449
|
+
</code></pre>
|
450
|
+
```
|
451
|
+
|
452
|
+

|
453
|
+
|
454
|
+
|
455
|
+
|
456
|
+
|
457
|
+
#### <a id="2.2.3"></a>In html forms [↑](#Оглавление "To the table of contents")
|
458
|
+
|
459
|
+
#### <a id="2.2.3.1"></a>With the `form.select` helper [↑](#Оглавление "To the table of contents")
|
460
|
+
|
461
|
+
```erb
|
462
|
+
<%= form_with(model: Catalog.find(11), url: root_path, method: :get) do |form| %>
|
463
|
+
<%= form.select :parent_id,
|
464
|
+
@catalogs.to_a.to_nested.nested_to_options(:name, :id),
|
465
|
+
{
|
466
|
+
include_blank: 'None'
|
467
|
+
},
|
468
|
+
{
|
469
|
+
multiple: false,
|
470
|
+
size: 11,
|
471
|
+
class: 'form-select form-select-sm nested_array-select'
|
472
|
+
}
|
473
|
+
%>
|
474
|
+
<% end %>
|
475
|
+
```
|
476
|
+
|
477
|
+

|
478
|
+
|
479
|
+
|
480
|
+
|
481
|
+
|
482
|
+
#### <a id="2.2.3.2"></a>With `form.select` and `options_for_select` helpers [↑](#Оглавление "To the table of contents")
|
483
|
+
|
484
|
+
```erb
|
485
|
+
<%= form_with(model: Catalog.find(11), url: root_path, method: :get) do |form| %>
|
486
|
+
<%= form.select :parent_id,
|
487
|
+
options_for_select(
|
488
|
+
@catalogs.to_a.to_nested.nested_to_options(:name, :id).unshift(['None', '']),
|
489
|
+
selected: form.object.parent_id.to_s
|
490
|
+
),
|
491
|
+
{
|
492
|
+
},
|
493
|
+
{
|
494
|
+
multiple: false,
|
495
|
+
size: 11,
|
496
|
+
class: 'nested_array-select'
|
497
|
+
}
|
498
|
+
%>
|
499
|
+
<% end %>
|
500
|
+
```
|
501
|
+
|
502
|
+

|
503
|
+
|
504
|
+
|
505
|
+
|
506
|
+
|
507
|
+
#### <a id="2.2.3.3"></a>Dropdown list with radio buttons `form.radio_button` [↑](#Оглавление "To the table of contents")
|
508
|
+
|
509
|
+
```erb
|
510
|
+
<%= form_with(model: nil, url: root_path, method: :get) do |form| %>
|
511
|
+
<ul class="nested_array-details">
|
512
|
+
<% @catalogs.to_a.to_nested.each_nested details: true do |node, origin| %>
|
513
|
+
<%= node.before %>
|
514
|
+
<%= form.radio_button :parent_id, origin.id %>
|
515
|
+
<%= form.label :parent_id, origin.name, value: origin.id %>
|
516
|
+
<small>[<%= origin.id %>, <%= origin.parent_id || :nil %>, <%= node.level %>]</small>
|
517
|
+
<%= node.after(open: node.is_has_children) %>
|
40
518
|
<% end %>
|
41
519
|
</ul>
|
520
|
+
<% end %>
|
42
521
|
```
|
43
522
|
|
44
|
-
|
523
|
+

|
45
524
|
|
46
|
-
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
47
525
|
|
48
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
49
526
|
|
50
|
-
## Contributing
|
51
527
|
|
52
|
-
|
528
|
+
## Development
|
53
529
|
|
54
|
-
|
530
|
+
To connect the local version of the gem, replace the second argument(version) in
|
531
|
+
the connection line (Gemfile file) with the path option:
|
55
532
|
|
56
|
-
|
533
|
+
```rb
|
534
|
+
# Working with tree arrays
|
535
|
+
gem "nested_array", path: "../nested_array"
|
536
|
+
```
|
data/TODO.md
CHANGED
@@ -1,26 +1,12 @@
|
|
1
|
-
# Что реализовано, необходимо реализовать и почему
|
2
|
-
|
3
|
-
## Почему
|
4
|
-
|
5
|
-
### Почему возвращаем массив Hash
|
6
|
-
|
7
|
-
Когда хотим из плоской структуры получить древовидную, то на руках мы можем
|
8
|
-
иметь данные различного типа, например, массив Hash или массив ActiveRecord,
|
9
|
-
результатом обработки должен быть массив объектов у которых должно быть поле
|
10
|
-
children содержащее потомков. Именно поэтому мы не можем оставлять в результате
|
11
|
-
массив ActiveRecord, так как поле children будет конфликтовать с уже
|
12
|
-
существующим методом, например при использовании гема closure_tree. С другой
|
13
|
-
стороны мы моглибы внедрить поле nested_children во все объекты ActiveRecord,
|
14
|
-
но такой подход, мне кажется, похож на «Monkey patch».
|
15
|
-
|
16
|
-
|
17
|
-
## TODO
|
18
|
-
|
19
|
-
Хочу возвращать массив OpenStruct вместо массива Hash.
|
20
|
-
|
21
1
|
При возврате массива OpenStruct (всегда) пропадает смысл метода `each_nested!`
|
22
2
|
который должен отдавать в переменной node исходные данные (ну они не исходые
|
23
3
|
уже). Поэтому необходимо выпустить версию 3.0.0 с удалением метода
|
24
4
|
`each_nested!`.
|
25
5
|
|
6
|
+
Добавлен метод nested_to_collection_select, нужно пересмотреть метод
|
7
|
+
nested_to_options (возможно удалить в следующей версии).
|
8
|
+
|
26
9
|
Переработать README-ru и на английский доперевести в конце концов.
|
10
|
+
|
11
|
+
Нужно интегрировать Rails::Engine класс, а то ругается при тестах. Класс нужен
|
12
|
+
чтобы в рельсе можно было использовать ассеты.
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|