Commit f83ac4db9062a997faf339fefb59e0bf046c271b

Authored by AntonioTerceiro
1 parent 63f3d444

ActionItem21: moving filesystem-like behaviour from Category class into lib/acts…

…_as_filesystem.rb. All tests for Category still passing.



git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@937 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing 2 changed files with 132 additions and 103 deletions   Show diff stats
app/models/category.rb
@@ -14,113 +14,11 @@ class Category < ActiveRecord::Base @@ -14,113 +14,11 @@ class Category < ActiveRecord::Base
14 end 14 end
15 end 15 end
16 16
17 - acts_as_tree :order => 'name'  
18 -  
19 - # calculates the full name of a category by accessing the name of all its  
20 - # ancestors.  
21 - #  
22 - # If you have this category hierarchy:  
23 - # Category "A"  
24 - # Category "B"  
25 - # Category "C"  
26 - #  
27 - # Then Category "C" will have "A/B/C" as its full name.  
28 - def full_name(sep = '/')  
29 - my_name = self.name ? self.name : '?'  
30 - self.parent ? (self.parent.full_name(sep) + sep + my_name) : (my_name)  
31 - end  
32 -  
33 - # calculates the level of the category in the category hierarchy. Top-level  
34 - # categories have level 0; the children of the top-level categories have  
35 - # level 1; the children of categories with level 1 have level 2, and so on.  
36 - #  
37 - # A level 0  
38 - # / \  
39 - # B C level 1  
40 - # / \ / \  
41 - # E F G H level 2  
42 - # ...  
43 - def level  
44 - self.parent ? (self.parent.level + 1) : 0  
45 - end  
46 -  
47 - # Is this category a top-level category?  
48 - def top_level?  
49 - self.parent.nil?  
50 - end  
51 -  
52 - # Is this category a leaf in the hierarchy tree of categories?  
53 - #  
54 - # Being a leaf means that this category has no subcategories.  
55 - def leaf?  
56 - self.children.empty?  
57 - end  
58 -  
59 # Finds all top level categories for a given environment. 17 # Finds all top level categories for a given environment.
60 def self.top_level_for(environment) 18 def self.top_level_for(environment)
61 self.find(:all, :conditions => ['parent_id is null and environment_id = ?', environment.id ]) 19 self.find(:all, :conditions => ['parent_id is null and environment_id = ?', environment.id ])
62 end 20 end
63 21
64 - # used to know when to trigger batch renaming  
65 - attr_accessor :recalculate_path  
66 -  
67 - # sets the name of the category. Also sets #slug accordingly.  
68 - def name=(value)  
69 - if self.name != value  
70 - self.recalculate_path = true  
71 - end  
72 -  
73 - self[:name] = value  
74 - unless self.name.blank?  
75 - # FIXME encapsulate this patter (transliterate -> downcase -> gsub ...)  
76 - # in a String method, say, to_slug  
77 - self.slug = self.name.transliterate.downcase.gsub( /[^-a-z0-9~\s\.:;+=_]/, '').gsub(/[\s\.:;=_+]+/, '-').gsub(/[\-]{2,}/, '-').to_s  
78 - end  
79 - end  
80 -  
81 - # sets the slug of the category. Also sets the path with the new slug value.  
82 - def slug=(value)  
83 - self[:slug] = value  
84 - unless self.slug.blank?  
85 - self.path = self.calculate_path  
86 - end  
87 - end  
88 -  
89 - # calculates the full path to this category using parent's path.  
90 - def calculate_path  
91 - if self.top_level?  
92 - self.slug  
93 - else  
94 - self.parent.calculate_path + "/" + self.slug  
95 - end  
96 - end  
97 -  
98 - # calculate the right path  
99 - before_create do |cat|  
100 - if cat.path == cat.slug && (! cat.top_level?)  
101 - cat.path = cat.calculate_path  
102 - end  
103 - end  
104 -  
105 - # when renaming a category, all children categories must have their paths  
106 - # recalculated  
107 - after_update do |cat|  
108 - if cat.recalculate_path  
109 - cat.children.each do |item|  
110 - item.path = item.calculate_path  
111 - item.recalculate_path = true  
112 - item.save!  
113 - end  
114 - end  
115 - cat.recalculate_path = false  
116 - end  
117 -  
118 - def top_ancestor  
119 - self.top_level? ? self : self.parent.top_ancestor  
120 - end  
121 -  
122 - def explode_path  
123 - path.split(/\//)  
124 - end 22 + acts_as_filesystem
125 23
126 end 24 end
lib/acts_as_filesystem.rb 0 → 100644
@@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
  1 +module ActsAsFileSystem
  2 +
  3 + module ClassMethods
  4 +
  5 + # Declares the ActiveRecord model to acts like a filesystem: objects are
  6 + # arranged in a tree (liks acts_as_tree), and . The underlying table must
  7 + # have the following fields:
  8 + #
  9 + # * name (+:string+) - the title of the object
  10 + # * slug (+:string+)- the title turned in a URL-friendly string (downcased,
  11 + # non-ascii chars transliterated into ascii, all sequences of
  12 + # non-alphanumericd characters changed into dashed)
  13 + # * path (+:text+)- stores the full path of the object (the full path of
  14 + # the parent, a "/" and the slug of the object)
  15 + def acts_as_filesystem
  16 +
  17 + include ActsAsFileSystem::InstanceMethods
  18 +
  19 + # a filesystem is a tree
  20 + acts_as_tree :order => 'name'
  21 +
  22 + # calculate the right path
  23 + before_create do |record|
  24 + if record.path == record.slug && (! record.top_level?)
  25 + record.path = record.calculate_path
  26 + end
  27 + end
  28 +
  29 + # when renaming a category, all children categories must have their paths
  30 + # recalculated
  31 + after_update do |record|
  32 + if record.recalculate_path
  33 + record.children.each do |item|
  34 + item.path = item.calculate_path
  35 + item.recalculate_path = true
  36 + item.save!
  37 + end
  38 + end
  39 + record.recalculate_path = false
  40 + end
  41 +
  42 + end
  43 + end
  44 +
  45 + module InstanceMethods
  46 + # used to know when to trigger batch renaming
  47 + attr_accessor :recalculate_path
  48 +
  49 + # calculates the full name of a category by accessing the name of all its
  50 + # ancestors.
  51 + #
  52 + # If you have this category hierarchy:
  53 + # Category "A"
  54 + # Category "B"
  55 + # Category "C"
  56 + #
  57 + # Then Category "C" will have "A/B/C" as its full name.
  58 + def full_name(sep = '/')
  59 + my_name = self.name ? self.name : '?'
  60 + self.parent ? (self.parent.full_name(sep) + sep + my_name) : (my_name)
  61 + end
  62 +
  63 + # calculates the level of the category in the category hierarchy. Top-level
  64 + # categories have level 0; the children of the top-level categories have
  65 + # level 1; the children of categories with level 1 have level 2, and so on.
  66 + #
  67 + # A level 0
  68 + # / \
  69 + # B C level 1
  70 + # / \ / \
  71 + # E F G H level 2
  72 + # ...
  73 + def level
  74 + self.parent ? (self.parent.level + 1) : 0
  75 + end
  76 +
  77 + # Is this category a top-level category?
  78 + def top_level?
  79 + self.parent.nil?
  80 + end
  81 +
  82 + # Is this category a leaf in the hierarchy tree of categories?
  83 + #
  84 + # Being a leaf means that this category has no subcategories.
  85 + def leaf?
  86 + self.children.empty?
  87 + end
  88 +
  89 + # sets the name of the category. Also sets #slug accordingly.
  90 + def name=(value)
  91 + if self.name != value
  92 + self.recalculate_path = true
  93 + end
  94 +
  95 + self[:name] = value
  96 + unless self.name.blank?
  97 + # FIXME encapsulate this pattern (transliterate -> downcase -> gsub
  98 + # ...) in a String method, say, to_slug
  99 + self.slug = self.name.transliterate.downcase.gsub( /[^-a-z0-9~\s\.:;+=_]/, '').gsub(/[\s\.:;=_+]+/, '-').gsub(/[\-]{2,}/, '-').to_s
  100 + end
  101 + end
  102 +
  103 + # sets the slug of the category. Also sets the path with the new slug value.
  104 + def slug=(value)
  105 + self[:slug] = value
  106 + unless self.slug.blank?
  107 + self.path = self.calculate_path
  108 + end
  109 + end
  110 +
  111 + # calculates the full path to this category using parent's path.
  112 + def calculate_path
  113 + if self.top_level?
  114 + self.slug
  115 + else
  116 + self.parent.calculate_path + "/" + self.slug
  117 + end
  118 + end
  119 +
  120 + def top_ancestor
  121 + self.top_level? ? self : self.parent.top_ancestor
  122 + end
  123 +
  124 + def explode_path
  125 + path.split(/\//)
  126 + end
  127 + end
  128 +end
  129 +
  130 +ActiveRecord::Base.extend ActsAsFileSystem::ClassMethods
  131 +