awesome_nested_set 2.1.6 → 3.0.0.rc.6
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 +7 -0
- data/CHANGELOG +5 -0
- data/README.md +230 -0
- data/lib/awesome_nested_set/awesome_nested_set.rb +66 -692
- data/lib/awesome_nested_set/columns.rb +84 -0
- data/lib/awesome_nested_set/helper.rb +2 -47
- data/lib/awesome_nested_set/iterator.rb +29 -0
- data/lib/awesome_nested_set/model/movable.rb +146 -0
- data/lib/awesome_nested_set/model/prunable.rb +70 -0
- data/lib/awesome_nested_set/model/rebuildable.rb +42 -0
- data/lib/awesome_nested_set/model/relatable.rb +121 -0
- data/lib/awesome_nested_set/model/transactable.rb +27 -0
- data/lib/awesome_nested_set/model/validatable.rb +70 -0
- data/lib/awesome_nested_set/model.rb +248 -0
- data/lib/awesome_nested_set/move.rb +131 -0
- data/lib/awesome_nested_set/set_validator.rb +63 -0
- data/lib/awesome_nested_set/tree.rb +63 -0
- data/lib/awesome_nested_set/version.rb +1 -1
- data/lib/awesome_nested_set.rb +1 -1
- metadata +60 -37
- data/README.rdoc +0 -153
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: ebe27a6d3e69be31c797a0d3c663f3677d68b302
|
|
4
|
+
data.tar.gz: e9f0144d3430f05b4b5af855f8f58a9cd3cd174d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: bd9ddf03673994b9ff5cdb2a7c855f507aab5c69c1bf8eb21a367d1601634709932482d690e17baf34e5713b1f08cfabf47e50d4a9b1b76e400d9d4ed85d1971
|
|
7
|
+
data.tar.gz: be3ee9c75fbc3179ed6c75776edb9b65fde98ad2a7b415023d922748f5bd4b288785485e23109bf69bac45b21484f75ea9127999a942fe04ef59fc61e9e02a01
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
* Support Rails 4.1 [Micah Geisel]
|
|
2
|
+
* Support dependent: restrict_with_error [Tiago Moraes]
|
|
3
|
+
* Added information to the README regarding indexes to be added for performance [bdarfler]
|
|
4
|
+
* Modified associate_parents to add child objects to the parent#children collection [Tiago Moraes]
|
|
5
|
+
|
|
1
6
|
2.1.6
|
|
2
7
|
* Fixed rebuild! when there is a default_scope with order [Adrian Serafin]
|
|
3
8
|
* Testing with stable bundler, ruby 2.0, MySQL and PostgreSQL [Philip Arndt]
|
data/README.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# AwesomeNestedSet
|
|
2
|
+
|
|
3
|
+
[![Build Status][Build Status Image]][Build Status]
|
|
4
|
+
[Build Status Image]: https://travis-ci.org/collectiveidea/awesome_nested_set.png?branch=master
|
|
5
|
+
[Build Status]: https://travis-ci.org/collectiveidea/awesome_nested_set
|
|
6
|
+
|
|
7
|
+
Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models.
|
|
8
|
+
It is a replacement for acts_as_nested_set and BetterNestedSet, but more awesome.
|
|
9
|
+
|
|
10
|
+
Version 2 supports Rails 3 and Rails 4. Gem versions prior to 2.0 support Rails 2.
|
|
11
|
+
|
|
12
|
+
## What makes this so awesome?
|
|
13
|
+
|
|
14
|
+
This is a new implementation of nested set based off of BetterNestedSet that fixes some bugs, removes tons of duplication, adds a few useful methods, and adds STI support.
|
|
15
|
+
|
|
16
|
+
[](https://codeclimate.com/github/collectiveidea/awesome_nested_set)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Add to your Gemfile:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
gem 'awesome_nested_set'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
To make use of `awesome_nested_set`, your model needs to have 3 fields:
|
|
29
|
+
`lft`, `rgt`, and `parent_id`. The names of these fields are configurable.
|
|
30
|
+
You can also have an optional field, `depth`:
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
class CreateCategories < ActiveRecord::Migration
|
|
34
|
+
def self.up
|
|
35
|
+
create_table :categories do |t|
|
|
36
|
+
t.string :name
|
|
37
|
+
t.integer :parent_id
|
|
38
|
+
t.integer :lft
|
|
39
|
+
t.integer :rgt
|
|
40
|
+
t.integer :depth # this is optional.
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.down
|
|
45
|
+
drop_table :categories
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Enable the nested set functionality by declaring `acts_as_nested_set` on your model
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
class Category < ActiveRecord::Base
|
|
54
|
+
acts_as_nested_set
|
|
55
|
+
end
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Run `rake rdoc` to generate the API docs and see [CollectiveIdea::Acts::NestedSet](lib/awesome_nested_set/awesome_nested_set.rb) for more information.
|
|
59
|
+
|
|
60
|
+
## Options
|
|
61
|
+
|
|
62
|
+
You can pass various options to `acts_as_nested_set` macro. Configuration options are:
|
|
63
|
+
|
|
64
|
+
* `parent_column`: specifies the column name to use for keeping the position integer (default: parent_id)
|
|
65
|
+
* `left_column`: column name for left boundry data (default: lft)
|
|
66
|
+
* `right_column`: column name for right boundry data (default: rgt)
|
|
67
|
+
* `depth_column`: column name for the depth data default (default: depth)
|
|
68
|
+
* `scope`: restricts what is to be considered a list. Given a symbol, it'll attach “_id” (if it hasn't been already) and use that as the foreign key restriction. You can also pass an array to scope by multiple attributes. Example: `acts_as_nested_set :scope => [:notable_id, :notable_type]`
|
|
69
|
+
* `dependent`: behavior for cascading destroy. If set to :destroy, all the child objects are destroyed alongside this object by calling their destroy method. If set to :delete_all (default), all the child objects are deleted without calling their destroy method.
|
|
70
|
+
* `counter_cache`: adds a counter cache for the number of children. defaults to false. Example: `acts_as_nested_set :counter_cache => :children_count`
|
|
71
|
+
* `order_column`: on which column to do sorting, by default it is the left_column_name. Example: `acts_as_nested_set :order_column => :position`
|
|
72
|
+
|
|
73
|
+
See [CollectiveIdea::Acts::NestedSet::Model::ClassMethods](/lib/awesome_nested_set/model.rb#L26) for a list of class methods and [CollectiveIdea::Acts::NestedSet::Model](lib/awesome_nested_set/model.rb#L13) for a list of instance methods added to acts_as_nested_set models
|
|
74
|
+
|
|
75
|
+
## Indexes
|
|
76
|
+
|
|
77
|
+
It is highly recommended that you add an index to the `rgt` column on your models. Every insertion requires finding the next `rgt` value to use and this can be slow for large tables without an index. It is probably best to index the other fields as well (`parent_id`, `lft`, `depth`).
|
|
78
|
+
|
|
79
|
+
## Callbacks
|
|
80
|
+
|
|
81
|
+
There are three callbacks called when moving a node:
|
|
82
|
+
`before_move`, `after_move` and `around_move`.
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
class Category < ActiveRecord::Base
|
|
86
|
+
acts_as_nested_set
|
|
87
|
+
|
|
88
|
+
after_move :rebuild_slug
|
|
89
|
+
around_move :da_fancy_things_around
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def rebuild_slug
|
|
94
|
+
# do whatever
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def da_fancy_things_around
|
|
98
|
+
# do something...
|
|
99
|
+
yield # actually moves
|
|
100
|
+
# do something else...
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Beside this there are also hooks to act on the newly added or removed children.
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
class Category < ActiveRecord::Base
|
|
109
|
+
acts_as_nested_set :before_add => :do_before_add_stuff,
|
|
110
|
+
:after_add => :do_after_add_stuff,
|
|
111
|
+
:before_remove => :do_before_remove_stuff,
|
|
112
|
+
:after_remove => :do_after_remove_stuff
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def do_before_add_stuff(child_node)
|
|
117
|
+
# do whatever with the child
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def do_after_add_stuff(child_node)
|
|
121
|
+
# do whatever with the child
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def do_before_remove_stuff(child_node)
|
|
125
|
+
# do whatever with the child
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def do_after_remove_stuff(child_node)
|
|
129
|
+
# do whatever with the child
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Protecting attributes from mass assignment
|
|
135
|
+
|
|
136
|
+
It's generally best to "whitelist" the attributes that can be used in mass assignment:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
class Category < ActiveRecord::Base
|
|
140
|
+
acts_as_nested_set
|
|
141
|
+
attr_accessible :name, :parent_id
|
|
142
|
+
end
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
If for some reason that is not possible, you will probably want to protect the `lft` and `rgt` attributes:
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
class Category < ActiveRecord::Base
|
|
149
|
+
acts_as_nested_set
|
|
150
|
+
attr_protected :lft, :rgt
|
|
151
|
+
end
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
## Add to your existing project
|
|
156
|
+
|
|
157
|
+
To make use of `awesome_nested_set`, your model needs to have 3 fields:
|
|
158
|
+
`lft`, `rgt`, and `parent_id`. The names of these fields are configurable.
|
|
159
|
+
You can also have an optional field, `depth`.
|
|
160
|
+
|
|
161
|
+
Create a migration to add fields:
|
|
162
|
+
|
|
163
|
+
```ruby
|
|
164
|
+
class AddNestedToCategories < ActiveRecord::Migration
|
|
165
|
+
|
|
166
|
+
def self.up
|
|
167
|
+
add_column :categories, :parent_id, :integer # Comment this line if your project already has this column
|
|
168
|
+
# Category.where(parent_id: 0).update_all(parent_id: nil) # Uncomment this line if your project already has :parent_id
|
|
169
|
+
add_column :categories, :lft , :integer
|
|
170
|
+
add_column :categories, :rgt , :integer
|
|
171
|
+
add_column :categories, :depth , :integer # this is optional.
|
|
172
|
+
|
|
173
|
+
# This is necessary to update :lft and :rgt columns
|
|
174
|
+
Category.rebuild!
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def self.down
|
|
178
|
+
remove_column :categories, :parent_id
|
|
179
|
+
remove_column :categories, :lft
|
|
180
|
+
remove_column :categories, :rgt
|
|
181
|
+
remove_column :categories, :depth # this is optional.
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Enable the nested set functionality by declaring `acts_as_nested_set` on your model
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
class Category < ActiveRecord::Base
|
|
191
|
+
acts_as_nested_set
|
|
192
|
+
end
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Your project is now ready to run with the `awesome_nested_set` gem!
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
## Conversion from other trees
|
|
199
|
+
|
|
200
|
+
Coming from acts_as_tree or another system where you only have a parent_id? No problem. Simply add the lft & rgt fields as above, and then run:
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
Category.rebuild!
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Your tree will be converted to a valid nested set. Awesome!
|
|
207
|
+
|
|
208
|
+
## View Helper
|
|
209
|
+
|
|
210
|
+
The view helper is called #nested_set_options.
|
|
211
|
+
|
|
212
|
+
Example usage:
|
|
213
|
+
|
|
214
|
+
```erb
|
|
215
|
+
<%= f.select :parent_id, nested_set_options(Category, @category) {|i| "#{'-' * i.level} #{i.name}" } %>
|
|
216
|
+
|
|
217
|
+
<%= select_tag 'parent_id', options_for_select(nested_set_options(Category) {|i| "#{'-' * i.level} #{i.name}" } ) %>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
See [CollectiveIdea::Acts::NestedSet::Helper](lib/awesome_nested_set/helper.rb) for more information about the helpers.
|
|
221
|
+
|
|
222
|
+
## References
|
|
223
|
+
|
|
224
|
+
You can learn more about nested sets at: http://threebit.net/tutorials/nestedset/tutorial1.html
|
|
225
|
+
|
|
226
|
+
## How to contribute
|
|
227
|
+
|
|
228
|
+
Please see the ['Contributing' document](CONTRIBUTING.md).
|
|
229
|
+
|
|
230
|
+
Copyright © 2008 - 2013 Collective Idea, released under the MIT license
|