ancestry 2.1.0 → 2.2.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 +5 -13
- data/MIT-LICENSE +1 -1
- data/README.rdoc +71 -19
- data/ancestry.gemspec +20 -11
- data/lib/ancestry/class_methods.rb +22 -13
- data/lib/ancestry/has_ancestry.rb +5 -4
- data/lib/ancestry/instance_methods.rb +40 -13
- metadata +76 -20
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZWRkMWYxOWZhOTJiNjU2MTE2ZTcyYWIwM2FlNmVmNjk0NjBkZGE2ZQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1b34c7c664ec5c1a9ac92379c65d9ea196658a3e
|
4
|
+
data.tar.gz: 2d9ff6493829ef26b6b8f3591404f7567139c717
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OTg2MzVjY2Q3MWEyNTEzZDUzNjc4OTA5NWVhNTFiNWJjYjFiMTQxNjhkYzM5
|
11
|
-
ODNlY2Y0MmIwZDc2ODQ4YTRiNmYxMWMwOTJiNzE0NDZmMDlhZGQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
N2E1ZjAwY2M1YjkzZTBlNWRkNDQ0ZTVlMDM3OTg3YmE0ZDgwMzNlNTdjOTFh
|
14
|
-
Y2NkYWY0NGUwNDFjZWI3OTZkMTAwMTBmNDI4OWZlOGQyMDRiZmQxOTgyOWFi
|
15
|
-
ZGFmYzk1YTExNjFhYTczNzIxMGE2NGVlZTA4ZGMwYWViMjU3NGE=
|
6
|
+
metadata.gz: d4b6408a4e4582b8cb654e4d38560f1f7b0b743b55023ff6668449a75847874036975faf53c74c18e75fbc59c6eb6d8d1c3bd7d22b28ce97595bcd5d56bd1f49
|
7
|
+
data.tar.gz: b06389bb0d03045bd0f9f82ab2dac3db63c8ca2996c87bcc4f46bb9b71d876090bc136b928cd5ac9d2c3c6b62ed48cd0ca2175e5c5e9a0f6c2e169a6ef24e005
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
{<img src="https://travis-ci.org/stefankroes/ancestry.
|
2
|
-
{<img src="https://coveralls.io/repos/stefankroes/ancestry/badge.
|
1
|
+
{<img src="https://travis-ci.org/stefankroes/ancestry.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/stefankroes/ancestry]
|
2
|
+
{<img src="https://coveralls.io/repos/stefankroes/ancestry/badge.svg" alt="Coverage Status" />}[https://coveralls.io/r/stefankroes/ancestry]
|
3
|
+
{<img src="https://badges.gitter.im/Join Chat.svg" alt="Gitter" />}[https://gitter.im/stefankroes/ancestry?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
|
4
|
+
{<img src="https://hakiri.io/github/stefankroes/ancestry/master.svg" alt="Security" />}[https://hakiri.io/github/stefankroes/ancestry/master]
|
3
5
|
|
4
6
|
= Ancestry
|
5
7
|
|
@@ -9,20 +11,51 @@ Ancestry is a gem/plugin that allows the records of a Ruby on Rails ActiveRecord
|
|
9
11
|
|
10
12
|
To apply Ancestry to any ActiveRecord model, follow these simple steps:
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
14
|
+
== Install
|
15
|
+
=== Rails 2
|
16
|
+
- See 1-3-stable branch
|
17
|
+
=== Rails 3 and 4
|
18
|
+
- Add to Gemfile:
|
19
|
+
# Gemfile
|
20
|
+
|
21
|
+
gem 'ancestry'
|
22
|
+
- Install required gems:
|
23
|
+
$ bundle install
|
24
|
+
|
25
|
+
== Add ancestry column to your table
|
26
|
+
- Create migration:
|
27
|
+
$ rails g migration add_ancestry_to_[table] ancestry:string
|
28
|
+
- Add index to migration:
|
29
|
+
# db/migrate/[date]_add_ancestry_to_[table].rb
|
30
|
+
|
31
|
+
class AddAncestryTo[Table] < ActiveRecord::Migration
|
32
|
+
# Rails 4 Syntax
|
33
|
+
def change
|
34
|
+
add_column [table], :ancestry, :string
|
35
|
+
add_index [table], :ancestry
|
36
|
+
end
|
37
|
+
|
38
|
+
# Rails 3 Syntax
|
39
|
+
def up
|
40
|
+
add_column [table], :ancestry, :string
|
41
|
+
add_index [table], :ancestry
|
42
|
+
end
|
43
|
+
|
44
|
+
def down
|
45
|
+
remove_column [table], :ancestry
|
46
|
+
remove_index [table], :ancestry
|
47
|
+
end
|
48
|
+
|
49
|
+
- Migrate your database:
|
50
|
+
$ rake db:migrate
|
51
|
+
|
52
|
+
== Add ancestry to your model
|
53
|
+
- Add to app/models/[model].rb:
|
54
|
+
# app/models/[model.rb]
|
55
|
+
|
56
|
+
class [Model] < ActiveRecord::Base
|
57
|
+
has_ancestry
|
58
|
+
end
|
26
59
|
|
27
60
|
Your model is now a tree!
|
28
61
|
|
@@ -57,7 +90,7 @@ To navigate an Ancestry model, use the following methods on any instance / recor
|
|
57
90
|
child_ids Returns a list of child ids
|
58
91
|
has_children? Returns true if the record has any children, false otherwise
|
59
92
|
is_childless? Returns true is the record has no children, false otherwise
|
60
|
-
siblings Scopes the model on siblings of the record, the record itself is included
|
93
|
+
siblings Scopes the model on siblings of the record, the record itself is included*
|
61
94
|
sibling_ids Returns a list of sibling ids
|
62
95
|
has_siblings? Returns true if the record's parent has more than one child
|
63
96
|
is_only_child? Returns true if the record is the only child of its parent
|
@@ -67,6 +100,8 @@ To navigate an Ancestry model, use the following methods on any instance / recor
|
|
67
100
|
subtree_ids Returns a list of all ids in the record's subtree
|
68
101
|
depth Return the depth of the node, root nodes are at depth 0
|
69
102
|
|
103
|
+
* If the record is a root, other root records are considered siblings
|
104
|
+
|
70
105
|
= Options for has_ancestry
|
71
106
|
|
72
107
|
The has_ancestry methods supports the following options:
|
@@ -174,6 +209,23 @@ To get the arranged nodes as a nested array of hashes for serialization:
|
|
174
209
|
}
|
175
210
|
]
|
176
211
|
|
212
|
+
You can also supply your own serialization logic using blocks:
|
213
|
+
|
214
|
+
For example, using Active Model Serializers:
|
215
|
+
|
216
|
+
TreeNode.arrange_serializable do |parent, children|
|
217
|
+
MySerializer.new(parent, children: children)
|
218
|
+
end
|
219
|
+
|
220
|
+
Or plain hashes:
|
221
|
+
|
222
|
+
TreeNode.arrange_serializable do |parent, children|
|
223
|
+
{
|
224
|
+
my_id: parent.id
|
225
|
+
my_children: children
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
177
229
|
The result of arrange_serializable can easily be serialized to json with 'to_json', or some other format:
|
178
230
|
|
179
231
|
TreeNode.arrange_serializable.to_json
|
@@ -269,10 +321,10 @@ In the example above, the ancestry column is created as a string. This puts a li
|
|
269
321
|
|
270
322
|
The materialised path pattern requires Ancestry to use a 'like' condition in order to fetch descendants. This should not be particularly slow however since the the condition never starts with a wildcard which allows the DBMS to use the column index. If you have any data on performance with a large number of records, please drop me line.
|
271
323
|
|
272
|
-
= Contributing and
|
324
|
+
= Contributing and license
|
273
325
|
|
274
326
|
I will try to keep Ancestry up to date with changing versions of Rails and Ruby and also with any bug reports I might receive. I will implement new features on request as I see fit and have time.
|
275
327
|
|
276
328
|
Question? Bug report? Faulty/incomplete documentation? Feature request? Please post an issue on 'http://github.com/stefankroes/ancestry/issues'. Make sure you have read the documentation and you have included tests and documentation with any pull request.
|
277
329
|
|
278
|
-
Copyright (c)
|
330
|
+
Copyright (c) 2016 Stefan Kroes, released under the MIT license
|
data/ancestry.gemspec
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
require 'ancestry/version'
|
4
|
+
|
1
5
|
Gem::Specification.new do |s|
|
2
6
|
s.name = 'ancestry'
|
3
7
|
s.summary = 'Organize ActiveRecord model into a tree structure'
|
@@ -11,7 +15,7 @@ Gem::Specification.new do |s|
|
|
11
15
|
orphaned records.
|
12
16
|
EOF
|
13
17
|
|
14
|
-
s.version =
|
18
|
+
s.version = Ancestry::VERSION
|
15
19
|
|
16
20
|
s.author = 'Stefan Kroes'
|
17
21
|
s.email = 's.a.kroes@gmail.com'
|
@@ -19,17 +23,22 @@ EOF
|
|
19
23
|
s.license = 'MIT'
|
20
24
|
|
21
25
|
s.files = [
|
22
|
-
'ancestry.gemspec',
|
23
|
-
'init.rb',
|
24
|
-
'install.rb',
|
25
|
-
'lib/ancestry.rb',
|
26
|
-
'lib/ancestry/has_ancestry.rb',
|
27
|
-
'lib/ancestry/exceptions.rb',
|
28
|
-
'lib/ancestry/class_methods.rb',
|
29
|
-
'lib/ancestry/instance_methods.rb',
|
30
|
-
'MIT-LICENSE',
|
26
|
+
'ancestry.gemspec',
|
27
|
+
'init.rb',
|
28
|
+
'install.rb',
|
29
|
+
'lib/ancestry.rb',
|
30
|
+
'lib/ancestry/has_ancestry.rb',
|
31
|
+
'lib/ancestry/exceptions.rb',
|
32
|
+
'lib/ancestry/class_methods.rb',
|
33
|
+
'lib/ancestry/instance_methods.rb',
|
34
|
+
'MIT-LICENSE',
|
31
35
|
'README.rdoc'
|
32
36
|
]
|
33
37
|
|
34
|
-
s.
|
38
|
+
s.required_ruby_version = '>= 1.8.7'
|
39
|
+
s.add_runtime_dependency 'activerecord', '>= 3.0.0'
|
40
|
+
s.add_development_dependency 'rake', '~> 10.0'
|
41
|
+
s.add_development_dependency 'test-unit'
|
42
|
+
s.add_development_dependency 'minitest'
|
43
|
+
s.add_development_dependency 'sqlite3'
|
35
44
|
end
|
@@ -42,25 +42,34 @@ module Ancestry
|
|
42
42
|
# Arrange array of nodes into a nested hash of the form
|
43
43
|
# {node => children}, where children = {} if the node has no children
|
44
44
|
def arrange_nodes(nodes)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
45
|
+
arranged = ActiveSupport::OrderedHash.new
|
46
|
+
min_depth = Float::INFINITY
|
47
|
+
index = Hash.new { |h, k| h[k] = ActiveSupport::OrderedHash.new }
|
48
|
+
|
49
|
+
nodes.each do |node|
|
50
|
+
children = index[node.id]
|
51
|
+
index[node.parent_id][node] = children
|
52
|
+
|
53
|
+
depth = node.depth
|
54
|
+
if depth < min_depth
|
55
|
+
min_depth = depth
|
56
|
+
arranged.clear
|
57
|
+
end
|
58
|
+
arranged[node] = children if depth == min_depth
|
56
59
|
end
|
60
|
+
|
61
|
+
arranged
|
57
62
|
end
|
58
63
|
|
59
64
|
# Arrangement to nested array
|
60
|
-
def arrange_serializable options={}, nodes=nil
|
65
|
+
def arrange_serializable options={}, nodes=nil, &block
|
61
66
|
nodes = arrange(options) if nodes.nil?
|
62
67
|
nodes.map do |parent, children|
|
63
|
-
|
68
|
+
if block_given?
|
69
|
+
yield parent, arrange_serializable(options, children, &block)
|
70
|
+
else
|
71
|
+
parent.serializable_hash.merge 'children' => arrange_serializable(options, children)
|
72
|
+
end
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
@@ -43,8 +43,9 @@ class << ActiveRecord::Base
|
|
43
43
|
scope :descendants_of, lambda { |object| where(to_node(object).descendant_conditions) }
|
44
44
|
scope :subtree_of, lambda { |object| where(to_node(object).subtree_conditions) }
|
45
45
|
scope :siblings_of, lambda { |object| where(to_node(object).sibling_conditions) }
|
46
|
-
scope :ordered_by_ancestry, lambda { reorder("(
|
47
|
-
scope :ordered_by_ancestry_and, lambda { |order| reorder("(
|
46
|
+
scope :ordered_by_ancestry, lambda { reorder("(CASE WHEN #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)} IS NULL THEN 0 ELSE 1 END), #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}") }
|
47
|
+
scope :ordered_by_ancestry_and, lambda { |order| reorder("(CASE WHEN #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)} IS NULL THEN 0 ELSE 1 END), #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, #{order}") }
|
48
|
+
scope :path_of, lambda { |object| to_node(object).path }
|
48
49
|
|
49
50
|
# Update descendants with new ancestry before save
|
50
51
|
before_save :update_descendants_with_new_ancestry
|
@@ -74,9 +75,9 @@ class << ActiveRecord::Base
|
|
74
75
|
}
|
75
76
|
end
|
76
77
|
|
77
|
-
after_save :touch_ancestors_callback
|
78
78
|
after_touch :touch_ancestors_callback
|
79
79
|
after_destroy :touch_ancestors_callback
|
80
|
+
after_save :touch_ancestors_callback, if: :changed?
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
@@ -86,4 +87,4 @@ ActiveSupport.on_load :active_record do
|
|
86
87
|
alias_method :acts_as_tree, :has_ancestry
|
87
88
|
end
|
88
89
|
end
|
89
|
-
end
|
90
|
+
end
|
@@ -53,6 +53,8 @@ module Ancestry
|
|
53
53
|
descendants.each do |descendant|
|
54
54
|
descendant.without_ancestry_callbacks do
|
55
55
|
new_ancestry = descendant.ancestor_ids.delete_if { |x| x == self.id }.join("/")
|
56
|
+
# check for empty string if it's then set to nil
|
57
|
+
new_ancestry = nil if new_ancestry.empty?
|
56
58
|
descendant.update_attribute descendant.class.ancestry_column, new_ancestry || nil
|
57
59
|
end
|
58
60
|
end
|
@@ -92,7 +94,7 @@ module Ancestry
|
|
92
94
|
end
|
93
95
|
|
94
96
|
# Ancestors
|
95
|
-
|
97
|
+
|
96
98
|
def ancestry_changed?
|
97
99
|
changed.include?(self.ancestry_base_class.ancestry_column.to_s)
|
98
100
|
end
|
@@ -143,8 +145,12 @@ module Ancestry
|
|
143
145
|
write_attribute self.ancestry_base_class.depth_cache_column, depth
|
144
146
|
end
|
145
147
|
|
148
|
+
def ancestor_of?(node)
|
149
|
+
node.ancestor_ids.include?(self.id)
|
150
|
+
end
|
151
|
+
|
146
152
|
# Parent
|
147
|
-
|
153
|
+
|
148
154
|
def parent= parent
|
149
155
|
write_attribute(self.ancestry_base_class.ancestry_column, if parent.nil? then nil else parent.child_ancestry end)
|
150
156
|
end
|
@@ -165,8 +171,12 @@ module Ancestry
|
|
165
171
|
parent_id.present?
|
166
172
|
end
|
167
173
|
|
174
|
+
def parent_of?(node)
|
175
|
+
self.id == node.parent_id
|
176
|
+
end
|
177
|
+
|
168
178
|
# Root
|
169
|
-
|
179
|
+
|
170
180
|
def root_id
|
171
181
|
if ancestor_ids.empty? then id else ancestor_ids.first end
|
172
182
|
end
|
@@ -180,8 +190,12 @@ module Ancestry
|
|
180
190
|
end
|
181
191
|
alias :root? :is_root?
|
182
192
|
|
193
|
+
def root_of?(node)
|
194
|
+
self.id == node.root_id
|
195
|
+
end
|
196
|
+
|
183
197
|
# Children
|
184
|
-
|
198
|
+
|
185
199
|
def child_conditions
|
186
200
|
t = get_arel_table
|
187
201
|
t[get_ancestry_column].eq(child_ancestry)
|
@@ -205,8 +219,12 @@ module Ancestry
|
|
205
219
|
end
|
206
220
|
alias_method :childless?, :is_childless?
|
207
221
|
|
222
|
+
def child_of?(node)
|
223
|
+
self.parent_id == node.id
|
224
|
+
end
|
225
|
+
|
208
226
|
# Siblings
|
209
|
-
|
227
|
+
|
210
228
|
def sibling_conditions
|
211
229
|
t = get_arel_table
|
212
230
|
t[get_ancestry_column].eq(read_attribute(self.ancestry_base_class.ancestry_column))
|
@@ -230,8 +248,12 @@ module Ancestry
|
|
230
248
|
end
|
231
249
|
alias_method :only_child?, :is_only_child?
|
232
250
|
|
251
|
+
def sibling_of?(node)
|
252
|
+
self.ancestry == node.ancestry
|
253
|
+
end
|
254
|
+
|
233
255
|
# Descendants
|
234
|
-
|
256
|
+
|
235
257
|
def descendant_conditions
|
236
258
|
t = get_arel_table
|
237
259
|
t[get_ancestry_column].matches("#{child_ancestry}/%").or(t[get_ancestry_column].eq(child_ancestry))
|
@@ -245,11 +267,15 @@ module Ancestry
|
|
245
267
|
descendants(depth_options).select(self.ancestry_base_class.primary_key).collect(&self.ancestry_base_class.primary_key.to_sym)
|
246
268
|
end
|
247
269
|
|
270
|
+
def descendant_of?(node)
|
271
|
+
ancestor_ids.include?(node.id)
|
272
|
+
end
|
273
|
+
|
248
274
|
# Subtree
|
249
|
-
|
275
|
+
|
250
276
|
def subtree_conditions
|
251
277
|
t = get_arel_table
|
252
|
-
t[get_primary_key_column].eq(self.id)
|
278
|
+
descendant_conditions.or(t[get_primary_key_column].eq(self.id))
|
253
279
|
end
|
254
280
|
|
255
281
|
def subtree depth_options = {}
|
@@ -261,7 +287,7 @@ module Ancestry
|
|
261
287
|
end
|
262
288
|
|
263
289
|
# Callback disabling
|
264
|
-
|
290
|
+
|
265
291
|
def without_ancestry_callbacks
|
266
292
|
@disable_ancestry_callbacks = true
|
267
293
|
yield
|
@@ -269,13 +295,13 @@ module Ancestry
|
|
269
295
|
end
|
270
296
|
|
271
297
|
def ancestry_callbacks_disabled?
|
272
|
-
|
298
|
+
defined?(@disable_ancestry_callbacks) && @disable_ancestry_callbacks
|
273
299
|
end
|
274
300
|
|
275
301
|
private
|
276
302
|
|
277
303
|
def cast_primary_key(key)
|
278
|
-
if [:string, :uuid].include? primary_key_type
|
304
|
+
if [:string, :uuid, :text].include? primary_key_type
|
279
305
|
key
|
280
306
|
else
|
281
307
|
key.to_i
|
@@ -292,9 +318,10 @@ module Ancestry
|
|
292
318
|
end
|
293
319
|
end
|
294
320
|
|
295
|
-
# Validates the ancestry, but can also be applied if validation is bypassed to determine if
|
321
|
+
# Validates the ancestry, but can also be applied if validation is bypassed to determine if children should be affected
|
296
322
|
def sane_ancestry?
|
297
|
-
|
323
|
+
ancestry_value = read_attribute(self.ancestry_base_class.ancestry_column)
|
324
|
+
ancestry_value.nil? || (ancestry_value.to_s =~ Ancestry::ANCESTRY_PATTERN && !ancestor_ids.include?(self.id))
|
298
325
|
end
|
299
326
|
|
300
327
|
def unscoped_find id
|
metadata
CHANGED
@@ -1,51 +1,108 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ancestry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Kroes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 3.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.0.0
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: test-unit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |2
|
84
|
+
Ancestry allows the records of a ActiveRecord model to be organized in a tree
|
85
|
+
structure, using a single, intuitively formatted database column. It exposes
|
86
|
+
all the standard tree structure relations (ancestors, parent, root, children,
|
87
|
+
siblings, descendants) and all of them can be fetched in a single sql query.
|
88
|
+
Additional features are named_scopes, integrity checking, integrity restoration,
|
89
|
+
arrangement of (sub)tree into hashes and different strategies for dealing with
|
90
|
+
orphaned records.
|
34
91
|
email: s.a.kroes@gmail.com
|
35
92
|
executables: []
|
36
93
|
extensions: []
|
37
94
|
extra_rdoc_files: []
|
38
95
|
files:
|
96
|
+
- MIT-LICENSE
|
97
|
+
- README.rdoc
|
39
98
|
- ancestry.gemspec
|
40
99
|
- init.rb
|
41
100
|
- install.rb
|
42
101
|
- lib/ancestry.rb
|
43
|
-
- lib/ancestry/has_ancestry.rb
|
44
|
-
- lib/ancestry/exceptions.rb
|
45
102
|
- lib/ancestry/class_methods.rb
|
103
|
+
- lib/ancestry/exceptions.rb
|
104
|
+
- lib/ancestry/has_ancestry.rb
|
46
105
|
- lib/ancestry/instance_methods.rb
|
47
|
-
- MIT-LICENSE
|
48
|
-
- README.rdoc
|
49
106
|
homepage: http://github.com/stefankroes/ancestry
|
50
107
|
licenses:
|
51
108
|
- MIT
|
@@ -56,19 +113,18 @@ require_paths:
|
|
56
113
|
- lib
|
57
114
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
115
|
requirements:
|
59
|
-
- -
|
116
|
+
- - ">="
|
60
117
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
118
|
+
version: 1.8.7
|
62
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
120
|
requirements:
|
64
|
-
- -
|
121
|
+
- - ">="
|
65
122
|
- !ruby/object:Gem::Version
|
66
123
|
version: '0'
|
67
124
|
requirements: []
|
68
125
|
rubyforge_project:
|
69
|
-
rubygems_version: 2.1
|
126
|
+
rubygems_version: 2.5.1
|
70
127
|
signing_key:
|
71
128
|
specification_version: 4
|
72
129
|
summary: Organize ActiveRecord model into a tree structure
|
73
130
|
test_files: []
|
74
|
-
has_rdoc:
|