File: README.md

package info (click to toggle)
ruby-awesome-nested-set 3.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, jessie, jessie-kfreebsd, sid, stretch
  • size: 160 kB
  • ctags: 206
  • sloc: ruby: 948; makefile: 2
file content (228 lines) | stat: -rw-r--r-- 7,519 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# Awesome Nested Set

[![Build Status](https://travis-ci.org/collectiveidea/awesome_nested_set.png?branch=master)](https://travis-ci.org/collectiveidea/awesome_nested_set) [![Code Climate](https://codeclimate.com/github/collectiveidea/awesome_nested_set.png)](https://codeclimate.com/github/collectiveidea/awesome_nested_set) [![Dependency Status](https://gemnasium.com/collectiveidea/awesome_nested_set.svg)](https://gemnasium.com/collectiveidea/awesome_nested_set)


Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models.
It is a replacement for acts_as_nested_set and BetterNestedSet, but more awesome.

Version 3 supports Rails 4. Version 2 supports Rails 3. Gem versions prior to 2.0 support Rails 2.

## What makes this so awesome?

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.


## Installation

Add to your Gemfile:

```ruby
gem 'awesome_nested_set'
```

## Usage

To make use of `awesome_nested_set`, your model needs to have 3 fields:
`lft`, `rgt`, and `parent_id`. The names of these fields are configurable.
You can also have an optional field, `depth`:

```ruby
class CreateCategories < ActiveRecord::Migration
  def self.up
    create_table :categories do |t|
      t.string :name
      t.integer :parent_id
      t.integer :lft
      t.integer :rgt
      t.integer :depth # this is optional.
    end
  end

  def self.down
    drop_table :categories
  end
end
```

Enable the nested set functionality by declaring `acts_as_nested_set` on your model

```ruby
class Category < ActiveRecord::Base
  acts_as_nested_set
end
```

Run `rake rdoc` to generate the API docs and see [CollectiveIdea::Acts::NestedSet](lib/awesome_nested_set/awesome_nested_set.rb) for more information.

## Options

You can pass various options to `acts_as_nested_set` macro. Configuration options are:

* `parent_column`: specifies the column name to use for keeping the position integer (default: parent_id)
* `left_column`: column name for left boundry data (default: lft)
* `right_column`: column name for right boundry data (default: rgt)
* `depth_column`: column name for the depth data default (default: depth)
* `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]`
* `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.
* `counter_cache`: adds a counter cache for the number of children. defaults to false. Example: `acts_as_nested_set :counter_cache => :children_count`
* `order_column`: on which column to do sorting, by default it is the left_column_name. Example: `acts_as_nested_set :order_column => :position`

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

## Indexes

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`).

## Callbacks

There are three callbacks called when moving a node:
`before_move`, `after_move` and `around_move`.

```ruby
class Category < ActiveRecord::Base
  acts_as_nested_set

  after_move :rebuild_slug
  around_move :da_fancy_things_around

  private

  def rebuild_slug
    # do whatever
  end

  def da_fancy_things_around
    # do something...
    yield # actually moves
    # do something else...
  end
end
```

Beside this there are also hooks to act on the newly added or removed children.

```ruby
class Category < ActiveRecord::Base
  acts_as_nested_set  :before_add     => :do_before_add_stuff,
                      :after_add      => :do_after_add_stuff,
                      :before_remove  => :do_before_remove_stuff,
                      :after_remove   => :do_after_remove_stuff

  private

  def do_before_add_stuff(child_node)
    # do whatever with the child
  end

  def do_after_add_stuff(child_node)
    # do whatever with the child
  end

  def do_before_remove_stuff(child_node)
    # do whatever with the child
  end

  def do_after_remove_stuff(child_node)
    # do whatever with the child
  end
end
```

## Protecting attributes from mass assignment

It's generally best to "whitelist" the attributes that can be used in mass assignment:

```ruby
class Category < ActiveRecord::Base
  acts_as_nested_set
  attr_accessible :name, :parent_id
end
```

If for some reason that is not possible, you will probably want to protect the `lft` and `rgt` attributes:

```ruby
class Category < ActiveRecord::Base
  acts_as_nested_set
  attr_protected :lft, :rgt
end
```


## Add to your existing project

To make use of `awesome_nested_set`, your model needs to have 3 fields:
`lft`, `rgt`, and `parent_id`. The names of these fields are configurable.
You can also have an optional field, `depth`.

Create a migration to add fields:

```ruby
class AddNestedToCategories < ActiveRecord::Migration

  def self.up
    add_column :categories, :parent_id, :integer # Comment this line if your project already has this column
    # Category.where(parent_id: 0).update_all(parent_id: nil) # Uncomment this line if your project already has :parent_id
    add_column :categories, :lft      , :integer
    add_column :categories, :rgt      , :integer
    add_column :categories, :depth    , :integer  # this is optional.

    # This is necessary to update :lft and :rgt columns
    Category.rebuild!
  end

  def self.down
    remove_column :categories, :parent_id
    remove_column :categories, :lft
    remove_column :categories, :rgt
    remove_column :categories, :depth  # this is optional.
  end

end
```

Enable the nested set functionality by declaring `acts_as_nested_set` on your model

```ruby
class Category < ActiveRecord::Base
  acts_as_nested_set
end
```

Your project is now ready to run with the `awesome_nested_set` gem!


## Conversion from other trees

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:

```ruby
Category.rebuild!
```

Your tree will be converted to a valid nested set. Awesome!

## View Helper

The view helper is called #nested_set_options.

Example usage:

```erb
<%= f.select :parent_id, nested_set_options(Category, @category) {|i| "#{'-' * i.level} #{i.name}" } %>

<%= select_tag 'parent_id', options_for_select(nested_set_options(Category) {|i| "#{'-' * i.level} #{i.name}" } ) %>
```

See [CollectiveIdea::Acts::NestedSet::Helper](lib/awesome_nested_set/helper.rb) for more information about the helpers.

## References

You can learn more about nested sets at: http://threebit.net/tutorials/nestedset/tutorial1.html

## How to contribute

Please see the ['Contributing' document](CONTRIBUTING.md).

Copyright © 2008 - 2014 Collective Idea, released under the MIT license