Commit 8923158bf6bc9f7ae4b485381b3cde99de123b1d

Authored by Braulio Bhavamitra
Committed by Braulio Bhavamitra
1 parent 95ebdaf6

Improve migration performance

db/migrate/20120820142056_add_ancestry_to_categories.rb
... ... @@ -2,10 +2,7 @@ class AddAncestryToCategories < ActiveRecord::Migration
2 2 def self.up
3 3 add_column :categories, :ancestry, :text
4 4  
5   - Category.all.each do |category|
6   - category.set_ancestry
7   - category.save!
8   - end
  5 + Category.build_ancestry
9 6 end
10 7  
11 8 def self.down
... ...
lib/acts_as_filesystem.rb
1 1 module ActsAsFileSystem
2 2  
3   - module ClassMethods
  3 + module ActsMethods
4 4  
5 5 # Declares the ActiveRecord model to acts like a filesystem: objects are
6 6 # arranged in a tree (liks acts_as_tree), and . The underlying table must
... ... @@ -14,11 +14,12 @@ module ActsAsFileSystem
14 14 # the parent, a "/" and the slug of the object)
15 15 # * children_count - a cache of the number of children elements.
16 16 def acts_as_filesystem
17   - include ActsAsFileSystem::InstanceMethods
18   -
19 17 # a filesystem is a tree
20 18 acts_as_tree :counter_cache => :children_count
21 19  
  20 + include InstanceMethods
  21 + extend ClassMethods
  22 +
22 23 before_create :set_path
23 24 before_save :set_ancestry
24 25 after_update :update_children_path
... ... @@ -26,6 +27,20 @@ module ActsAsFileSystem
26 27  
27 28 end
28 29  
  30 + module ClassMethods
  31 +
  32 + def build_ancestry(parent_id = nil, ancestry = '')
  33 + self.base_class.all(:conditions => {:parent_id => parent_id}).each do |node|
  34 + node.ancestry = ancestry
  35 + node.save :run_callbacks => false
  36 +
  37 + build_ancestry node.id, (ancestry.empty? ? "#{node.formatted_ancestry_id}" :
  38 + "#{ancestry}#{node.ancestry_sep}#{node.formatted_ancestry_id}")
  39 + end
  40 + end
  41 +
  42 + end
  43 +
29 44 module InstanceMethods
30 45  
31 46 # used to know when to trigger batch renaming
... ... @@ -44,25 +59,35 @@ module ActsAsFileSystem
44 59 path.split(/\//)
45 60 end
46 61  
  62 + def ancestry_column
  63 + 'ancestry'
  64 + end
  65 + def ancestry_sep
  66 + '.'
  67 + end
47 68 def has_ancestry?
48   - self.class.column_names.include? 'ancestry'
  69 + self.class.column_names.include? self.ancestry_column
49 70 end
50   - def ancestry
51   - self['ancestry']
  71 +
  72 + def formatted_ancestry_id
  73 + "%010d" % self.id if self.id
52 74 end
53   - def ancestry=(value)
54   - self['ancestry'] = value
  75 +
  76 + def ancestry
  77 + self[ancestry_column]
55 78 end
56   - # get the serialized tree from database column 'ancetry'
57   - # and convert it to an array
58   - def ancestry_ids
  79 + def ancestor_ids
59 80 return nil if !has_ancestry? or ancestry.nil?
60   - @ancestry_ids ||= ancestry.split('.').map{ |id| id.to_i }
  81 + @ancestor_ids ||= ancestry.split(ancestry_sep).map{ |id| id.to_i }
  82 + end
  83 +
  84 + def ancestry=(value)
  85 + self[ancestry_column] = value
61 86 end
62 87 def set_ancestry
63 88 return unless self.has_ancestry?
64 89 if self.ancestry.nil? or (new_record? or parent_id_changed?) or recalculate_path
65   - self.ancestry = self.hierarchy[0...-1].map{ |p| "%010d" % p.id }.join('.')
  90 + self.ancestry = self.hierarchy(true)[0...-1].map{ |p| p.formatted_ancestry_id }.join(ancestry_sep)
66 91 end
67 92 end
68 93  
... ... @@ -107,7 +132,7 @@ module ActsAsFileSystem
107 132 self.hierarchy.first
108 133 end
109 134 def top_ancestor_id
110   - self.ancestry_ids.first
  135 + self.ancestor_ids.first
111 136 end
112 137  
113 138 # returns the full hierarchy from the top-level item to this one. For
... ... @@ -123,9 +148,9 @@ module ActsAsFileSystem
123 148 if @hierarchy.nil?
124 149 @hierarchy = []
125 150  
126   - if ancestry_ids
127   - objects = self.class.base_class.all(:conditions => {:id => ancestry_ids})
128   - ancestry_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } }
  151 + if !reload and !recalculate_path and ancestor_ids
  152 + objects = self.class.base_class.all(:conditions => {:id => ancestor_ids})
  153 + ancestor_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } }
129 154 @hierarchy << self
130 155 else
131 156 item = self
... ... @@ -207,5 +232,5 @@ module ActsAsFileSystem
207 232 end
208 233 end
209 234  
210   -ActiveRecord::Base.extend ActsAsFileSystem::ClassMethods
  235 +ActiveRecord::Base.extend ActsAsFileSystem::ActsMethods
211 236  
... ...