ancestry 3.0.5 → 3.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 441841ddcb84e00cdc685fe6bfc4ba8db2a184ae
4
- data.tar.gz: d860eef74743307b1fae929ec652f8ec77474a10
2
+ SHA256:
3
+ metadata.gz: 2f1ae94346d7ad0aa07830437239dc7f13dda73408c61a118e60f53ef21e6282
4
+ data.tar.gz: 1eb3e39a50b257dddc13559d52b03955c8174682f990a723614ca9e2e3dc6945
5
5
  SHA512:
6
- metadata.gz: a75b3aceafbe2a286feff48f0bb8ec1fe4618ad45b80d24ee7c400fdedfcde0144dad477aeae119d7709861068237cd4c12a5d41429b3c7ff6f667b8da47c71f
7
- data.tar.gz: a1abe3c0d18f3bddb7bf531a7a1a46d5f53a954da1eba0a46741f00b8f0aa4baae7802a172c676ed65afc1b843aea8fe4a7cdc6669241777f31debc8e4025d70
6
+ metadata.gz: 87a3c689530416fd20fa4064bb7c610e8e9e3b013324776e5a7c96ad7cb0a8f1a136dfbe71ada9e53b5116ef41602dab7d2d7664e2fc047e8a31f7a6598e2238
7
+ data.tar.gz: f420ad732aca06c42116a97db60898db8712163aae660d13b8f0d32b806eaa6e81edac4ba2eb167986456995859cfd52da829abbbdf7d3377177b9f9049b73d5
@@ -0,0 +1,277 @@
1
+ # Ancestry Changelog
2
+
3
+ Doing our best at supporting [SemVer](http://semver.org/) with
4
+ a nice looking [Changelog](http://keepachangelog.com).
5
+
6
+ ## Version [HEAD] <small>now</small>
7
+
8
+ * dropped support for rails 4.2 and 5.0
9
+
10
+ ## Versions [3.2.1] <small>2020-09-23</small>
11
+
12
+ * fixed gemspec to include locales and pg (thx @HectorMF)
13
+
14
+ ## Versions [3.2.0] <small>2020-09-23</small>
15
+
16
+ * introduce i18n
17
+ * pg sql optimization for ancestry changes (thx @suonlight and @geis)
18
+ * pg sql optimization for sorting (thx @brendon and @d-m-u)
19
+ * fix to humanise model name (thx @mkllnk)
20
+ * able to convert to ancestry from a parent_id column with a different name
21
+ * documentation fixes for better diagrams and grammar (thx @dtamais, @d-m-u, and @CamilleDrapier)
22
+
23
+ ## Versions [3.1.0] <small>2020-08-03</small>
24
+
25
+ * `:primary_key_format` method lets you change syntax. good for uuids.
26
+ * changed code from being `ancestry` string to `ancestry_ids` focused. May break monkey patches.
27
+ * Moved many methods from `has_ancestry` and `InstanceMethods` to `MaterializedPath`. May break monkey patches.
28
+ * Removed tests for `mysql` driver. Starting with rails 4.1, it supports `mysql2` driver.
29
+ * Better documentation for relationships (thnx @dtamai and @d-m-u)
30
+ * Fix creating children in `after_*` callbacks (thx @jstirk)
31
+
32
+ ## Version [3.0.7] <small>2018-11-06</small>
33
+
34
+ * Fixed rails 5.1 change detection (thx @jrafanie)
35
+ * Introduce counter cache (thx @hw676018683)
36
+
37
+ ## Version [3.0.6] <small>2018-11-06</small>
38
+
39
+ * Fixed rails 4.1 version check (thx @myxoh)
40
+
41
+ ## Version [3.0.5] <small>2018-11-06</small>
42
+
43
+ ## Changed
44
+
45
+ * Added indirect children support (thx @tilo)
46
+ * Fixed test sorting for pg on mac osx
47
+
48
+ ## Fixes
49
+
50
+ * Reduced memory footprint of parsing ancestry column (thx @NickLaMuro)
51
+
52
+ ## Version [3.0.4] <small>2018-10-27</small>
53
+
54
+ ## Fixes
55
+
56
+ * Properly detects non-integer columns (thx @adam101)
57
+ * Arrange no longer drops nodes due to missing parents (thx @trafium)
58
+
59
+ ## Version [3.0.3] <small>2018-10-23</small>
60
+
61
+ This branch (3.x) should still be compatible with rails 3 and 4.
62
+ Rails 5.1 and 5.2 support were introduced in this version, but ongoing support
63
+ has been moved to ancestry 4.0
64
+
65
+ ## Fixes
66
+
67
+ * Reduce object allocation (thx @NickLaMuro)
68
+ * Rails 5.1 fixes (thx @ctrombley)
69
+ * Avoid redundant query to DB in subtree_of scope (thx @Slike9)
70
+ * Syntax tweaks (thx @ekohl, @richardonrails)
71
+ * Fixed reverse ordering
72
+ * Dropped builds for ruby 1.9.3, 2.0, 2.1, and 2.2
73
+ * Dropped builds for Rails 3.x and 4.x (will use Active Record `or` syntax)
74
+
75
+ ## Version [3.0.2] <small>2018-04-24</small>
76
+
77
+ ## Fixes
78
+
79
+ * fixed `order_by_ancestry` bug
80
+ * fixed order tests for postgres on mac (it uses a different collation)
81
+ * fixed documentation (thx @besquared, @danfrenette, @eiwi1101, @isimluk, @mabusaad, @tilsammans)
82
+ * added missing `Ancestry::version`
83
+ * added Rails 5.2 support (thx @jjuliano)
84
+
85
+ ## Version [3.0.1] <small>2017-07-05</small>
86
+
87
+ ## Fixes
88
+
89
+ * added gem metadata
90
+ * fixed keep a changelog link (thx @mattbrictson)
91
+ * added alias has_parent?
92
+ * fixed bug where unscoping too much (thx @brendon)
93
+ * fixed tests on mysql 5.7 and rails 3.2
94
+ * Dropped 3.1 scope changes
95
+
96
+ ## Version [3.0.0] <small>2017-05-18</small>
97
+
98
+ ## Changed
99
+
100
+ * Dropping Rails 3.0, and 3.1. Added Rails 5.1 support (thx @ledermann)
101
+ * Dropping Rails 4.0, 4.1 for build reasons. Since 4.2 is supported, all 4.x should still work.
102
+
103
+ ## Fixes
104
+
105
+ * Performance: Use `pluck` vs `map` for ids (thx @njakobsen and @culturecode)
106
+ * Fixed acts_as_tree compatibility (thx @crazymykl)
107
+ * Fixed loading ActiveRails prematurely (thx @vovimayhem)
108
+ * Fixes exist (thx @ledermann)
109
+ * Properly touches parents when different class for STI (thx @samtgarson)
110
+ * Fixed issues with parent_id (only present on master) (thx @domcleal)
111
+
112
+ ## Version [2.2.2] <small>2016-11-01</small>
113
+
114
+ ### Changed
115
+
116
+ * Use `COALESCE` only for sorting versions greater than 5.0
117
+ * Fixed bug with explicit order clauses (introduced in 2.2.0)
118
+ * No longer load schema on `has_ancestry` load (thx @ledermann)
119
+
120
+ ## Version [2.2.1] <small>2016-10-25</small>
121
+
122
+ Sorry for blip, local master got out of sync with upstream master.
123
+ Missed 2 commits (which are feature adds)
124
+
125
+ ### Added
126
+ * Use like (vs ilike) for rails 5.0 (performance enhancement)
127
+ * Use `COALESCE` for sorting on pg, mysql, and sqlite vs `CASE`
128
+
129
+ ## Version [2.2.0] <small>2016-10-25</small>
130
+
131
+ ### Added
132
+ * Predicates for scopes: e.g.: `ancestor_of?`, `parent_of?` (thx @neglectedvalue)
133
+ * Scope `path_of`
134
+
135
+ ### Changed
136
+ * `arrange` now accepts blocks (thx @mastfish)
137
+ * Performance tuning `arrange_node` (thx @fryguy)
138
+ * In orphan strategy, set `ancestry` to `nil` for no parents (thx @haslinger)
139
+ * Only updates `updated_at` when a record is changed (thx @brocktimus)
140
+ * No longer casts text primary key as an integer
141
+ * Upgrading tests for ruby versions (thx @brocktimus, @fryguy, @yui-knk)
142
+ * Fix non-default ancestry not getting used properly (thx @javiyu)
143
+
144
+ ## Version [2.1.0] <small>2014-04-16</small>
145
+ * Added arrange_serializable (thx @krishandley, @chicagogrrl)
146
+ * Add the :touch to update ancestors on save (thx @adammck)
147
+ * Change conditions into arel (thx @mlitwiniuk)
148
+ * Added children? & siblings? alias (thx @bigtunacan)
149
+ * closure_tree compatibility (thx @gzigzigzeo)
150
+ * Performance tweak (thx @mjc)
151
+ * Improvements to organization (thx @xsuchy, @ryakh)
152
+
153
+ ## Version [2.0.0] <small>2013-05-17</small>
154
+ * Removed rails 2 compatibility
155
+ * Added table name to condition constructing methods (thx @aflatter)
156
+ * Fix depth_cache not being updated when moving up to ancestors (thx @scottatron)
157
+ * add alias :root? to existing is_root? (thx @divineforest)
158
+ * Add block to sort_by_ancestry (thx @Iliya)
159
+ * Add attribute query method for parent_id (thx @sj26)
160
+ * Fixed and tested for rails 4 (thx @adammck, @Nihad, @Systho, @Philippe, e.a.)
161
+ * Fixed overwriting ActiveRecord::Base.base_class (thx @Rozhnov)
162
+ * New adopt strategy (thx unknown)
163
+ * Many more improvements
164
+
165
+ ## Version [1.3.0] <small>2012-05-04</small>
166
+ * Ancestry now ignores default scopes when moving or destroying nodes, ensuring tree consistency
167
+ * Changed ActiveRecord dependency to 2.3.14
168
+
169
+ ## Version [1.2.5] <small>2012-03-15</small>
170
+ * Fixed warnings: "parenthesize argument(s) for future version"
171
+ * Fixed a bug in the restore_ancestry_integrity! method (thx Arthur Holstvoogd)
172
+
173
+ ## Version [1.2.4] <small>2011-04-22</small>
174
+ * Prepended table names to column names in queries (thx @raelik)
175
+ * Better check to see if acts_as_tree can be overloaded (thx @jims)
176
+ * Performance inprovements (thx @kueda)
177
+
178
+ ## Version [1.2.3] <small>2010-10-28</small>
179
+ * Fixed error with determining ActiveRecord version
180
+ * Added option to specify :primary_key_format (thx @rolftimmermans)
181
+
182
+ ## Version [1.2.2] <small>2010-10-24</small>
183
+ * Fixed all deprecation warnings for rails 3.0.X
184
+ * Added `:report` option to `check_ancestry_integrity!`
185
+ * Changed ActiveRecord dependency to 2.2.2
186
+ * Tested and fixed for ruby 1.8.7 and 1.9.2
187
+ * Changed usage of `update_attributes` to `update_attribute` to allow ancestry column protection
188
+
189
+ ## Version [1.2.0] <small>2009-11-07</small>
190
+ * Removed some duplication in has_ancestry
191
+ * Cleaned up plugin pattern according to http://yehudakatz.com/2009/11/12/better-ruby-idioms/
192
+ * Moved parts of ancestry into seperate files
193
+ * Made it possible to pass options into the arrange method
194
+ * Renamed acts_as_tree to has_ancestry
195
+ * Aliased has_ancestry as acts_as_tree if acts_as_tree is available
196
+ * Added subtree_of scope
197
+ * Updated ordered_by_ancestry scope to support Microsoft SQL Server
198
+ * Added empty hash as parameter to exists? calls for older ActiveRecord versions
199
+
200
+ ## Version [1.1.4] <small>2009-11-07</small>
201
+ * Thanks to a patch from tom taylor, Ancestry now works with different primary keys
202
+
203
+ ## Version [1.1.3] <small>2009-11-01</small>
204
+ * Fixed a pretty bad bug where several operations took far too many queries
205
+
206
+ ## Version [1.1.2] <small>2009-10-29</small>
207
+ * Added validation for depth cache column
208
+ * Added STI support (reported broken)
209
+
210
+ ## Version [1.1.1] <small>2009-10-28</small>
211
+ * Fixed some parentheses warnings that where reported
212
+ * Fixed a reported issue with arrangement
213
+ * Fixed issues with ancestors and path order on postgres
214
+ * Added ordered_by_ancestry scope (needed to fix issues)
215
+
216
+ ## Version [1.1.0] <small>2009-10-22</small>
217
+ * Depth caching (and cache rebuilding)
218
+ * Depth method for nodes
219
+ * Named scopes for selecting by depth
220
+ * Relative depth options for tree navigation methods:
221
+ * ancestors
222
+ * path
223
+ * descendants
224
+ * descendant_ids
225
+ * subtree
226
+ * subtree_ids
227
+ * Updated README
228
+ * Easy migration from existing plugins/gems
229
+ * acts_as_tree checks unknown options
230
+ * acts_as_tree checks that options are hash
231
+ * Added a bang (!) to the integrity functions
232
+ * Since these functions should only be used from ./script/console and not
233
+ from your application, this change is not considered as breaking backwards
234
+ compatibility and the major version wasn't bumped.
235
+ * Updated install script to point to documentation
236
+ * Removed rails specific init
237
+ * Removed uninstall script
238
+
239
+ ## Version 1.0.0 <small>2009-10-16</small>
240
+ * Initial version
241
+ * Tree building
242
+ * Tree navigation
243
+ * Integrity checking / restoration
244
+ * Arrangement
245
+ * Orphan strategies
246
+ * Subtree movement
247
+ * Named scopes
248
+ * Validations
249
+
250
+
251
+ [HEAD]: https://github.com/stefankroes/ancestry/compare/v3.2.0...HEAD
252
+ [3.1.0]: https://github.com/stefankroes/ancestry/compare/v3.1.0...v3.2.0
253
+ [3.1.0]: https://github.com/stefankroes/ancestry/compare/v3.0.7...v3.1.0
254
+ [3.0.7]: https://github.com/stefankroes/ancestry/compare/v3.0.6...v3.0.7
255
+ [3.0.6]: https://github.com/stefankroes/ancestry/compare/v3.0.5...v3.0.6
256
+ [3.0.5]: https://github.com/stefankroes/ancestry/compare/v3.0.4...v3.0.5
257
+ [3.0.4]: https://github.com/stefankroes/ancestry/compare/v3.0.3...v3.0.4
258
+ [3.0.3]: https://github.com/stefankroes/ancestry/compare/v3.0.2...v3.0.3
259
+ [3.0.2]: https://github.com/stefankroes/ancestry/compare/v3.0.1...v3.0.2
260
+ [3.0.1]: https://github.com/stefankroes/ancestry/compare/v3.0.0...v3.0.1
261
+ [3.0.0]: https://github.com/stefankroes/ancestry/compare/v2.2.2...v3.0.0
262
+ [2.2.2]: https://github.com/stefankroes/ancestry/compare/v2.2.1...v2.2.2
263
+ [2.2.1]: https://github.com/stefankroes/ancestry/compare/v2.2.0...v2.2.1
264
+ [2.2.0]: https://github.com/stefankroes/ancestry/compare/v2.1.0...v2.2.0
265
+ [2.1.0]: https://github.com/stefankroes/ancestry/compare/v2.0.0...v2.1.0
266
+ [2.0.0]: https://github.com/stefankroes/ancestry/compare/v1.3.0...v2.0.0
267
+ [1.3.0]: https://github.com/stefankroes/ancestry/compare/v1.2.5...v1.3.0
268
+ [1.2.5]: https://github.com/stefankroes/ancestry/compare/v1.2.4...v1.2.5
269
+ [1.2.4]: https://github.com/stefankroes/ancestry/compare/v1.2.3...v1.2.4
270
+ [1.2.3]: https://github.com/stefankroes/ancestry/compare/v1.2.2...v1.2.3
271
+ [1.2.2]: https://github.com/stefankroes/ancestry/compare/v1.2.0...v1.2.2
272
+ [1.2.0]: https://github.com/stefankroes/ancestry/compare/v1.1.4...v1.2.0
273
+ [1.1.4]: https://github.com/stefankroes/ancestry/compare/v1.1.3...v1.1.4
274
+ [1.1.3]: https://github.com/stefankroes/ancestry/compare/v1.1.2...v1.1.3
275
+ [1.1.2]: https://github.com/stefankroes/ancestry/compare/v1.1.1...v1.1.2
276
+ [1.1.1]: https://github.com/stefankroes/ancestry/compare/v1.1.0...v1.1.1
277
+ [1.1.0]: https://github.com/stefankroes/ancestry/compare/v1.0.0...v1.1.0
data/README.md CHANGED
@@ -3,24 +3,24 @@
3
3
  # Ancestry
4
4
 
5
5
  Ancestry is a gem that allows the records of a Ruby on Rails
6
- ActiveRecord model to be organised as a tree structure (or hierarchy). It uses
7
- a single database column, using the materialised path pattern. It exposes all the standard tree structure
8
- relations (ancestors, parent, root, children, siblings, descendants) and all
9
- of them can be fetched in a single SQL query. Additional features are STI
6
+ ActiveRecord model to be organised as a tree structure (or hierarchy). It employs
7
+ the materialised path pattern and exposes all the standard tree structure
8
+ relations (ancestors, parent, root, children, siblings, descendants), allowing all
9
+ of them to be fetched in a single SQL query. Additional features include STI
10
10
  support, scopes, depth caching, depth constraints, easy migration from older
11
11
  gems, integrity checking, integrity restoration, arrangement of
12
- (sub)tree into hashes and different strategies for dealing with orphaned
12
+ (sub)trees into hashes, and various strategies for dealing with orphaned
13
13
  records.
14
14
 
15
15
  NOTE:
16
16
 
17
- - Ancestry 3.x supports Rails 5.0 and earlier.
17
+ - Ancestry 2.x supports Rails 4.1 and earlier
18
+ - Ancestry 3.x supports Rails 5.0 and 4.2
18
19
  - Ancestry 4.0 only supports rails 5.0 and higher
19
20
 
20
21
  # Installation
21
22
 
22
- To apply Ancestry to any `ActiveRecord` model, follow these simple steps:
23
-
23
+ Follow these simple steps to apply Ancestry to any ActiveRecord model:
24
24
 
25
25
  ## Install
26
26
 
@@ -54,7 +54,7 @@ $ rake db:migrate
54
54
 
55
55
 
56
56
  ## Add ancestry to your model
57
- * Add to [app/models/](model).rb:
57
+ * Add to app/models/[model.rb]:
58
58
 
59
59
  ```ruby
60
60
  # app/models/[model.rb]
@@ -68,9 +68,9 @@ Your model is now a tree!
68
68
 
69
69
  # Using acts_as_tree instead of has_ancestry
70
70
 
71
- In version 1.2.0 the **acts_as_tree** method was **renamed to has_ancestry**
71
+ In version 1.2.0, the **acts_as_tree** method was **renamed to has_ancestry**
72
72
  in order to allow usage of both the acts_as_tree gem and the ancestry gem in a
73
- single application. method `acts_as_tree` will continue to be supported in the future.
73
+ single application. The `acts_as_tree` method will continue to be supported in the future.
74
74
 
75
75
  # Organising records into a tree
76
76
 
@@ -81,64 +81,38 @@ parent_id can be set using parent= and parent_id= on a record or by including
81
81
  them in the hash passed to new, create, create!, update_attributes and
82
82
  update_attributes!. For example:
83
83
 
84
- ```ruby
85
- TreeNode.create! :name => 'Stinky', :parent => TreeNode.create!(:name => 'Squeeky')
86
- ```
84
+ `TreeNode.create! :name => 'Stinky', :parent => TreeNode.create!(:name => 'Squeeky')`.
87
85
 
88
- You can also create children through the children relation on a node:
86
+ Children can be created through the children relation on a node: `node.children.create :name => 'Stinky'`.
89
87
 
90
- ```ruby
91
- node.children.create :name => 'Stinky'
92
- ```
88
+ # Tree Navigation
89
+
90
+ The node with the large border is the reference node (the node from which the navigation method is invoked.)
91
+ The yellow nodes are those returned by the method.
92
+
93
+ | | | |
94
+ |:-: |:-: |:-: |
95
+ |**parent** |**root**<sup><a href="#fn1" id="ref1">1</a></sup> |**ancestors** |
96
+ |![parent](/img/parent.png) |![root](/img/root.png) |![ancestors](/img/ancestors.png) |
97
+ | nil for a root node |self for a root node |root..parent |
98
+ | `parent_id` |`root_id` |`ancestor_ids` |
99
+ | `has_parent?` |`is_root?` |`ancestors?` |
100
+ |`parent_of?` |`root_of?` |`ancestor_of?` |
101
+ |**children** |**descendants** |**indirects** |
102
+ |![children](/img/children.png) |![descendants](/img/descendants.png) |![indirects](/img/indirects.png) |
103
+ | `child_ids` |`descendant_ids` |`indirect_ids` |
104
+ | `has_children?` | | |
105
+ | `child_of?` |`descendant_of?` |`indirect_of?` |
106
+ |**siblings** |**subtree** |**path** |
107
+ |![siblings](/img/siblings.png) |![subtree](/img/subtree.png) |![path](/img/path.png) |
108
+ | includes self |self..indirects |root..self |
109
+ |`sibling_ids` |`subtree_ids` |`path_ids` |
110
+ |`has_siblings?` | | |
111
+ |`sibling_of?(node)` | | |
93
112
 
94
- # Navigating your tree
95
-
96
- To navigate an Ancestry model, use the following instance methods:
97
-
98
- | method |return value|
99
- |-------------------|------------|
100
- |`parent` |parent of the record, nil for a root node|
101
- |`parent_id` |parent id of the record, nil for a root node|
102
- |`root` |root of the record's tree, self for a root node|
103
- |`root_id` |root id of the record's tree, self for a root node|
104
- |`root?` <br/> `is_root?` | true if the record is a root node, false otherwise|
105
- |`ancestors` |ancestors of the record, starting with the root and ending with the parent|
106
- |`ancestors?` |true if the record has ancestors (aka not a root node)|
107
- |`ancestor_ids` |ancestor ids of the record|
108
- |`path` |path of the record, starting with the root and ending with self|
109
- |`path_ids` |a list the path ids, starting with the root id and ending with the node's own id|
110
- |`children` |direct children of the record|
111
- |`child_ids` |direct children's ids|
112
- |`has_parent?` <br/> `ancestors?` |true if the record has a parent, false otherwise|
113
- |`has_children?` <br/> `children?` |true if the record has any children, false otherwise|
114
- |`is_childless?` <br/> `childless?` |true is the record has no children, false otherwise|
115
- |`siblings` |siblings of the record, the record itself is included*|
116
- |`sibling_ids` |sibling ids|
117
- |`has_siblings?` <br/> `siblings?` |true if the record's parent has more than one child|
118
- |`is_only_child?` <br/> `only_child?` |true if the record is the only child of its parent|
119
- |`descendants` |direct and indirect children of the record|
120
- |`descendant_ids` |direct and indirect children's ids of the record|
121
- |`indirects` |indirect children of the record|
122
- |`indirect_ids` |indirect children's ids of the record|
123
- |`subtree` |the model on descendants and itself|
124
- |`subtree_ids` |a list of all ids in the record's subtree|
125
- |`depth` |the depth of the node, root nodes are at depth 0|
126
-
127
- \* If the record is a root, other root records are considered siblings
128
- \* Siblings returns the record itself
129
-
130
- There are also instance methods to determine the relationship between 2 nodes:
131
-
132
- |method |return value|
133
- |-------------------|---------------|
134
- |`parent_of?(node)` | node's parent is this record|
135
- |`root_of?(node)` | node's root is this record|
136
- |`ancestor_of?(node)`| node's ancestors include this record|
137
- |`child_of?(node)` | node is record's parent|
138
- |`descendant_of?(node)` | node is one of this record's ancestors|
139
- |`indirect_of?(node)` | node is one of this record's ancestors but not a parent|
140
-
141
- # Options for `has_ancestry`
113
+ <sup id="fn1">1. [other root records are considered siblings]<a href="#ref1" title="Jump back to footnote 1.">↩</a></sup>
114
+
115
+ # `has_ancestry` options
142
116
 
143
117
  The has_ancestry method supports the following options:
144
118
 
@@ -147,24 +121,22 @@ The has_ancestry method supports the following options:
147
121
  :destroy All children are destroyed as well (default)
148
122
  :rootify The children of the destroyed node become root nodes
149
123
  :restrict An AncestryException is raised if any children exist
150
- :adopt The orphan subtree is added to the parent of the deleted node.
151
- If the deleted node is Root, then rootify the orphan subtree.
124
+ :adopt The orphan subtree is added to the parent of the deleted node
125
+ If the deleted node is Root, then rootify the orphan subtree
152
126
  :cache_depth Cache the depth of each node in the 'ancestry_depth' column (default: false)
153
127
  If you turn depth_caching on for an existing model:
154
128
  - Migrate: add_column [table], :ancestry_depth, :integer, :default => 0
155
129
  - Build cache: TreeNode.rebuild_depth_cache!
156
130
  :depth_cache_column Pass in a symbol to store depth cache in a different column
157
- :primary_key_format Supply a regular expression that matches the format of your primary key.
158
- By default, primary keys only match integers ([0-9]+).
131
+ :primary_key_format Supply a regular expression that matches the format of your primary key
132
+ By default, primary keys only match integers ([0-9]+)
159
133
  :touch Instruct Ancestry to touch the ancestors of a node when it changes, to
160
134
  invalidate nested key-based caches. (default: false)
161
135
 
162
136
  # (Named) Scopes
163
137
 
164
- Where possible, the navigation methods return scopes instead of records, this
165
- means additional ordering, conditions, limits, etc. can be applied and that
166
- the result can be either retrieved, counted or checked for existence. For
167
- example:
138
+ The navigation methods return scopes instead of records, where possible. Additional ordering,
139
+ conditions, limits, etc. can be applied and the results can be retrieved, counted, or checked for existence:
168
140
 
169
141
  ```ruby
170
142
  node.children.where(:name => 'Mary').exists?
@@ -172,7 +144,7 @@ node.subtree.order(:name).limit(10).each { ... }
172
144
  node.descendants.count
173
145
  ```
174
146
 
175
- For convenience, a couple of named scopes are included at the class level:
147
+ A couple of class-level named scopes are included:
176
148
 
177
149
  roots Root nodes
178
150
  ancestors_of(node) Ancestors of node, node can be either a record or an id
@@ -182,8 +154,7 @@ For convenience, a couple of named scopes are included at the class level:
182
154
  subtree_of(node) Subtree of node, node can be either a record or an id
183
155
  siblings_of(node) Siblings of node, node can be either a record or an id
184
156
 
185
- Thanks to some convenient rails magic, it is even possible to create nodes
186
- through the children and siblings scopes:
157
+ It is possible thanks to some convenient rails magic to create nodes through the children and siblings scopes:
187
158
 
188
159
  node.children.create
189
160
  node.siblings.create!
@@ -192,8 +163,8 @@ through the children and siblings scopes:
192
163
 
193
164
  # Selecting nodes by depth
194
165
 
195
- When depth caching is enabled (see has_ancestry options), five more named
196
- scopes can be used to select nodes on their depth:
166
+ With depth caching enabled (see has_ancestry options), an additional five named
167
+ scopes can be used to select nodes by depth:
197
168
 
198
169
  before_depth(depth) Return nodes that are less deep than depth (node.depth < depth)
199
170
  to_depth(depth) Return nodes up to a certain depth (node.depth <= depth)
@@ -201,42 +172,27 @@ scopes can be used to select nodes on their depth:
201
172
  from_depth(depth) Return nodes starting from a certain depth (node.depth >= depth)
202
173
  after_depth(depth) Return nodes that are deeper than depth (node.depth > depth)
203
174
 
204
- The depth scopes are also available through calls to descendants,
205
- descendant_ids, subtree, subtree_ids, path and ancestors. In this case, depth
206
- values are interpreted relatively. Some examples:
207
-
208
- node.subtree(:to_depth => 2) Subtree of node, to a depth of node.depth + 2 (self, children and grandchildren)
209
- node.subtree.to_depth(5) Subtree of node to an absolute depth of 5
210
- node.descendants(:at_depth => 2) Descendant of node, at depth node.depth + 2 (grandchildren)
211
- node.descendants.at_depth(10) Descendants of node at an absolute depth of 10
212
- node.ancestors.to_depth(3) The oldest 4 ancestors of node (its root and 3 more)
213
- node.path(:from_depth => -2) The node's grandparent, parent and the node itself
175
+ Depth scopes are also available through calls to `descendants`,
176
+ `descendant_ids`, `subtree`, `subtree_ids`, `path` and `ancestors` (with relative depth).
177
+ Note that depth constraints cannot be passed to `ancestor_ids` or `path_ids` as both relations
178
+ can be fetched directly from the ancestry column without needing a query. Use
179
+ `ancestors(depth_options).map(&:id)` or `ancestor_ids.slice(min_depth..max_depth)` instead.
214
180
 
215
181
  node.ancestors(:from_depth => -6, :to_depth => -4)
216
182
  node.path.from_depth(3).to_depth(4)
217
183
  node.descendants(:from_depth => 2, :to_depth => 4)
218
184
  node.subtree.from_depth(10).to_depth(12)
219
185
 
220
- Please note that depth constraints cannot be passed to ancestor_ids and
221
- path_ids. The reason for this is that both these relations can be fetched
222
- directly from the ancestry column without performing a database query. It
223
- would require an entirely different method of applying the depth constraints
224
- which isn't worth the effort of implementing. You can use
225
- ancestors(depth_options).map(&:id) or ancestor_ids.slice(min_depth..max_depth)
226
- instead.
227
-
228
186
  # STI support
229
187
 
230
- Ancestry works fine with STI. Just create a STI inheritance hierarchy and
231
- build an Ancestry tree from the different classes/models. All Ancestry
232
- relations that were described above will return nodes of any model type. If
233
- you do only want nodes of a specific subclass you'll have to add a condition
234
- on type for that.
188
+ To use with STI: create a STI inheritance hierarchy and build a tree from the different
189
+ classes/models. All Ancestry relations that were described above will return nodes of any model type. If
190
+ you do only want nodes of a specific subclass, a type condition is required.
235
191
 
236
192
  # Arrangement
237
193
 
238
- Ancestry can arrange an entire subtree into nested hashes for easy navigation
239
- after retrieval from the database. TreeNode.arrange could for example return:
194
+ A subtree can be arranged into nested hashes for easy navigation after database retrieval.
195
+ `TreeNode.arrange` could, for instance, return:
240
196
 
241
197
  ```ruby
242
198
  {
@@ -249,43 +205,20 @@ after retrieval from the database. TreeNode.arrange could for example return:
249
205
  }
250
206
  ```
251
207
 
252
- The arrange method also works on a scoped class, for example:
253
-
254
- ```ruby
255
- TreeNode.find_by_name('Crunchy').subtree.arrange
256
- ```
257
-
258
- The arrange method takes `ActiveRecord` find options. If you want your hashes to
259
- be ordered, you should pass the order to the arrange method instead of to the
260
- scope. example:
208
+ The `arrange` method can work on a scoped class (`TreeNode.find_by(:name => 'Crunchy').subtree.arrange`),
209
+ and can take ActiveRecord find options. If you want ordered hashes, pass the order to the method instead of
210
+ the scope as follows:
261
211
 
262
- ```ruby
263
- TreeNode.find_by_name('Crunchy').subtree.arrange(:order => :name)
264
- ```
212
+ `TreeNode.find_by(:name => 'Crunchy').subtree.arrange(:order => :name)`.
265
213
 
266
- To get the arranged nodes as a nested array of hashes for serialization:
214
+ The `arrange_serializable` method returns the arranged nodes as a nested array of hashes. Order
215
+ can be passed in the same fashion as to the `arrange` method:
216
+ `TreeNode.arrange_serializable(:order => :name)` The result can easily be serialized to json with `to_json`
217
+ or other formats. You can also supply your own serialization logic with blocks.
267
218
 
268
- TreeNode.arrange_serializable
219
+ Using `ActiveModel` serializers:
269
220
 
270
- ```ruby
271
- [
272
- {
273
- "ancestry" => nil, "id" => 1, "children" => [
274
- { "ancestry" => "1", "id" => 2, "children" => [] }
275
- ]
276
- }
277
- ]
278
- ```
279
-
280
- You can also supply your own serialization logic using blocks:
281
-
282
- For example, using `ActiveModel` Serializers:
283
-
284
- ```ruby
285
- TreeNode.arrange_serializable do |parent, children|
286
- MySerializer.new(parent, children: children)
287
- end
288
- ```
221
+ `TreeNode.arrange_serializable { |parent, children| MySerializer.new(parent, children: children) }`.
289
222
 
290
223
  Or plain hashes:
291
224
 
@@ -298,39 +231,22 @@ TreeNode.arrange_serializable do |parent, children|
298
231
  end
299
232
  ```
300
233
 
301
- The result of arrange_serializable can easily be serialized to json with
302
- `to_json`, or some other format:
303
-
304
- ```
305
- TreeNode.arrange_serializable.to_json
306
- ```
307
-
308
- You can also pass the order to the arrange_serializable method just as you can
309
- pass it to the arrange method:
310
-
311
- ```
312
- TreeNode.arrange_serializable(:order => :name)
313
- ```
314
-
315
234
  # Sorting
316
235
 
317
- If you just want to sort an array of nodes as if you were traversing them in
318
- preorder, you can use the sort_by_ancestry class method:
319
-
320
- ```
321
- TreeNode.sort_by_ancestry(array_of_nodes)
322
- ```
323
-
324
- Note that since materialised path trees don't support ordering within a rank,
325
- the order of siblings depends on their order in the original array.
236
+ The `sort_by_ancestry` class method: `TreeNode.sort_by_ancestry(array_of_nodes)` can be used
237
+ to sort an array of nodes as if traversing in preorder. (Note that since materialised path
238
+ trees do not support ordering within a rank, the order of siblings is
239
+ dependant upon their original array order.)
326
240
 
327
241
  # Migrating from plugin that uses parent_id column
328
242
 
329
243
  Most current tree plugins use a parent_id column (has_ancestry,
330
- awesome_nested_set, better_nested_set, acts_as_nested_set). With ancestry it is
331
- easy to migrate from any of these plugins, to do so, use the
332
- build_ancestry_from_parent_ids! method on your ancestry model. These steps
333
- provide a more detailed explanation:
244
+ awesome_nested_set, better_nested_set, acts_as_nested_set). With Ancestry it is
245
+ easy to migrate from any of these plugins. To do so, use the
246
+ `build_ancestry_from_parent_ids!` method on your ancestry model.
247
+
248
+ <details>
249
+ <summary>Details</summary>
334
250
 
335
251
  1. Add ancestry column to your table
336
252
  * Create migration: **rails g migration [add_ancestry_to_](table)
@@ -340,7 +256,7 @@ provide a more detailed explanation:
340
256
  * Migrate your database: **rake db:migrate**
341
257
 
342
258
 
343
- 2. Remove old tree gem and add in Ancestry to `Gemfile`
259
+ 2. Remove old tree gem and add in Ancestry to Gemfile
344
260
  * See 'Installation' for more info on installing and configuring gems
345
261
 
346
262
 
@@ -351,7 +267,7 @@ provide a more detailed explanation:
351
267
 
352
268
 
353
269
  4. Generate ancestry columns
354
- * In './script.console': **[model].build_ancestry_from_parent_ids!**
270
+ * In rails console: **[model].build_ancestry_from_parent_ids!**
355
271
  * Make sure it worked ok: **[model].check_ancestry_integrity!**
356
272
 
357
273
 
@@ -365,42 +281,7 @@ provide a more detailed explanation:
365
281
  * Create migration: `rails g migration [remove_parent_id_from_](table)`
366
282
  * Add to migration: `remove_column [table], :parent_id`
367
283
  * Migrate your database: `rake db:migrate`
368
-
369
- # Integrity checking and restoration
370
-
371
- I don't see any way Ancestry tree integrity could get compromised without
372
- explicitly setting cyclic parents or invalid ancestry and circumventing
373
- validation with update_attribute, if you do, please let me know.
374
-
375
- Ancestry includes some methods for detecting integrity problems and restoring
376
- integrity just to be sure. To check integrity use:
377
- [Model].check_ancestry_integrity!. An AncestryIntegrityException will be
378
- raised if there are any problems. You can also specify :report => :list to
379
- return an array of exceptions or :report => :echo to echo any error messages.
380
- To restore integrity use: [Model].restore_ancestry_integrity!.
381
-
382
- For example, from IRB:
383
-
384
- ```
385
- >> stinky = TreeNode.create :name => 'Stinky'
386
- $ #<TreeNode id: 1, name: "Stinky", ancestry: nil>
387
- >> squeeky = TreeNode.create :name => 'Squeeky', :parent => stinky
388
- $ #<TreeNode id: 2, name: "Squeeky", ancestry: "1">
389
- >> stinky.update_attribute :parent, squeeky
390
- $ true
391
- >> TreeNode.all
392
- $ [#<TreeNode id: 1, name: "Stinky", ancestry: "1/2">, #<TreeNode id: 2, name: "Squeeky", ancestry: "1/2/1">]
393
- >> TreeNode.check_ancestry_integrity!
394
- !! Ancestry::AncestryIntegrityException: Conflicting parent id in node 1: 2 for node 1, expecting nil
395
- >> TreeNode.restore_ancestry_integrity!
396
- $ [#<TreeNode id: 1, name: "Stinky", ancestry: 2>, #<TreeNode id: 2, name: "Squeeky", ancestry: nil>]
397
- ```
398
-
399
- Additionally, if you think something is wrong with your depth cache:
400
-
401
- ```
402
- >> TreeNode.rebuild_depth_cache!
403
- ```
284
+ </details>
404
285
 
405
286
  # Running Tests
406
287