ancestry 3.0.1 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +53 -53
- data/ancestry.gemspec +2 -0
- data/lib/ancestry.rb +1 -0
- data/lib/ancestry/has_ancestry.rb +3 -3
- data/lib/ancestry/instance_methods.rb +1 -7
- data/lib/ancestry/version.rb +3 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8088b41fa07084ef6a761d52c2d33b051c24eae3
|
4
|
+
data.tar.gz: ed5f0c0678e1d238adb4b68ed6d6239204c397a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c97d7541dbba13b6a768edab18a21c2916fbb9ea0f61674f4831a0e56f0eed83bf3b1a18bd743b1f2e0eb26b6b78ca21c69271052e3fb1042d8cf194c74802ca
|
7
|
+
data.tar.gz: 7274762db4aee75b633c14fb158b68da2e4e525c4c5e5557c9c164aa6a2dc8d68c7cdc96f443112a327b0a21b76a3acc57cb09c7653ec5b24a4a839266b7313b
|
data/README.md
CHANGED
@@ -34,19 +34,7 @@ $ bundle install
|
|
34
34
|
## Add ancestry column to your table
|
35
35
|
* Create migration:
|
36
36
|
```bash
|
37
|
-
$ rails g migration add_ancestry_to_[table] ancestry:string
|
38
|
-
```
|
39
|
-
|
40
|
-
* Add index to migration:
|
41
|
-
```ruby
|
42
|
-
# db/migrate/[date]_add_ancestry_to_[table].rb
|
43
|
-
|
44
|
-
class AddAncestryTo[Table] < ActiveRecord::Migration
|
45
|
-
def change
|
46
|
-
add_column [table], :ancestry, :string
|
47
|
-
add_index [table], :ancestry
|
48
|
-
end
|
49
|
-
end
|
37
|
+
$ rails g migration add_ancestry_to_[table] ancestry:string:index
|
50
38
|
```
|
51
39
|
|
52
40
|
* Migrate your database:
|
@@ -95,39 +83,50 @@ node.children.create :name => 'Stinky'
|
|
95
83
|
|
96
84
|
# Navigating your tree
|
97
85
|
|
98
|
-
To navigate an Ancestry model, use the following
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
86
|
+
To navigate an Ancestry model, use the following instance methods:
|
87
|
+
|
88
|
+
| method |return value|
|
89
|
+
|-------------------|------------|
|
90
|
+
|`parent` |parent of the record, nil for a root node|
|
91
|
+
|`parent_id` |parent id of the record, nil for a root node|
|
92
|
+
|`root` |root of the record's tree, self for a root node|
|
93
|
+
|`root_id` |root id of the record's tree, self for a root node|
|
94
|
+
|`root?` <br/> `is_root?` | true if the record is a root node, false otherwise|
|
95
|
+
|`ancestors` |ancestors of the record, starting with the root and ending with the parent|
|
96
|
+
|`ancestors?` |true if the record has ancestors (aka not a root node)|
|
97
|
+
|`ancestor_ids` |ancestor ids of the record|
|
98
|
+
|`path` |path of the record, starting with the root and ending with self|
|
99
|
+
|`path_ids` |a list the path ids, starting with the root id and ending with the node's own id|
|
100
|
+
|`children` |direct children of the record|
|
101
|
+
|`child_ids` |direct children's ids|
|
102
|
+
|`has_parent?` <br/> `ancestors?` |true if the record has a parent, false otherwise|
|
103
|
+
|`has_children?` <br/> `children?` |true if the record has any children, false otherwise|
|
104
|
+
|`is_childless?` <br/> `childless?` |true is the record has no children, false otherwise|
|
105
|
+
|`siblings` |siblings of the record, the record itself is included*|
|
106
|
+
|`sibling_ids` |sibling ids|
|
107
|
+
|`has_siblings?` <br/> `siblings?` |true if the record's parent has more than one child|
|
108
|
+
|`is_only_child?` <br/> `only_child?` |true if the record is the only child of its parent|
|
109
|
+
|`descendants` |direct and indirect children of the record|
|
110
|
+
|`descendant_ids` |direct and indirect children's ids of the record|
|
111
|
+
|`subtree` |the model on descendants and itself|
|
112
|
+
|`subtree_ids` |a list of all ids in the record's subtree|
|
113
|
+
|`depth` |the depth of the node, root nodes are at depth 0|
|
114
|
+
|
115
|
+
\* If the record is a root, other root records are considered siblings
|
116
|
+
\* Siblings returns the record itself
|
117
|
+
|
118
|
+
There are also instance methods to determine the relationship between 2 nodes:
|
119
|
+
|
120
|
+
|method |return value|
|
121
|
+
|-------------------|---------------|
|
122
|
+
|`parent_of?(node)` | node's parent is this record|
|
123
|
+
|`root_of?(node)` | node's root is this record|
|
124
|
+
|`ancestor_of?(node)`| node's ancestors include this record|
|
125
|
+
|`child_of?(node)` | node is record's parent|
|
127
126
|
|
128
127
|
# Options for `has_ancestry`
|
129
128
|
|
130
|
-
The has_ancestry
|
129
|
+
The has_ancestry method supports the following options:
|
131
130
|
|
132
131
|
:ancestry_column Pass in a symbol to store ancestry in a different column
|
133
132
|
:orphan_strategy Instruct Ancestry what to do with children of a node that is destroyed:
|
@@ -155,7 +154,7 @@ example:
|
|
155
154
|
|
156
155
|
```ruby
|
157
156
|
node.children.where(:name => 'Mary').exists?
|
158
|
-
node.subtree.order(:name).limit(10).each
|
157
|
+
node.subtree.order(:name).limit(10).each { ... }
|
159
158
|
node.descendants.count
|
160
159
|
```
|
161
160
|
|
@@ -215,7 +214,7 @@ instead.
|
|
215
214
|
|
216
215
|
Ancestry works fine with STI. Just create a STI inheritance hierarchy and
|
217
216
|
build an Ancestry tree from the different classes/models. All Ancestry
|
218
|
-
relations that
|
217
|
+
relations that were described above will return nodes of any model type. If
|
219
218
|
you do only want nodes of a specific subclass you'll have to add a condition
|
220
219
|
on type for that.
|
221
220
|
|
@@ -225,11 +224,12 @@ Ancestry can arrange an entire subtree into nested hashes for easy navigation
|
|
225
224
|
after retrieval from the database. TreeNode.arrange could for example return:
|
226
225
|
|
227
226
|
```ruby
|
228
|
-
{
|
229
|
-
|
230
|
-
|
231
|
-
=> {}
|
232
|
-
}
|
227
|
+
{
|
228
|
+
#<TreeNode id: 100018, name: "Stinky", ancestry: nil> => {
|
229
|
+
#<TreeNode id: 100019, name: "Crunchy", ancestry: "100018"> => {
|
230
|
+
#<TreeNode id: 100020, name: "Squeeky", ancestry: "100018/100019"> => {}
|
231
|
+
},
|
232
|
+
#<TreeNode id: 100021, name: "Squishy", ancestry: "100018"> => {}
|
233
233
|
}
|
234
234
|
}
|
235
235
|
```
|
@@ -277,7 +277,7 @@ Or plain hashes:
|
|
277
277
|
```ruby
|
278
278
|
TreeNode.arrange_serializable do |parent, children|
|
279
279
|
{
|
280
|
-
my_id: parent.id
|
280
|
+
my_id: parent.id,
|
281
281
|
my_children: children
|
282
282
|
}
|
283
283
|
end
|
@@ -312,7 +312,7 @@ the order of siblings depends on their order in the original array.
|
|
312
312
|
# Migrating from plugin that uses parent_id column
|
313
313
|
|
314
314
|
Most current tree plugins use a parent_id column (has_ancestry,
|
315
|
-
awesome_nested_set, better_nested_set, acts_as_nested_set). With ancestry
|
315
|
+
awesome_nested_set, better_nested_set, acts_as_nested_set). With ancestry it is
|
316
316
|
easy to migrate from any of these plugins, to do so, use the
|
317
317
|
build_ancestry_from_parent_ids! method on your ancestry model. These steps
|
318
318
|
provide a more detailed explanation:
|
@@ -418,7 +418,7 @@ remove the limitation entirely. Changing it to a text will however decrease
|
|
418
418
|
performance because an index cannot be put on the column in that case.
|
419
419
|
|
420
420
|
The materialised path pattern requires Ancestry to use a 'like' condition in
|
421
|
-
order to fetch descendants. The wild character (`%`) is on the
|
421
|
+
order to fetch descendants. The wild character (`%`) is on the right of the
|
422
422
|
query, so indexes should be used.
|
423
423
|
|
424
424
|
# Contributing and license
|
data/ancestry.gemspec
CHANGED
@@ -37,12 +37,14 @@ EOF
|
|
37
37
|
'lib/ancestry/class_methods.rb',
|
38
38
|
'lib/ancestry/instance_methods.rb',
|
39
39
|
'lib/ancestry/materialized_path.rb',
|
40
|
+
'lib/ancestry/version.rb',
|
40
41
|
'MIT-LICENSE',
|
41
42
|
'README.md'
|
42
43
|
]
|
43
44
|
|
44
45
|
s.required_ruby_version = '>= 1.8.7'
|
45
46
|
s.add_runtime_dependency 'activerecord', '>= 3.2.0'
|
47
|
+
s.add_development_dependency 'rdoc'
|
46
48
|
s.add_development_dependency 'yard'
|
47
49
|
s.add_development_dependency 'rake', '~> 10.0'
|
48
50
|
s.add_development_dependency 'test-unit'
|
data/lib/ancestry.rb
CHANGED
@@ -46,12 +46,12 @@ module Ancestry
|
|
46
46
|
scope :siblings_of, lambda { |object| where(sibling_conditions(object)) }
|
47
47
|
scope :ordered_by_ancestry, Proc.new { |order|
|
48
48
|
if %w(mysql mysql2 sqlite sqlite3 postgresql).include?(connection.adapter_name.downcase) && ActiveRecord::VERSION::MAJOR >= 5
|
49
|
-
reorder("coalesce(#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, '')", order)
|
49
|
+
reorder(Arel.sql("coalesce(#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, '')"), order)
|
50
50
|
else
|
51
|
-
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)
|
51
|
+
reorder(Arel.sql("(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)
|
52
52
|
end
|
53
53
|
}
|
54
|
-
scope :ordered_by_ancestry_and, Proc.new { |order|
|
54
|
+
scope :ordered_by_ancestry_and, Proc.new { |order| ordered_by_ancestry(order) }
|
55
55
|
scope :path_of, lambda { |object| to_node(object).path }
|
56
56
|
|
57
57
|
# Update descendants with new ancestry before save
|
@@ -114,13 +114,7 @@ module Ancestry
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def ancestor_ids_was
|
117
|
-
|
118
|
-
saved_changes.transform_values(&:first)
|
119
|
-
else
|
120
|
-
changed_attributes
|
121
|
-
end
|
122
|
-
|
123
|
-
parse_ancestry_column(relevant_attributes[self.ancestry_base_class.ancestry_column.to_s])
|
117
|
+
parse_ancestry_column(send("#{self.ancestry_base_class.ancestry_column}_was"))
|
124
118
|
end
|
125
119
|
|
126
120
|
def path_ids
|
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.0.
|
4
|
+
version: 3.0.2
|
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:
|
12
|
+
date: 2018-04-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -25,6 +25,20 @@ dependencies:
|
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: 3.2.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rdoc
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: yard
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,6 +133,7 @@ files:
|
|
119
133
|
- lib/ancestry/has_ancestry.rb
|
120
134
|
- lib/ancestry/instance_methods.rb
|
121
135
|
- lib/ancestry/materialized_path.rb
|
136
|
+
- lib/ancestry/version.rb
|
122
137
|
homepage: http://github.com/stefankroes/ancestry
|
123
138
|
licenses:
|
124
139
|
- MIT
|
@@ -143,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
158
|
version: '0'
|
144
159
|
requirements: []
|
145
160
|
rubyforge_project:
|
146
|
-
rubygems_version: 2.
|
161
|
+
rubygems_version: 2.6.13
|
147
162
|
signing_key:
|
148
163
|
specification_version: 4
|
149
164
|
summary: Organize ActiveRecord model into a tree structure
|