forestify 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +49 -0
  3. data/lib/forestify.rb +73 -0
  4. metadata +48 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2012 Gabriel Malkas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # forestify
2
+
3
+ forestify creates forests out of your Active Record models : it implements a simple data-structure which hierarchizes your data.
4
+
5
+ For example, given the following model :
6
+
7
+ ```ruby
8
+ class Tag < ActiveRecord::Base
9
+ attr_accessible :name
10
+ forestify
11
+ end
12
+ ```
13
+
14
+ You can then do something like this :
15
+
16
+ ```ruby
17
+ vehicle = Tag.new(name: "Vehicle")
18
+ vehicle.save!
19
+ car = Tag.new(name: "Car", parent: vehicle.id)
20
+ car.save!
21
+ audi = Tag.new(name: "Audi", parent: car.id)
22
+ audi.save!
23
+
24
+ audi.parents
25
+ # => [vehicle, car]
26
+ car.is_leaf?
27
+ # => false
28
+ car.is_node?
29
+ # => true
30
+ ```
31
+
32
+ # Installation
33
+
34
+ Run ```gem install forestify``` or add this line to your Gemfile ```gem 'forestify'``` then run ```bundle install```
35
+
36
+ Although I will add generators later, you still need to manually add migrations to make your models "forestify-ready".
37
+
38
+ ```ruby
39
+ change_table :tags do |t|
40
+ t.string :name
41
+ t.integer :left_position
42
+ t.integer :right_position
43
+ t.integer :level
44
+ end
45
+ ```
46
+
47
+ # LICENSE
48
+
49
+ Copyright 2012 Gabriel Malkas. Released under MIT License. See LICENSE for details.
data/lib/forestify.rb ADDED
@@ -0,0 +1,73 @@
1
+ module Forestify
2
+ def forestify
3
+ unless included_modules.include? InstanceMethods
4
+ include InstanceMethods
5
+ end
6
+ before_create :initialize_position
7
+ before_destroy :update_positions_after_delete
8
+ attr_accessor :parent
9
+ end
10
+
11
+ module InstanceMethods
12
+
13
+ # Initialize position fields
14
+ # Should be run only once
15
+ def initialize_position
16
+ # @parent = -1 is the option 'No parent'
17
+ if @parent.nil? || @parent == "-1"
18
+ # No parent has been specified, we need to add this leaf
19
+ # to the right side of the last root node.
20
+ last = self.class.order("right_position DESC").first
21
+ self.left_position = (last.nil?) ? 0 : last.right_position + 1
22
+ self.right_position = self.left_position + 1
23
+ self.level = 0
24
+ else
25
+ # Makes sure it's an integer
26
+ @parent = @parent.to_i
27
+ p = self.class.find(@parent)
28
+ self.left_position = p.right_position
29
+ self.right_position = self.left_position + 1
30
+ self.level = p.level + 1
31
+ # update nodes on the right hand side of parent
32
+ self.class.update_all "left_position = left_position + 2", ['left_position > ?', p.right_position]
33
+ self.class.update_all "right_position = right_position + 2", ['right_position > ?', p.right_position]
34
+ # update parent
35
+ p.update_attribute 'right_position', p.right_position + 2
36
+ end
37
+ end
38
+
39
+ def update_positions_after_delete
40
+ if is_node?
41
+ # Update nodes to the right
42
+ self.class.update_all "left_position = left_position - 2", ['left_position > ?', self.right_position]
43
+ self.class.update_all "right_position = right_position - 2", ['right_position > ?', self.right_position]
44
+ # Update children
45
+ self.class.update_all "level = level - 1", ['left_position > ? AND right_position < ?', self.left_position, self.right_position]
46
+ self.class.update_all "left_position = left_position - 1, right_position = right_position - 1", ['left_position > ? AND right_position < ?', self.left_position, self.right_position]
47
+ else
48
+ self.class.update_all "left_position = left_position - 2", ['left_position > ?', self.right_position]
49
+ self.class.update_all "right_position = right_position - 2", ['right_position > ?', self.right_position]
50
+ end
51
+ end
52
+
53
+
54
+ def parents
55
+ self.class.where('left_position < ?', self.left_position).where('right_position > ?', self.right_position)
56
+ end
57
+
58
+ def children
59
+ [] if is_leaf?
60
+ self.class.where('left_position > ?', self.left_position).where('right_position < ?', self.right_position)
61
+ end
62
+
63
+ def is_node?
64
+ (self.right_position - self.left_position) > 1
65
+ end
66
+
67
+ def is_leaf?
68
+ !is_node?
69
+ end
70
+ end
71
+ end
72
+
73
+ ActiveRecord::Base.send :extend, Forestify
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: forestify
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gabriel Malkas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-05 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Forestify brings a tree data-structure to your Active Record models
15
+ email: gabriel.malkas@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - LICENSE
22
+ - lib/forestify.rb
23
+ homepage: ''
24
+ licenses:
25
+ - MIT
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 1.8.11
45
+ signing_key:
46
+ specification_version: 3
47
+ summary: Forestify brings a tree data-structure to your Active Record models
48
+ test_files: []