ancestry 3.2.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d11437b15407107e0d4690084bc462a50d97d4fe9615445ff295a96d74943c67
4
- data.tar.gz: e2bdffb78316b524828c0a6d38c0c0e4101ef71c57bda836272d41e0381b44c3
3
+ metadata.gz: 82bcd1895093ab9b569806ef05fc307fc2ca9ab53ffeb09199bd66fe3672ecfb
4
+ data.tar.gz: fe7d0d356641658be2953309c27dd28a42e81ed569690cc5e26b2721b1aa6a37
5
5
  SHA512:
6
- metadata.gz: 533b6b0cc2db821091081f09c7680cbe163abbcc85500d278c52625861bdd901a7623232cde8ccbf21f3e0960a5231adb889055555e4849d75ede13651f626ad
7
- data.tar.gz: 6f754739730731009eee294e9a6fed1d268d3f0cbf4024cec96221a0a68b5f59569ac47bb42f13e3e7798f76982d35ff35b03a01fe44f4d217b7e3e37c9c62d4
6
+ metadata.gz: f33384a1114d865662be0133c532249be0e7ea438a66e469947b3aaba3172378ae50309e02c4f219c1f161281a9e060bff6087a496850c26351fd83348627e79
7
+ data.tar.gz: 2a6cb3fb28f6c9a8228b522c590c2125c4e31056a97ac6a6cda96ea4152725fe89e375b59c894091ebcd3d5be36ad18b348c6691211bc6bea2b0a49502c9f423
data/CHANGELOG.md ADDED
@@ -0,0 +1,303 @@
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 [4.2.0] <sub><sup>2022-06-09</sub></sup>
7
+
8
+ * added strategy: materialized_path2 [#571](https://github.com/stefankroes/ancestry/pull/571)
9
+ * Added tree_view method [#561](https://github.com/stefankroes/ancestry/pull/561) (thx @bizcho)
10
+ * Fixed bug when errors would not undo callbacks [#566](https://github.com/stefankroes/ancestry/pull/566) (thx @daniloisr)
11
+ * ruby 3.0 support
12
+ * rails 7.0 support (thx @chenillen, @petergoldstein)
13
+ * Documentation fixes (thx @benkoshy, @mijoharas)
14
+
15
+ ## Version [4.1.0] <sub><sup>2021-06-25</sub></sup>
16
+
17
+ * `parent` with an invalid id now returns nil (thx @vanboom)
18
+ * `root` returns self if ancestry is invalid (thx @vanboom)
19
+ * fix case where invalid object prevented ancestry updates (thx @d-m-u)
20
+ * oracleenhanced uses nulls first for sorting (thx @lual)
21
+ * fix counter cache and STI (thx @mattvague)
22
+
23
+ ## Version [4.0.0] <sub><sup>2021-04-12</sub></sup>
24
+
25
+ * dropped support for rails 4.2 and 5.0 (thx @d-m-u)
26
+ * better documentation counter cache option (thx @pustomytnyk)
27
+ * clean up code (thx @amatsuda @d-m-u)
28
+ * fixed rails 6.1 support (thx @cmr119 @d-staehler @danini-the-panini )
29
+ * phasing out `parent_id?`, `ancestors?` and using `has_parent?` instead
30
+ * fixed postgres order bug on rails 6.2 and higher (thx @smoyt)
31
+
32
+ ## Version [3.2.1] <sub><sup>2020-09-23</sub></sup>
33
+
34
+ * fixed gemspec to include locales and pg (thx @HectorMF)
35
+
36
+ ## Version [3.2.0] <sub><sup>2020-09-23</sub></sup>
37
+
38
+ * introduce i18n
39
+ * pg sql optimization for ancestry changes (thx @suonlight and @geis)
40
+ * pg sql optimization for sorting (thx @brendon and @d-m-u)
41
+ * fix to humanise model name (thx @mkllnk)
42
+ * able to convert to ancestry from a parent_id column with a different name
43
+ * documentation fixes for better diagrams and grammar (thx @dtamais, @d-m-u, and @CamilleDrapier)
44
+
45
+ ## Version [3.1.0] <sub><sup>2020-08-03</sub></sup>
46
+
47
+ * `:primary_key_format` method lets you change syntax. good for uuids.
48
+ * changed code from being `ancestry` string to `ancestry_ids` focused. May break monkey patches.
49
+ * Moved many methods from `has_ancestry` and `InstanceMethods` to `MaterializedPath`. May break monkey patches.
50
+ * Removed tests for `mysql` driver. Starting with rails 4.1, it supports `mysql2` driver.
51
+ * Better documentation for relationships (thnx @dtamai and @d-m-u)
52
+ * Fix creating children in `after_*` callbacks (thx @jstirk)
53
+
54
+ ## Version [3.0.7] <sub><sup>2018-11-06</sub></sup>
55
+
56
+ * Fixed rails 5.1 change detection (thx @jrafanie)
57
+ * Introduce counter cache (thx @hw676018683)
58
+
59
+ ## Version [3.0.6] <sub><sup>2018-11-06</sub></sup>
60
+
61
+ * Fixed rails 4.1 version check (thx @myxoh)
62
+
63
+ ## Version [3.0.5] <sub><sup>2018-11-06</sub></sup>
64
+
65
+ ## Changed
66
+
67
+ * Added indirect children support (thx @tilo)
68
+ * Fixed test sorting for pg on mac osx
69
+
70
+ ## Fixes
71
+
72
+ * Reduced memory footprint of parsing ancestry column (thx @NickLaMuro)
73
+
74
+ ## Version [3.0.4] <sub><sup>2018-10-27</sub></sup>
75
+
76
+ ## Fixes
77
+
78
+ * Properly detects non-integer columns (thx @adam101)
79
+ * Arrange no longer drops nodes due to missing parents (thx @trafium)
80
+
81
+ ## Version [3.0.3] <sub><sup>2018-10-23</sub></sup>
82
+
83
+ This branch (3.x) should still be compatible with rails 3 and 4.
84
+ Rails 5.1 and 5.2 support were introduced in this version, but ongoing support
85
+ has been moved to ancestry 4.0
86
+
87
+ ## Fixes
88
+
89
+ * Reduce object allocation (thx @NickLaMuro)
90
+ * Rails 5.1 fixes (thx @ctrombley)
91
+ * Avoid redundant query to DB in subtree_of scope (thx @Slike9)
92
+ * Syntax tweaks (thx @ekohl, @richardonrails)
93
+ * Fixed reverse ordering
94
+ * Dropped builds for ruby 1.9.3, 2.0, 2.1, and 2.2
95
+ * Dropped builds for Rails 3.x and 4.x (will use Active Record `or` syntax)
96
+
97
+ ## Version [3.0.2] <sub><sup>2018-04-24</sub></sup>
98
+
99
+ ## Fixes
100
+
101
+ * fixed `order_by_ancestry` bug
102
+ * fixed order tests for postgres on mac (it uses a different collation)
103
+ * fixed documentation (thx @besquared, @danfrenette, @eiwi1101, @isimluk, @mabusaad, @tilsammans)
104
+ * added missing `Ancestry::version`
105
+ * added Rails 5.2 support (thx @jjuliano)
106
+
107
+ ## Version [3.0.1] <sub><sup>2017-07-05</sub></sup>
108
+
109
+ ## Fixes
110
+
111
+ * added gem metadata
112
+ * fixed keep a changelog link (thx @mattbrictson)
113
+ * added alias has_parent?
114
+ * fixed bug where unscoping too much (thx @brendon)
115
+ * fixed tests on mysql 5.7 and rails 3.2
116
+ * Dropped 3.1 scope changes
117
+
118
+ ## Version [3.0.0] <sub><sup>2017-05-18</sub></sup>
119
+
120
+ ## Changed
121
+
122
+ * Dropping Rails 3.0, and 3.1. Added Rails 5.1 support (thx @ledermann)
123
+ * Dropping Rails 4.0, 4.1 for build reasons. Since 4.2 is supported, all 4.x should still work.
124
+
125
+ ## Fixes
126
+
127
+ * Performance: Use `pluck` vs `map` for ids (thx @njakobsen and @culturecode)
128
+ * Fixed acts_as_tree compatibility (thx @crazymykl)
129
+ * Fixed loading ActiveRails prematurely (thx @vovimayhem)
130
+ * Fixes exist (thx @ledermann)
131
+ * Properly touches parents when different class for STI (thx @samtgarson)
132
+ * Fixed issues with parent_id (only present on master) (thx @domcleal)
133
+
134
+ ## Version [2.2.2] <sub><sup>2016-11-01</sub></sup>
135
+
136
+ ### Changed
137
+
138
+ * Use `COALESCE` only for sorting versions greater than 5.0
139
+ * Fixed bug with explicit order clauses (introduced in 2.2.0)
140
+ * No longer load schema on `has_ancestry` load (thx @ledermann)
141
+
142
+ ## Version [2.2.1] <sub><sup>2016-10-25</sub></sup>
143
+
144
+ Sorry for blip, local master got out of sync with upstream master.
145
+ Missed 2 commits (which are feature adds)
146
+
147
+ ### Added
148
+ * Use like (vs ilike) for rails 5.0 (performance enhancement)
149
+ * Use `COALESCE` for sorting on pg, mysql, and sqlite vs `CASE`
150
+
151
+ ## Version [2.2.0] <sub><sup>2016-10-25</sub></sup>
152
+
153
+ ### Added
154
+ * Predicates for scopes: e.g.: `ancestor_of?`, `parent_of?` (thx @neglectedvalue)
155
+ * Scope `path_of`
156
+
157
+ ### Changed
158
+ * `arrange` now accepts blocks (thx @mastfish)
159
+ * Performance tuning `arrange_node` (thx @fryguy)
160
+ * In orphan strategy, set `ancestry` to `nil` for no parents (thx @haslinger)
161
+ * Only updates `updated_at` when a record is changed (thx @brocktimus)
162
+ * No longer casts text primary key as an integer
163
+ * Upgrading tests for ruby versions (thx @brocktimus, @fryguy, @yui-knk)
164
+ * Fix non-default ancestry not getting used properly (thx @javiyu)
165
+
166
+ ## Version [2.1.0] <sub><sup>2014-04-16</sub></sup>
167
+ * Added arrange_serializable (thx @krishandley, @chicagogrrl)
168
+ * Add the :touch to update ancestors on save (thx @adammck)
169
+ * Change conditions into arel (thx @mlitwiniuk)
170
+ * Added children? & siblings? alias (thx @bigtunacan)
171
+ * closure_tree compatibility (thx @gzigzigzeo)
172
+ * Performance tweak (thx @mjc)
173
+ * Improvements to organization (thx @xsuchy, @ryakh)
174
+
175
+ ## Version [2.0.0] <sub><sup>2013-05-17</sub></sup>
176
+ * Removed rails 2 compatibility
177
+ * Added table name to condition constructing methods (thx @aflatter)
178
+ * Fix depth_cache not being updated when moving up to ancestors (thx @scottatron)
179
+ * add alias :root? to existing is_root? (thx @divineforest)
180
+ * Add block to sort_by_ancestry (thx @Iliya)
181
+ * Add attribute query method for parent_id (thx @sj26)
182
+ * Fixed and tested for rails 4 (thx @adammck, @Nihad, @Systho, @Philippe, e.a.)
183
+ * Fixed overwriting ActiveRecord::Base.base_class (thx @Rozhnov)
184
+ * New adopt strategy (thx unknown)
185
+ * Many more improvements
186
+
187
+ ## Version [1.3.0] <sub><sup>2012-05-04</sub></sup>
188
+ * Ancestry now ignores default scopes when moving or destroying nodes, ensuring tree consistency
189
+ * Changed ActiveRecord dependency to 2.3.14
190
+
191
+ ## Version [1.2.5] <sub><sup>2012-03-15</sub></sup>
192
+ * Fixed warnings: "parenthesize argument(s) for future version"
193
+ * Fixed a bug in the restore_ancestry_integrity! method (thx Arthur Holstvoogd)
194
+
195
+ ## Version [1.2.4] <sub><sup>2011-04-22</sub></sup>
196
+ * Prepended table names to column names in queries (thx @raelik)
197
+ * Better check to see if acts_as_tree can be overloaded (thx @jims)
198
+ * Performance inprovements (thx @kueda)
199
+
200
+ ## Version [1.2.3] <sub><sup>2010-10-28</sub></sup>
201
+ * Fixed error with determining ActiveRecord version
202
+ * Added option to specify :primary_key_format (thx @rolftimmermans)
203
+
204
+ ## Version [1.2.2] <sub><sup>2010-10-24</sub></sup>
205
+ * Fixed all deprecation warnings for rails 3.0.X
206
+ * Added `:report` option to `check_ancestry_integrity!`
207
+ * Changed ActiveRecord dependency to 2.2.2
208
+ * Tested and fixed for ruby 1.8.7 and 1.9.2
209
+ * Changed usage of `update_attributes` to `update_attribute` to allow ancestry column protection
210
+
211
+ ## Version [1.2.0] <sub><sup>2009-11-07</sub></sup>
212
+ * Removed some duplication in has_ancestry
213
+ * Cleaned up plugin pattern according to http://yehudakatz.com/2009/11/12/better-ruby-idioms/
214
+ * Moved parts of ancestry into seperate files
215
+ * Made it possible to pass options into the arrange method
216
+ * Renamed acts_as_tree to has_ancestry
217
+ * Aliased has_ancestry as acts_as_tree if acts_as_tree is available
218
+ * Added subtree_of scope
219
+ * Updated ordered_by_ancestry scope to support Microsoft SQL Server
220
+ * Added empty hash as parameter to exists? calls for older ActiveRecord versions
221
+
222
+ ## Version [1.1.4] <sub><sup>2009-11-07</sub></sup>
223
+ * Thanks to a patch from tom taylor, Ancestry now works with different primary keys
224
+
225
+ ## Version [1.1.3] <sub><sup>2009-11-01</sub></sup>
226
+ * Fixed a pretty bad bug where several operations took far too many queries
227
+
228
+ ## Version [1.1.2] <sub><sup>2009-10-29</sub></sup>
229
+ * Added validation for depth cache column
230
+ * Added STI support (reported broken)
231
+
232
+ ## Version [1.1.1] <sub><sup>2009-10-28</sub></sup>
233
+ * Fixed some parentheses warnings that where reported
234
+ * Fixed a reported issue with arrangement
235
+ * Fixed issues with ancestors and path order on postgres
236
+ * Added ordered_by_ancestry scope (needed to fix issues)
237
+
238
+ ## Version [1.1.0] <sub><sup>2009-10-22</sub></sup>
239
+ * Depth caching (and cache rebuilding)
240
+ * Depth method for nodes
241
+ * Named scopes for selecting by depth
242
+ * Relative depth options for tree navigation methods:
243
+ * ancestors
244
+ * path
245
+ * descendants
246
+ * descendant_ids
247
+ * subtree
248
+ * subtree_ids
249
+ * Updated README
250
+ * Easy migration from existing plugins/gems
251
+ * acts_as_tree checks unknown options
252
+ * acts_as_tree checks that options are hash
253
+ * Added a bang (!) to the integrity functions
254
+ * Since these functions should only be used from ./script/console and not
255
+ from your application, this change is not considered as breaking backwards
256
+ compatibility and the major version wasn't bumped.
257
+ * Updated install script to point to documentation
258
+ * Removed rails specific init
259
+ * Removed uninstall script
260
+
261
+ ## Version 1.0.0 <sub><sup>2009-10-16</sub></sup>
262
+ * Initial version
263
+ * Tree building
264
+ * Tree navigation
265
+ * Integrity checking / restoration
266
+ * Arrangement
267
+ * Orphan strategies
268
+ * Subtree movement
269
+ * Named scopes
270
+ * Validations
271
+
272
+
273
+ [HEAD]: https://github.com/stefankroes/ancestry/compare/v4.2.0...HEAD
274
+ [4.2.0]: https://github.com/stefankroes/ancestry/compare/v4.1.0...v4.2.0
275
+ [4.1.0]: https://github.com/stefankroes/ancestry/compare/v4.0.0...v4.1.0
276
+ [4.0.0]: https://github.com/stefankroes/ancestry/compare/v3.2.1...v4.0.0
277
+ [3.2.1]: https://github.com/stefankroes/ancestry/compare/v3.2.0...v3.2.1
278
+ [3.2.0]: https://github.com/stefankroes/ancestry/compare/v3.1.0...v3.2.0
279
+ [3.1.0]: https://github.com/stefankroes/ancestry/compare/v3.0.7...v3.1.0
280
+ [3.0.7]: https://github.com/stefankroes/ancestry/compare/v3.0.6...v3.0.7
281
+ [3.0.6]: https://github.com/stefankroes/ancestry/compare/v3.0.5...v3.0.6
282
+ [3.0.5]: https://github.com/stefankroes/ancestry/compare/v3.0.4...v3.0.5
283
+ [3.0.4]: https://github.com/stefankroes/ancestry/compare/v3.0.3...v3.0.4
284
+ [3.0.3]: https://github.com/stefankroes/ancestry/compare/v3.0.2...v3.0.3
285
+ [3.0.2]: https://github.com/stefankroes/ancestry/compare/v3.0.1...v3.0.2
286
+ [3.0.1]: https://github.com/stefankroes/ancestry/compare/v3.0.0...v3.0.1
287
+ [3.0.0]: https://github.com/stefankroes/ancestry/compare/v2.2.2...v3.0.0
288
+ [2.2.2]: https://github.com/stefankroes/ancestry/compare/v2.2.1...v2.2.2
289
+ [2.2.1]: https://github.com/stefankroes/ancestry/compare/v2.2.0...v2.2.1
290
+ [2.2.0]: https://github.com/stefankroes/ancestry/compare/v2.1.0...v2.2.0
291
+ [2.1.0]: https://github.com/stefankroes/ancestry/compare/v2.0.0...v2.1.0
292
+ [2.0.0]: https://github.com/stefankroes/ancestry/compare/v1.3.0...v2.0.0
293
+ [1.3.0]: https://github.com/stefankroes/ancestry/compare/v1.2.5...v1.3.0
294
+ [1.2.5]: https://github.com/stefankroes/ancestry/compare/v1.2.4...v1.2.5
295
+ [1.2.4]: https://github.com/stefankroes/ancestry/compare/v1.2.3...v1.2.4
296
+ [1.2.3]: https://github.com/stefankroes/ancestry/compare/v1.2.2...v1.2.3
297
+ [1.2.2]: https://github.com/stefankroes/ancestry/compare/v1.2.0...v1.2.2
298
+ [1.2.0]: https://github.com/stefankroes/ancestry/compare/v1.1.4...v1.2.0
299
+ [1.1.4]: https://github.com/stefankroes/ancestry/compare/v1.1.3...v1.1.4
300
+ [1.1.3]: https://github.com/stefankroes/ancestry/compare/v1.1.2...v1.1.3
301
+ [1.1.2]: https://github.com/stefankroes/ancestry/compare/v1.1.1...v1.1.2
302
+ [1.1.1]: https://github.com/stefankroes/ancestry/compare/v1.1.0...v1.1.1
303
+ [1.1.0]: https://github.com/stefankroes/ancestry/compare/v1.0.0...v1.1.0
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://travis-ci.org/stefankroes/ancestry.svg?branch=master)](https://travis-ci.org/stefankroes/ancestry) [![Coverage Status](https://coveralls.io/repos/stefankroes/ancestry/badge.svg)](https://coveralls.io/r/stefankroes/ancestry) [![Gitter](https://badges.gitter.im/Join+Chat.svg)](https://gitter.im/stefankroes/ancestry?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Security](https://hakiri.io/github/stefankroes/ancestry/master.svg)](https://hakiri.io/github/stefankroes/ancestry/master)
1
+ [![Gitter](https://badges.gitter.im/Join+Chat.svg)](https://gitter.im/stefankroes/ancestry?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2
2
 
3
3
  # Ancestry
4
4
 
@@ -44,6 +44,8 @@ $ bundle install
44
44
 
45
45
  ```bash
46
46
  $ rails g migration add_ancestry_to_[table] ancestry:string:index
47
+ # or use different column name of your choosing. e.g. name:
48
+ # rails g migration add_name_to_[people] name:string:index
47
49
  ```
48
50
 
49
51
  * Migrate your database:
@@ -52,6 +54,20 @@ $ rails g migration add_ancestry_to_[table] ancestry:string:index
52
54
  $ rake db:migrate
53
55
  ```
54
56
 
57
+ Depending upon your comfort with databases, you may want to create the column
58
+ with `C` or `POSIX` encoding. This is a more primitive encoding and just compares
59
+ bytes. Since this column will just contains numbers and slashes, it works much
60
+ better. It also works better for the uuid case as well.
61
+
62
+ Alternatively, if you create a [`text_pattern_ops`](https://www.postgresql.org/docs/current/indexes-opclass.html) index for your postgresql column, subtree selection will use an efficient index for you regardless of whether you created the column with `POSIX` encoding.
63
+
64
+ If you opt out of this, and are trying to run tests on postgres, you may need to
65
+ set the environment variable `COLLATE_SYMBOLS=false`. Sorry to say that a discussion
66
+ on this topic is out of scope. The important take away is postgres sort order is
67
+ not consistent across operating systems but other databases do not have this same
68
+ issue.
69
+
70
+ NOTE: A Btree index (as is recommended) has a limitaton of 2704 characters for the ancestry column. This means you can't have an tree with a depth that is too great (~> 900 items at most).
55
71
 
56
72
  ## Add ancestry to your model
57
73
  * Add to app/models/[model.rb]:
@@ -60,7 +76,8 @@ $ rake db:migrate
60
76
  # app/models/[model.rb]
61
77
 
62
78
  class [Model] < ActiveRecord::Base
63
- has_ancestry
79
+ has_ancestry # or alternatively as below:
80
+ # has_ancestry ancestry_column: :name ## if you've used a different column name
64
81
  end
65
82
  ```
66
83
 
@@ -132,6 +149,9 @@ The has_ancestry method supports the following options:
132
149
  By default, primary keys only match integers ([0-9]+)
133
150
  :touch Instruct Ancestry to touch the ancestors of a node when it changes, to
134
151
  invalidate nested key-based caches. (default: false)
152
+ :counter_cache Boolean whether to create counter cache column accessor.
153
+ Default column name is `children_count`.
154
+ Pass symbol to use different column name (default: false)
135
155
 
136
156
  # (Named) Scopes
137
157
 
@@ -16,7 +16,7 @@ module Ancestry
16
16
  if [:before_depth, :to_depth, :at_depth, :from_depth, :after_depth].include? scope_name
17
17
  scope.send scope_name, depth + relative_depth
18
18
  else
19
- raise Ancestry::AncestryException.new(I18n.t("ancestry.unknown_depth_option", {:scope_name => scope_name}))
19
+ raise Ancestry::AncestryException.new(I18n.t("ancestry.unknown_depth_option", scope_name: scope_name))
20
20
  end
21
21
  end
22
22
  end
@@ -74,6 +74,20 @@ module Ancestry
74
74
  end
75
75
  end
76
76
 
77
+ def tree_view(column, data = nil)
78
+ data = arrange unless data
79
+ data.each do |parent, children|
80
+ if parent.depth == 0
81
+ puts parent[column]
82
+ else
83
+ num = parent.depth - 1
84
+ indent = " "*num
85
+ puts " #{"|" if parent.depth > 1}#{indent}|_ #{parent[column]}"
86
+ end
87
+ tree_view(column, children) if children
88
+ end
89
+ end
90
+
77
91
  # Pseudo-preordered array of nodes. Children will always follow parents,
78
92
  def sort_by_ancestry(nodes, &block)
79
93
  arranged = nodes if nodes.is_a?(Hash)
@@ -217,31 +231,15 @@ module Ancestry
217
231
  end
218
232
 
219
233
  def unscoped_where
220
- if ActiveRecord::VERSION::MAJOR < 4
221
- self.ancestry_base_class.unscoped do
222
- yield self.ancestry_base_class
223
- end
224
- else
225
- yield self.ancestry_base_class.unscope(:where)
226
- end
234
+ yield self.ancestry_base_class.default_scoped.unscope(:where)
227
235
  end
228
236
 
229
237
  ANCESTRY_UNCAST_TYPES = [:string, :uuid, :text].freeze
230
- if ActiveSupport::VERSION::STRING < "4.2"
231
- def primary_key_is_an_integer?
232
- if defined?(@primary_key_is_an_integer)
233
- @primary_key_is_an_integer
234
- else
235
- @primary_key_is_an_integer = !ANCESTRY_UNCAST_TYPES.include?(columns_hash[primary_key.to_s].type)
236
- end
237
- end
238
- else
239
- def primary_key_is_an_integer?
240
- if defined?(@primary_key_is_an_integer)
241
- @primary_key_is_an_integer
242
- else
243
- @primary_key_is_an_integer = !ANCESTRY_UNCAST_TYPES.include?(type_for_attribute(primary_key).type)
244
- end
238
+ def primary_key_is_an_integer?
239
+ if defined?(@primary_key_is_an_integer)
240
+ @primary_key_is_an_integer
241
+ else
242
+ @primary_key_is_an_integer = !ANCESTRY_UNCAST_TYPES.include?(type_for_attribute(primary_key).type)
245
243
  end
246
244
  end
247
245
  end
@@ -4,8 +4,8 @@ module Ancestry
4
4
  # Check options
5
5
  raise Ancestry::AncestryException.new(I18n.t("ancestry.option_must_be_hash")) unless options.is_a? Hash
6
6
  options.each do |key, value|
7
- unless [:ancestry_column, :orphan_strategy, :cache_depth, :depth_cache_column, :touch, :counter_cache, :primary_key_format, :update_strategy].include? key
8
- raise Ancestry::AncestryException.new(I18n.t("ancestry.unknown_option", {:key => key.inspect, :value => value.inspect}))
7
+ unless [:ancestry_column, :orphan_strategy, :cache_depth, :depth_cache_column, :touch, :counter_cache, :primary_key_format, :update_strategy, :strategy].include? key
8
+ raise Ancestry::AncestryException.new(I18n.t("ancestry.unknown_option", key: key.inspect, value: value.inspect))
9
9
  end
10
10
  end
11
11
 
@@ -27,8 +27,13 @@ module Ancestry
27
27
  # Include dynamic class methods
28
28
  extend Ancestry::ClassMethods
29
29
 
30
- validates_format_of self.ancestry_column, :with => derive_ancestry_pattern(options[:primary_key_format]), :allow_nil => true
31
- extend Ancestry::MaterializedPath
30
+ if options[:strategy] == :materialized_path2
31
+ validates_format_of self.ancestry_column, :with => derive_materialized2_pattern(options[:primary_key_format]), :allow_nil => false
32
+ extend Ancestry::MaterializedPath2
33
+ else
34
+ validates_format_of self.ancestry_column, :with => derive_materialized_pattern(options[:primary_key_format]), :allow_nil => true
35
+ extend Ancestry::MaterializedPath
36
+ end
32
37
 
33
38
  update_strategy = options[:update_strategy] || Ancestry.default_update_strategy
34
39
  include Ancestry::MaterializedPathPg if update_strategy == :sql
@@ -87,12 +92,7 @@ module Ancestry
87
92
 
88
93
  after_touch :touch_ancestors_callback
89
94
  after_destroy :touch_ancestors_callback
90
-
91
- if ActiveRecord::VERSION::STRING >= '5.1.0'
92
- after_save :touch_ancestors_callback, if: :saved_changes?
93
- else
94
- after_save :touch_ancestors_callback, if: :changed?
95
- end
95
+ after_save :touch_ancestors_callback, if: :saved_changes?
96
96
  end
97
97
 
98
98
  def acts_as_tree(*args)
@@ -102,7 +102,7 @@ module Ancestry
102
102
 
103
103
  private
104
104
 
105
- def derive_ancestry_pattern(primary_key_format, delimiter = '/')
105
+ def derive_materialized_pattern(primary_key_format, delimiter = '/')
106
106
  primary_key_format ||= '[0-9]+'
107
107
 
108
108
  if primary_key_format.to_s.include?('\A')
@@ -111,9 +111,19 @@ module Ancestry
111
111
  /\A#{primary_key_format}(#{delimiter}#{primary_key_format})*\Z/
112
112
  end
113
113
  end
114
+
115
+ def derive_materialized2_pattern(primary_key_format, delimiter = '/')
116
+ primary_key_format ||= '[0-9]+'
117
+
118
+ if primary_key_format.to_s.include?('\A')
119
+ primary_key_format
120
+ else
121
+ /\A#{delimiter}(#{primary_key_format}#{delimiter})*\Z/
122
+ end
123
+ end
114
124
  end
115
125
  end
116
126
 
117
127
  ActiveSupport.on_load :active_record do
118
- send :extend, Ancestry::HasAncestry
128
+ extend Ancestry::HasAncestry
119
129
  end
@@ -2,13 +2,13 @@ module Ancestry
2
2
  module InstanceMethods
3
3
  # Validate that the ancestors don't include itself
4
4
  def ancestry_exclude_self
5
- errors.add(:base, I18n.t("ancestry.exclude_self", {:class_name => self.class.name.humanize})) if ancestor_ids.include? self.id
5
+ errors.add(:base, I18n.t("ancestry.exclude_self", class_name: self.class.name.humanize)) if ancestor_ids.include? self.id
6
6
  end
7
7
 
8
8
  # Update descendants with new ancestry (before save)
9
9
  def update_descendants_with_new_ancestry
10
10
  # If enabled and node is existing and ancestry was updated and the new ancestry is sane ...
11
- if !ancestry_callbacks_disabled? && !new_record? && ancestry_changed? && sane_ancestry?
11
+ if !ancestry_callbacks_disabled? && !new_record? && ancestry_changed? && sane_ancestor_ids?
12
12
  # ... for each descendant ...
13
13
  unscoped_descendants.each do |descendant|
14
14
  # ... replace old ancestry with new ancestry
@@ -39,7 +39,7 @@ module Ancestry
39
39
  when :adopt # make child elements of this node, child of its parent
40
40
  descendants.each do |descendant|
41
41
  descendant.without_ancestry_callbacks do
42
- descendant.update_attribute :ancestor_ids, descendant.ancestor_ids.delete_if { |x| x == self.id }
42
+ descendant.update_attribute :ancestor_ids, (descendant.ancestor_ids.delete_if { |x| x == self.id })
43
43
  end
44
44
  end
45
45
  when :restrict # throw an exception if it has children
@@ -62,7 +62,7 @@ module Ancestry
62
62
 
63
63
  # Counter Cache
64
64
  def increase_parent_counter_cache
65
- self.class.increment_counter _counter_cache_column, parent_id
65
+ self.ancestry_base_class.increment_counter _counter_cache_column, parent_id
66
66
  end
67
67
 
68
68
  def decrease_parent_counter_cache
@@ -74,24 +74,19 @@ module Ancestry
74
74
  return if defined?(@_trigger_destroy_callback) && !@_trigger_destroy_callback
75
75
  return if ancestry_callbacks_disabled?
76
76
 
77
- self.class.decrement_counter _counter_cache_column, parent_id
77
+ self.ancestry_base_class.decrement_counter _counter_cache_column, parent_id
78
78
  end
79
79
 
80
80
  def update_parent_counter_cache
81
- changed =
82
- if ActiveRecord::VERSION::STRING >= '5.1.0'
83
- saved_change_to_attribute?(self.ancestry_base_class.ancestry_column)
84
- else
85
- ancestry_changed?
86
- end
81
+ changed = saved_change_to_attribute?(self.ancestry_base_class.ancestry_column)
87
82
 
88
83
  return unless changed
89
84
 
90
85
  if parent_id_was = parent_id_before_last_save
91
- self.class.decrement_counter _counter_cache_column, parent_id_was
86
+ self.ancestry_base_class.decrement_counter _counter_cache_column, parent_id_was
92
87
  end
93
88
 
94
- parent_id && self.class.increment_counter(_counter_cache_column, parent_id)
89
+ parent_id && self.ancestry_base_class.increment_counter(_counter_cache_column, parent_id)
95
90
  end
96
91
 
97
92
  def _counter_cache_column
@@ -100,28 +95,37 @@ module Ancestry
100
95
 
101
96
  # Ancestors
102
97
 
103
- def ancestors?
98
+ def has_parent?
104
99
  ancestor_ids.present?
105
100
  end
106
- alias :has_parent? :ancestors?
101
+ alias :ancestors? :has_parent?
107
102
 
108
103
  def ancestry_changed?
109
104
  column = self.ancestry_base_class.ancestry_column.to_s
110
- if ActiveRecord::VERSION::STRING >= '5.1.0'
111
105
  # These methods return nil if there are no changes.
112
106
  # This was fixed in a refactoring in rails 6.0: https://github.com/rails/rails/pull/35933
113
107
  !!(will_save_change_to_attribute?(column) || saved_change_to_attribute?(column))
114
- else
115
- changed.include?(column)
116
- end
117
108
  end
118
109
 
119
110
  def sane_ancestor_ids?
120
- valid? || errors[self.ancestry_base_class.ancestry_column].blank?
111
+ current_context, self.validation_context = validation_context, nil
112
+ errors.clear
113
+
114
+ attribute = ancestry_base_class.ancestry_column
115
+ ancestry_value = send(attribute)
116
+ return true unless ancestry_value
117
+
118
+ self.class.validators_on(attribute).each do |validator|
119
+ validator.validate_each(self, attribute, ancestry_value)
120
+ end
121
+ ancestry_exclude_self
122
+ errors.none?
123
+ ensure
124
+ self.validation_context = current_context
121
125
  end
122
126
 
123
127
  def ancestors depth_options = {}
124
- return self.ancestry_base_class.none unless ancestors?
128
+ return self.ancestry_base_class.none unless has_parent?
125
129
  self.ancestry_base_class.scope_depth(depth_options, depth).ordered_by_ancestry.ancestors_of(self)
126
130
  end
127
131
 
@@ -162,12 +166,16 @@ module Ancestry
162
166
  end
163
167
 
164
168
  def parent_id
165
- ancestor_ids.last if ancestors?
169
+ ancestor_ids.last if has_parent?
166
170
  end
167
171
  alias :parent_id? :ancestors?
168
172
 
169
173
  def parent
170
- unscoped_find(parent_id) if ancestors?
174
+ if has_parent?
175
+ unscoped_where do |scope|
176
+ scope.find_by scope.primary_key => parent_id
177
+ end
178
+ end
171
179
  end
172
180
 
173
181
  def parent_of?(node)
@@ -177,15 +185,19 @@ module Ancestry
177
185
  # Root
178
186
 
179
187
  def root_id
180
- ancestors? ? ancestor_ids.first : id
188
+ has_parent? ? ancestor_ids.first : id
181
189
  end
182
190
 
183
191
  def root
184
- ancestors? ? unscoped_find(root_id) : self
192
+ if has_parent?
193
+ unscoped_where { |scope| scope.find_by(id: root_id) } || self
194
+ else
195
+ self
196
+ end
185
197
  end
186
198
 
187
199
  def is_root?
188
- !ancestors?
200
+ !has_parent?
189
201
  end
190
202
  alias :root? :is_root?
191
203
 
@@ -285,6 +297,7 @@ module Ancestry
285
297
  def without_ancestry_callbacks
286
298
  @disable_ancestry_callbacks = true
287
299
  yield
300
+ ensure
288
301
  @disable_ancestry_callbacks = false
289
302
  end
290
303
 
@@ -0,0 +1,16 @@
1
+ en:
2
+ ancestry:
3
+ unknown_depth_option: "Unknown depth option: %{scope_name}."
4
+ invalid_orphan_strategy: "Invalid orphan strategy, valid ones are :rootify, :adopt, :restrict and :destroy."
5
+ invalid_ancestry_column: "Invalid format for ancestry column of node %{node_id}: %{ancestry_column}."
6
+ reference_nonexistent_node: "Reference to nonexistent node in node %{node_id}: %{ancestor_id}."
7
+ conflicting_parent_id: "Conflicting parent id found in node %{node_id}: %{parent_id} for node %{node_id} while expecting %{expected}"
8
+ cannot_rebuild_depth_cache: "Cannot rebuild depth cache for model without depth caching."
9
+
10
+ option_must_be_hash: "Options for has_ancestry must be in a hash."
11
+ unknown_option: "Unknown option for has_ancestry: %{key} => %{value}."
12
+ named_scope_depth_cache: "Named scope '%{scope_name}' is only available when depth caching is enabled."
13
+
14
+ exclude_self: "%{class_name} cannot be a descendant of itself."
15
+ cannot_delete_descendants: "Cannot delete record because it has descendants."
16
+ no_child_for_new_record: "No child ancestry for new record. Save record before performing tree operations."
@@ -1,8 +1,12 @@
1
1
  module Ancestry
2
+ # store ancestry as grandparent_id/parent_id
3
+ # root a=nil,id=1 children=id,id/% == 1, 1/%
4
+ # 3: a=1/2,id=3 children=a/id,a/id/% == 1/2/3, 1/2/3/%
2
5
  module MaterializedPath
3
- BEFORE_LAST_SAVE_SUFFIX = ActiveRecord::VERSION::STRING >= '5.1.0' ? '_before_last_save'.freeze : '_was'.freeze
4
- IN_DATABASE_SUFFIX = ActiveRecord::VERSION::STRING >= '5.1.0' ? '_in_database'.freeze : '_was'.freeze
6
+ BEFORE_LAST_SAVE_SUFFIX = '_before_last_save'.freeze
7
+ IN_DATABASE_SUFFIX = '_in_database'.freeze
5
8
  ANCESTRY_DELIMITER='/'.freeze
9
+ ROOT=nil
6
10
 
7
11
  def self.extended(base)
8
12
  base.send(:include, InstanceMethods)
@@ -13,7 +17,7 @@ module Ancestry
13
17
  end
14
18
 
15
19
  def roots
16
- where(arel_table[ancestry_column].eq(nil))
20
+ where(arel_table[ancestry_column].eq(ROOT))
17
21
  end
18
22
 
19
23
  def ancestors_of(object)
@@ -38,34 +42,25 @@ module Ancestry
38
42
  def indirects_of(object)
39
43
  t = arel_table
40
44
  node = to_node(object)
41
- # rails has case sensitive matching.
42
- if ActiveRecord::VERSION::MAJOR >= 5
43
- where(t[ancestry_column].matches("#{node.child_ancestry}/%", nil, true))
44
- else
45
- where(t[ancestry_column].matches("#{node.child_ancestry}/%"))
46
- end
45
+ where(t[ancestry_column].matches("#{node.child_ancestry}#{ANCESTRY_DELIMITER}%", nil, true))
47
46
  end
48
47
 
49
48
  def descendants_of(object)
50
- where(descendant_conditions(object))
49
+ node = to_node(object)
50
+ indirects_of(node).or(children_of(node))
51
51
  end
52
52
 
53
53
  # deprecated
54
54
  def descendant_conditions(object)
55
55
  t = arel_table
56
56
  node = to_node(object)
57
- # rails has case sensitive matching.
58
- if ActiveRecord::VERSION::MAJOR >= 5
59
- t[ancestry_column].matches("#{node.child_ancestry}/%", nil, true).or(t[ancestry_column].eq(node.child_ancestry))
60
- else
61
- t[ancestry_column].matches("#{node.child_ancestry}/%").or(t[ancestry_column].eq(node.child_ancestry))
62
- end
57
+ t[ancestry_column].matches("#{node.child_ancestry}/%", nil, true).or(t[ancestry_column].eq(node.child_ancestry))
63
58
  end
64
59
 
65
60
  def subtree_of(object)
66
61
  t = arel_table
67
62
  node = to_node(object)
68
- where(descendant_conditions(node).or(t[primary_key].eq(node.id)))
63
+ descendants_of(node).or(where(t[primary_key].eq(node.id)))
69
64
  end
70
65
 
71
66
  def siblings_of(object)
@@ -77,8 +72,8 @@ module Ancestry
77
72
  def ordered_by_ancestry(order = nil)
78
73
  if %w(mysql mysql2 sqlite sqlite3).include?(connection.adapter_name.downcase)
79
74
  reorder(arel_table[ancestry_column], order)
80
- elsif %w(postgresql).include?(connection.adapter_name.downcase) && ActiveRecord::VERSION::STRING >= "6.1"
81
- reorder(Arel::Nodes::Ascending.new(arel_table[ancestry_column]).nulls_first)
75
+ elsif %w(postgresql oracleenhanced).include?(connection.adapter_name.downcase) && ActiveRecord::VERSION::STRING >= "6.1"
76
+ reorder(Arel::Nodes::Ascending.new(arel_table[ancestry_column]).nulls_first, order)
82
77
  else
83
78
  reorder(
84
79
  Arel::Nodes::Ascending.new(Arel::Nodes::NamedFunction.new('COALESCE', [arel_table[ancestry_column], Arel.sql("''")])),
@@ -92,22 +87,15 @@ module Ancestry
92
87
  end
93
88
 
94
89
  module InstanceMethods
95
-
96
- # Validates the ancestry, but can also be applied if validation is bypassed to determine if children should be affected
97
- def sane_ancestry?
98
- ancestry_value = read_attribute(self.ancestry_base_class.ancestry_column)
99
- (ancestry_value.nil? || !ancestor_ids.include?(self.id)) && valid?
100
- end
101
-
102
90
  # optimization - better to go directly to column and avoid parsing
103
91
  def ancestors?
104
- read_attribute(self.ancestry_base_class.ancestry_column).present?
92
+ read_attribute(self.ancestry_base_class.ancestry_column) != ROOT
105
93
  end
106
94
  alias :has_parent? :ancestors?
107
95
 
108
96
  def ancestor_ids=(value)
109
97
  col = self.ancestry_base_class.ancestry_column
110
- value.present? ? write_attribute(col, value.join(ANCESTRY_DELIMITER)) : write_attribute(col, nil)
98
+ value.present? ? write_attribute(col, generate_ancestry(value)) : write_attribute(col, ROOT)
111
99
  end
112
100
 
113
101
  def ancestor_ids
@@ -124,7 +112,7 @@ module Ancestry
124
112
 
125
113
  def parent_id_before_last_save
126
114
  ancestry_was = send("#{self.ancestry_base_class.ancestry_column}#{BEFORE_LAST_SAVE_SUFFIX}")
127
- return unless ancestry_was.present?
115
+ return if ancestry_was == ROOT
128
116
 
129
117
  parse_ancestry_column(ancestry_was).last
130
118
  end
@@ -141,16 +129,18 @@ module Ancestry
141
129
  # New records cannot have children
142
130
  raise Ancestry::AncestryException.new(I18n.t("ancestry.no_child_for_new_record")) if new_record?
143
131
  path_was = self.send("#{self.ancestry_base_class.ancestry_column}#{IN_DATABASE_SUFFIX}")
144
- path_was.blank? ? id.to_s : "#{path_was}/#{id}"
132
+ path_was.blank? ? id.to_s : "#{path_was}#{ANCESTRY_DELIMITER}#{id}"
145
133
  end
146
134
 
147
- private
148
-
149
- def parse_ancestry_column obj
150
- return [] unless obj
135
+ def parse_ancestry_column(obj)
136
+ return [] if obj == ROOT
151
137
  obj_ids = obj.split(ANCESTRY_DELIMITER)
152
138
  self.class.primary_key_is_an_integer? ? obj_ids.map!(&:to_i) : obj_ids
153
139
  end
140
+
141
+ def generate_ancestry(ancestor_ids)
142
+ ancestor_ids.join(ANCESTRY_DELIMITER)
143
+ end
154
144
  end
155
145
  end
156
146
  end
@@ -0,0 +1,54 @@
1
+ module Ancestry
2
+ # store ancestry as /grandparent_id/parent_id/
3
+ # root: a=/,id=1 children=a.id/% == /1/%
4
+ # 3: a=/1/2/,id=3 children=a.id/% == /1/2/3/%
5
+ module MaterializedPath2 < MaterializedPath
6
+ def indirects_of(object)
7
+ t = arel_table
8
+ node = to_node(object)
9
+ where(t[ancestry_column].matches("#{node.child_ancestry}%#{ANCESTRY_DELIMITER}%", nil, true))
10
+ end
11
+
12
+ def subtree_of(object)
13
+ t = arel_table
14
+ node = to_node(object)
15
+ where(descendant_conditions(node).or(t[primary_key].eq(node.id)))
16
+ end
17
+
18
+ def siblings_of(object)
19
+ t = arel_table
20
+ node = to_node(object)
21
+ where(t[ancestry_column].eq(node[ancestry_column]))
22
+ end
23
+
24
+ def ordered_by_ancestry(order = nil)
25
+ reorder(Arel::Nodes::Ascending.new(arel_table[ancestry_column]), order)
26
+ end
27
+
28
+ # deprecated
29
+ def descendant_conditions(object)
30
+ t = arel_table
31
+ node = to_node(object)
32
+ t[ancestry_column].matches("#{node.child_ancestry}%", nil, true)
33
+ end
34
+
35
+ module InstanceMethods
36
+ def child_ancestry
37
+ # New records cannot have children
38
+ raise Ancestry::AncestryException.new('No child ancestry for new record. Save record before performing tree operations.') if new_record?
39
+ path_was = self.send("#{self.ancestry_base_class.ancestry_column}#{IN_DATABASE_SUFFIX}")
40
+ "#{path_was}#{id}#{ANCESTRY_DELIMITER}"
41
+ end
42
+
43
+ def parse_ancestry_column(obj)
44
+ return [] if obj == ROOT
45
+ obj_ids = obj.split(ANCESTRY_DELIMITER).delete_if(&:blank?)
46
+ self.class.primary_key_is_an_integer? ? obj_ids.map!(&:to_i) : obj_ids
47
+ end
48
+
49
+ def generate_ancestry(ancestor_ids)
50
+ "#{ANCESTRY_DELIMITER}#{ancestor_ids.join(ANCESTRY_DELIMITER)}#{ANCESTRY_DELIMITER}"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,23 @@
1
+ module Ancestry
2
+ module MaterializedPathPg
3
+ # Update descendants with new ancestry (before save)
4
+ def update_descendants_with_new_ancestry
5
+ # If enabled and node is existing and ancestry was updated and the new ancestry is sane ...
6
+ if !ancestry_callbacks_disabled? && !new_record? && ancestry_changed? && sane_ancestor_ids?
7
+ ancestry_column = ancestry_base_class.ancestry_column
8
+ old_ancestry = path_ids_in_database.join(Ancestry::MaterializedPath::ANCESTRY_DELIMITER)
9
+ new_ancestry = path_ids.join(Ancestry::MaterializedPath::ANCESTRY_DELIMITER)
10
+ update_clause = [
11
+ "#{ancestry_column} = regexp_replace(#{ancestry_column}, '^#{old_ancestry}', '#{new_ancestry}')"
12
+ ]
13
+
14
+ if ancestry_base_class.respond_to?(:depth_cache_column) && respond_to?(ancestry_base_class.depth_cache_column)
15
+ depth_cache_column = ancestry_base_class.depth_cache_column.to_s
16
+ update_clause << "#{depth_cache_column} = length(regexp_replace(regexp_replace(ancestry, '^#{old_ancestry}', '#{new_ancestry}'), '\\d', '', 'g')) + 1"
17
+ end
18
+
19
+ unscoped_descendants.update_all update_clause.join(', ')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Ancestry
2
- VERSION = "3.2.0"
2
+ VERSION = '4.2.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ancestry
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Kroes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-09-23 00:00:00.000000000 Z
12
+ date: 2022-06-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: 4.2.0
20
+ version: 5.2.6
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: 4.2.0
27
+ version: 5.2.6
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: appraisal
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -67,6 +67,20 @@ dependencies:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
69
  version: '13.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: simplecov
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
70
84
  - !ruby/object:Gem::Dependency
71
85
  name: yard
72
86
  requirement: !ruby/object:Gem::Requirement
@@ -94,17 +108,18 @@ executables: []
94
108
  extensions: []
95
109
  extra_rdoc_files: []
96
110
  files:
111
+ - CHANGELOG.md
97
112
  - MIT-LICENSE
98
113
  - README.md
99
- - ancestry.gemspec
100
- - init.rb
101
- - install.rb
102
114
  - lib/ancestry.rb
103
115
  - lib/ancestry/class_methods.rb
104
116
  - lib/ancestry/exceptions.rb
105
117
  - lib/ancestry/has_ancestry.rb
106
118
  - lib/ancestry/instance_methods.rb
119
+ - lib/ancestry/locales/en.yml
107
120
  - lib/ancestry/materialized_path.rb
121
+ - lib/ancestry/materialized_path2.rb
122
+ - lib/ancestry/materialized_path_pg.rb
108
123
  - lib/ancestry/version.rb
109
124
  homepage: https://github.com/stefankroes/ancestry
110
125
  licenses:
@@ -114,7 +129,8 @@ metadata:
114
129
  changelog_uri: https://github.com/stefankroes/ancestry/blob/master/CHANGELOG.md
115
130
  source_code_uri: https://github.com/stefankroes/ancestry/
116
131
  bug_tracker_uri: https://github.com/stefankroes/ancestry/issues
117
- post_install_message:
132
+ post_install_message: Thank you for installing Ancestry. You can visit http://github.com/stefankroes/ancestry
133
+ to read the documentation.
118
134
  rdoc_options: []
119
135
  require_paths:
120
136
  - lib
@@ -122,15 +138,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
138
  requirements:
123
139
  - - ">="
124
140
  - !ruby/object:Gem::Version
125
- version: 2.0.0
141
+ version: '2.5'
126
142
  required_rubygems_version: !ruby/object:Gem::Requirement
127
143
  requirements:
128
144
  - - ">="
129
145
  - !ruby/object:Gem::Version
130
146
  version: '0'
131
147
  requirements: []
132
- rubyforge_project:
133
- rubygems_version: 2.7.6.2
148
+ rubygems_version: 3.3.7
134
149
  signing_key:
135
150
  specification_version: 4
136
151
  summary: Organize ActiveRecord model into a tree structure
data/ancestry.gemspec DELETED
@@ -1,51 +0,0 @@
1
- lib = File.expand_path('../lib/', __FILE__)
2
- $:.unshift lib unless $:.include?(lib)
3
- require 'ancestry/version'
4
-
5
- Gem::Specification.new do |s|
6
- s.name = 'ancestry'
7
- s.summary = 'Organize ActiveRecord model into a tree structure'
8
- s.description = <<-EOF
9
- Ancestry allows the records of a ActiveRecord model to be organized in a tree
10
- structure, using the materialized path pattern. It exposes the standard
11
- relations (ancestors, parent, root, children, siblings, descendants)
12
- and allows them to be fetched in a single query. Additional features include
13
- named scopes, integrity checking, integrity restoration, arrangement
14
- of (sub)tree into hashes and different strategies for dealing with orphaned
15
- records.
16
- EOF
17
- s.metadata = {
18
- "homepage_uri" => "https://github.com/stefankroes/ancestry",
19
- "changelog_uri" => "https://github.com/stefankroes/ancestry/blob/master/CHANGELOG.md",
20
- "source_code_uri" => "https://github.com/stefankroes/ancestry/",
21
- "bug_tracker_uri" => "https://github.com/stefankroes/ancestry/issues",
22
- }
23
- s.version = Ancestry::VERSION
24
-
25
- s.authors = ['Stefan Kroes', 'Keenan Brock']
26
- s.email = 'keenan@thebrocks.net'
27
- s.homepage = 'https://github.com/stefankroes/ancestry'
28
- s.license = 'MIT'
29
-
30
- s.files = [
31
- 'ancestry.gemspec',
32
- 'init.rb',
33
- 'install.rb',
34
- 'lib/ancestry.rb',
35
- 'lib/ancestry/has_ancestry.rb',
36
- 'lib/ancestry/exceptions.rb',
37
- 'lib/ancestry/class_methods.rb',
38
- 'lib/ancestry/instance_methods.rb',
39
- 'lib/ancestry/materialized_path.rb',
40
- 'lib/ancestry/version.rb',
41
- 'MIT-LICENSE',
42
- 'README.md'
43
- ]
44
-
45
- s.required_ruby_version = '>= 2.0.0'
46
- s.add_runtime_dependency 'activerecord', '>= 4.2.0'
47
- s.add_development_dependency 'appraisal'
48
- s.add_development_dependency 'minitest'
49
- s.add_development_dependency 'rake', '~> 13.0'
50
- s.add_development_dependency 'yard'
51
- end
data/init.rb DELETED
@@ -1 +0,0 @@
1
- require 'ancestry'
data/install.rb DELETED
@@ -1 +0,0 @@
1
- puts "Thank you for installing Ancestry. You can visit http://github.com/stefankroes/ancestry to read the documentation."