fast_tree 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ef95899f36c494fb5bc3cea8317205591f61dae7
4
+ data.tar.gz: f84331649e1fbf73db8853f7629ef8b7144f69a4
5
+ SHA512:
6
+ metadata.gz: 7a5137010f0f12bf4e6c03543814b542d218c61fecc8aee0e886e7fc7c66a6c39d2f51b1bcd9e843ef50ed99f07333e48002859ea5412dcb8d2b2e6d6ef94f9c
7
+ data.tar.gz: 8a6291deac4b760f876f50f24a2fec8c65262a1bf20b60c3a67041d60d4e6cdd4e13f3b789f71782c33a2e9c16f55782aacfde2534d60a5e8e5508082d9b66fd
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Chisato HASEGAWA
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # FastTree
2
+
3
+ [![CircleCI](https://circleci.com/gh/chase0213/fast_tree/tree/master.svg?style=svg)](https://circleci.com/gh/chase0213/fast_tree/tree/master)
4
+
5
+ Fast and Intuitive tree structure using nested sets model.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'fast_tree'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install fast_tree
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ `fast_tree` provides a generator which adds left and right pointers used in nested sets model to your model class.
27
+ Even if you have created a class or not, execute following commands in the terminal:
28
+
29
+ ```bash
30
+ $ bin/rails g fast_tree YOUR_MODEL_NAME
31
+ ```
32
+
33
+ After executing the command, add following sentence into your model:
34
+
35
+ ```ruby
36
+ include FastTree::Model
37
+ ```
38
+
39
+ Finally, you can use several methods as class methods and instance methods.
40
+
41
+ If you are interested in how it works, see the section "How It Works" below.
42
+
43
+ ### Create a tree
44
+
45
+ To initialize tree structure, do the following:
46
+
47
+ ```ruby
48
+ attributes = { name: "root node" }
49
+ YOUR_MODEL_NAME.create_tree(attributes)
50
+ ```
51
+
52
+ ### Create or add child
53
+
54
+ To create a new leaf under a node,
55
+
56
+ ```ruby
57
+ node = YOUR_MODEL_NAME.first
58
+
59
+ attributes = { name: "root node" }
60
+ node.create_child(attributes)
61
+ ```
62
+
63
+ or, to add existed node to another,
64
+
65
+ ```ruby
66
+ node = YOUR_MODEL_NAME.first
67
+
68
+ new_node = YOUR_MODEL_NAME.second
69
+ node.add_child(new_node)
70
+ ```
71
+
72
+ ### Create or add parent
73
+
74
+ To create a new parent over a node,
75
+
76
+ ```ruby
77
+ node = YOUR_MODEL_NAME.first
78
+
79
+ attributes = { name: "root node" }
80
+ YOUR_MODEL_NAME.create_parent(attributes, [node])
81
+ ```
82
+
83
+ or, to add existed node to another,
84
+
85
+ ```ruby
86
+ node = YOUR_MODEL_NAME.first
87
+
88
+ parent = YOUR_MODEL_NAME.second
89
+ YOUR_MODEL_NAME.add_parent(parent, [node])
90
+ ```
91
+
92
+ You can add/create a parent over several nodes:
93
+
94
+ ```ruby
95
+ children = YOUR_MODEL_NAME.take(3)
96
+ parent = YOUR_MODEL_NAME.last
97
+ YOUR_MODEL_NAME.add_parent(parent, children)
98
+ ```
99
+
100
+ NOTE: this method has a issue: https://github.com/chase0213/fast_tree/issues/6
101
+
102
+ ### Remove a node
103
+
104
+ To remove a node reconstructing the tree,
105
+
106
+ ```ruby
107
+ node = YOUR_MODEL_NAME.take
108
+ node.remove
109
+ ```
110
+
111
+ If you don't want to reconstruct the tree after deleting a node, do the following:
112
+
113
+ ```ruby
114
+ node = YOUR_MODEL_NAME.take
115
+ node.destroy
116
+ ```
117
+
118
+ ### Copy a subtree under a node
119
+
120
+ To copy a subtree under a node,
121
+
122
+ ```ruby
123
+ root_of_subtree = YOUR_MODEL_NAME.first
124
+ target = YOUR_MODEL_NAME.second
125
+
126
+ root_of_subtree.copy_to(targe)
127
+ ```
128
+
129
+ ### Move a subtree under a node
130
+
131
+ To move a subtree under a node,
132
+
133
+ ```ruby
134
+ root_of_subtree = YOUR_MODEL_NAME.first
135
+ target = YOUR_MODEL_NAME.second
136
+
137
+ root_of_subtree.move_to(targe)
138
+ ```
139
+
140
+
141
+ ## How It Works
142
+ The migration file will create a migration file, such as:
143
+
144
+ ```ruby
145
+ class AddFastTreeToTestTrees < ActiveRecord::Migration[5.0]
146
+ def self.up
147
+ change_table :test_trees do |t|
148
+ ## Pointers
149
+ t.integer :l_ptr
150
+ t.integer :r_ptr
151
+
152
+ end
153
+
154
+ add_index :test_trees, :l_ptr
155
+ add_index :test_trees, :r_ptr
156
+ end
157
+
158
+ def self.down
159
+ # model already existed. Please edit below which fields you would like to remove in this migration.
160
+ end
161
+ end
162
+ ```
163
+
164
+ , but you don't have to care what `l_ptr` and `r_ptr` are:
165
+ tree operations are executed in methods such as `create_child` or `remove`.
166
+
167
+
168
+ ## Contributing
169
+
170
+ 1. Fork it
171
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
172
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
173
+ 4. Push to the branch (`git push origin my-new-feature`)
174
+ 5. Create new Pull Request
175
+
176
+ ## License
177
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'FastTree'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,260 @@
1
+ module FastTree
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ # =================
6
+ # Class Methods
7
+ # =================
8
+
9
+ module ClassMethods
10
+
11
+ # ====================
12
+ # structure operation
13
+ # ====================
14
+
15
+ def add_parent(parent, children, &block)
16
+ # create space for parent
17
+ ptrs = _create_parent_embedded_space(children)
18
+
19
+ # parent node's pointer
20
+ parent.l_ptr = ptrs[:l_ptr]
21
+ parent.r_ptr = ptrs[:r_ptr]
22
+ parent.save
23
+ end
24
+
25
+ def create_parent(attributes = {}, children, &block)
26
+ # create space for parent
27
+ ptrs = _create_parent_embedded_space(children)
28
+
29
+ # parent node's pointer
30
+ attributes[:l_ptr] = ptrs[:l_ptr]
31
+ attributes[:r_ptr] = ptrs[:r_ptr]
32
+
33
+ self.create(attributes, &block)
34
+ end
35
+
36
+ def create_tree(attributes={}, &block)
37
+ root = self.find_root
38
+ if root
39
+ root
40
+ else
41
+ attributes[:l_ptr] = 0
42
+ attributes[:r_ptr] = 1
43
+ self.create(attributes, &block)
44
+ end
45
+ end
46
+
47
+
48
+ def _create_parent_embedded_space(children)
49
+ left = children.max {|c| c.l_ptr}.l_ptr
50
+ right = children.min {|c| c.r_ptr}.r_ptr
51
+
52
+ sql = <<-"EOS"
53
+ UPDATE #{self.to_s.underscore.pluralize}
54
+ SET l_ptr = CASE
55
+ WHEN l_ptr >= #{left}
56
+ AND r_ptr <= #{right}
57
+ THEN l_ptr + 1
58
+ WHEN l_ptr > #{right}
59
+ THEN l_ptr + 2
60
+ ELSE l_ptr
61
+ END,
62
+ r_ptr = CASE
63
+ WHEN l_ptr >= #{left}
64
+ AND r_ptr <= #{right}
65
+ THEN r_ptr + 1
66
+ WHEN l_ptr < #{left}
67
+ AND r_ptr > #{right}
68
+ THEN r_ptr + 2
69
+ WHEN l_ptr > #{right}
70
+ THEN r_ptr + 2
71
+ ELSE r_ptr
72
+ END
73
+ WHERE r_ptr > #{left}
74
+ EOS
75
+
76
+ ActiveRecord::Base.connection.execute(sql)
77
+
78
+ # return left and right pointers between which parent is embedded
79
+ {l_ptr: left, r_ptr: right + 2}
80
+ end
81
+
82
+ # ================
83
+ # model operation
84
+ # ================
85
+
86
+ def find_root
87
+ self.find_by(l_ptr: 0)
88
+ end
89
+
90
+ def find_subtree_by_root(node)
91
+ l_ptr = node.l_ptr
92
+ r_ptr = node.r_ptr
93
+
94
+ self.where(self.arel_table[:l_ptr].gteq(l_ptr))
95
+ .where(self.arel_table[:r_ptr].lteq(r_ptr))
96
+ end
97
+
98
+ # ================
99
+ # for debugging
100
+ # ================
101
+
102
+ def print_subtree(root)
103
+ puts("printing sub tree for #{root.name}...")
104
+ subtree = find_subtree_by_root(root)
105
+ subtree.order(l_ptr: :asc).each do |st_node|
106
+ st_node.reload
107
+ # white spaces on the left
108
+ wsl = st_node.l_ptr.times.map{|s| "_"}.join('')
109
+ # arrows
110
+ ars = (st_node.r_ptr - st_node.l_ptr ).times.map{|s| "-"}.join('')
111
+ # white spaces on the right
112
+ wsr = (root.width + 2 - wsl.size - ars.size).times.map{|s| " "}.join('')
113
+
114
+ puts("#{wsl}<#{ars}>#{wsr} ... #{st_node.name}")
115
+ end
116
+ puts("done.\n")
117
+ end
118
+ end
119
+
120
+
121
+ # class methods
122
+ # =========================================================
123
+ # instance methods
124
+
125
+
126
+ # =================
127
+ # Instance Methods
128
+ # =================
129
+
130
+ def add_child(node)
131
+ # bulk update nodes by a sql query
132
+ _update_nodes(r_ptr, r_ptr, "r_ptr >= #{r_ptr}")
133
+
134
+ # child node's pointer
135
+ node.l_ptr = r_ptr
136
+ node.r_ptr = r_ptr + 1
137
+ node.save
138
+ end
139
+
140
+ def create_child(attributes = {}, &block)
141
+ # bulk update nodes by a sql query
142
+ _update_nodes(r_ptr, r_ptr, "r_ptr >= #{r_ptr}")
143
+
144
+ # create child
145
+ attributes[:l_ptr] = r_ptr
146
+ attributes[:r_ptr] = r_ptr + 1
147
+ self.class.create(attributes, &block)
148
+ end
149
+
150
+ def copy_to(node)
151
+ subtree = self.class.find_subtree_by_root(self)
152
+
153
+ # create empty space into which subtree embedded
154
+ _update_nodes(node.l_ptr, node.r_ptr, "r_ptr >= #{r_ptr}", width + 1)
155
+
156
+ bias = node.l_ptr + 1 - l_ptr
157
+ subtree.each do |st_node|
158
+ attributes = st_node.attributes.to_h
159
+ attributes.delete("id")
160
+ attributes["l_ptr"] = attributes["l_ptr"] + bias
161
+ attributes["r_ptr"] = attributes["r_ptr"] + bias
162
+ self.class.create(attributes)
163
+ end
164
+ end
165
+
166
+ def depth
167
+ path.size - 1
168
+ end
169
+
170
+ def move_to(node)
171
+ # NOTE:
172
+ # copy_to and remove change node ids
173
+ # move operation should change nothing but left and right pointers
174
+
175
+ # bind subtree to a variable
176
+ subtree = self.class.find_subtree_by_root(self)
177
+
178
+ # fill (virtual) empty spaces that will be created by moving subtree
179
+ _update_nodes(l_ptr, r_ptr, "l_ptr > #{r_ptr}", - (width + 1))
180
+
181
+ # create empty spaces under the node
182
+ node.reload
183
+ _update_nodes(node.l_ptr, node.r_ptr, "l_ptr >= #{node.l_ptr} AND r_ptr <= #{node.r_ptr}", width + 1)
184
+
185
+ # move subtree under the given node
186
+ bias = node.l_ptr + 1 - l_ptr
187
+ subtree.each do |st_node|
188
+ st_node.l_ptr += bias
189
+ st_node.r_ptr += bias
190
+ st_node.save
191
+ end
192
+ end
193
+
194
+ def remove
195
+ # remove subtree
196
+ n_destroyed = self.class.find_subtree_by_root(self).destroy_all
197
+
198
+ # fill empty space
199
+ _update_nodes(l_ptr, r_ptr, "r_ptr >= #{r_ptr}", - (width + 1))
200
+
201
+ # return count of destroyed nodes
202
+ n_destroyed
203
+ end
204
+
205
+ def path
206
+ self.class.where(self.class.arel_table[:l_ptr].lteq(l_ptr))
207
+ .where(self.class.arel_table[:r_ptr].gteq(r_ptr))
208
+ .order(l_ptr: :asc)
209
+ end
210
+
211
+ def print_subtree
212
+ self.class.print_subtree(self)
213
+ end
214
+
215
+ def width
216
+ r_ptr - l_ptr
217
+ end
218
+
219
+
220
+ protected
221
+
222
+ def _update_nodes(left, right, condition, diff = 2)
223
+ #
224
+ # NOTE:
225
+ # Due to performance reason,
226
+ # use raw SQL query to move nodes
227
+ #
228
+
229
+ sql = <<-"EOS"
230
+ UPDATE #{self.class.to_s.underscore.pluralize}
231
+ SET l_ptr = CASE
232
+ WHEN l_ptr > #{right}
233
+ THEN l_ptr + #{diff}
234
+ WHEN l_ptr > #{left}
235
+ AND r_ptr < #{right}
236
+ THEN l_ptr + #{diff - 1}
237
+ ELSE l_ptr
238
+ END,
239
+ r_ptr = CASE
240
+ WHEN l_ptr <= #{left}
241
+ AND r_ptr >= #{right}
242
+ THEN r_ptr + #{diff}
243
+ WHEN l_ptr > #{right}
244
+ THEN r_ptr + #{diff}
245
+ WHEN l_ptr > #{left}
246
+ AND r_ptr < #{right}
247
+ THEN r_ptr + #{diff - 1}
248
+ ELSE
249
+ r_ptr
250
+ END
251
+ WHERE #{condition}
252
+ EOS
253
+
254
+ ActiveRecord::Base.connection.execute(sql)
255
+ end
256
+
257
+ class InvalidTreeStructureError < ActiveRecord::RecordInvalid; end
258
+
259
+ end
260
+ end
@@ -0,0 +1,3 @@
1
+ module FastTree
2
+ VERSION = '0.1.0'
3
+ end
data/lib/fast_tree.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'rails'
2
+
3
+ module FastTree
4
+
5
+ # =====================================
6
+ # Implementation of Fast Tree Structure
7
+ # =====================================
8
+
9
+ autoload :Model, 'fast_tree/model'
10
+
11
+ end
@@ -0,0 +1,48 @@
1
+ require 'rails/generators/active_record'
2
+ require 'generators/fast_tree/orm_helpers'
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class FastTreeGenerator < ActiveRecord::Generators::Base
7
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
8
+
9
+ include FastTree::Generators::OrmHelpers
10
+ source_root File.expand_path("../templates", __FILE__)
11
+
12
+ def copy_fast_tree_migration
13
+ if (behavior == :invoke && model_exists?) || (behavior == :revoke && migration_exists?(table_name))
14
+ migration_template "migration_existing.rb", "db/migrate/add_fast_tree_to_#{table_name}.rb", migration_version: migration_version
15
+ else
16
+ migration_template "migration.rb", "db/migrate/fast_tree_create_#{table_name}.rb", migration_version: migration_version
17
+ end
18
+ end
19
+
20
+ def generate_model
21
+ invoke "active_record:model", [name], migration: false unless model_exists? && behavior == :invoke
22
+ end
23
+
24
+ def migration_data
25
+ <<RUBY
26
+ ## Pointers
27
+ t.integer :l_ptr
28
+ t.integer :r_ptr
29
+ RUBY
30
+ end
31
+
32
+ def rails5?
33
+ Rails.version.start_with? '5'
34
+ end
35
+
36
+ def postgresql?
37
+ config = ActiveRecord::Base.configurations[Rails.env]
38
+ config && config['adapter'] == 'postgresql'
39
+ end
40
+
41
+ def migration_version
42
+ if rails5?
43
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,16 @@
1
+ class FastTreeCreate<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ create_table :<%= table_name %> do |t|
4
+ <%= migration_data -%>
5
+
6
+ <% attributes.each do |attribute| -%>
7
+ t.<%= attribute.type %> :<%= attribute.name %>
8
+ <% end -%>
9
+
10
+ t.timestamps null: false
11
+ end
12
+
13
+ add_index :<%= table_name %>, :l_ptr
14
+ add_index :<%= table_name %>, :r_ptr
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ class AddFastTreeTo<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
2
+ def self.up
3
+ change_table :<%= table_name %> do |t|
4
+ <%= migration_data -%>
5
+
6
+ <% attributes.each do |attribute| -%>
7
+ t.<%= attribute.type %> :<%= attribute.name %>
8
+ <% end -%>
9
+ end
10
+
11
+ add_index :<%= table_name %>, :l_ptr
12
+ add_index :<%= table_name %>, :r_ptr
13
+ end
14
+
15
+ def self.down
16
+ # model already existed. Please edit below which fields you would like to remove in this migration.
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators/named_base'
2
+
3
+ module FastTree
4
+ module Generators
5
+ class FastTreeGenerator < Rails::Generators::NamedBase
6
+ include Rails::Generators::ResourceHelpers
7
+
8
+ namespace "fast_tree"
9
+ source_root File.expand_path("../templates", __FILE__)
10
+
11
+ desc "Generates a model with the given NAME (if one does not exist) with a migration file"
12
+
13
+ hook_for :orm
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module FastTree
2
+ module Generators
3
+ module OrmHelpers
4
+ private
5
+
6
+ def model_exists?
7
+ File.exist?(File.join(destination_root, model_path))
8
+ end
9
+
10
+ def migration_exists?(table_name)
11
+ Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_fast_tree_to_#{table_name}.rb$/).first
12
+ end
13
+
14
+ def migration_path
15
+ @migration_path ||= File.join("db", "migrate")
16
+ end
17
+
18
+ def model_path
19
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :fast_tree do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fast_tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chisato Hasegawa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: acts_as_tree
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
+ description: fast_tree is an implementation of tree structure using nested sets model
56
+ email:
57
+ - chase0213@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - MIT-LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - lib/fast_tree.rb
66
+ - lib/fast_tree/model.rb
67
+ - lib/fast_tree/version.rb
68
+ - lib/generators/active_record/fast_tree_generator.rb
69
+ - lib/generators/active_record/templates/migration.rb
70
+ - lib/generators/active_record/templates/migration_existing.rb
71
+ - lib/generators/fast_tree/fast_tree_generator.rb
72
+ - lib/generators/fast_tree/orm_helpers.rb
73
+ - lib/tasks/fast_tree_tasks.rake
74
+ homepage: https://github.com/chase0213/fast_tree
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.5.1
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: '["Rails plugin for Fast Tree Structure", "fast_tree is an implementation
98
+ of tree structure using nested sets model", "MIT"]'
99
+ test_files: []