Class: Tag
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Tag
- Defined in:
- lib/taxonomy/tag.rb
Instance Attribute Summary collapse
-
#skip_before_destroy ⇒ Object
Returns the value of attribute skip_before_destroy.
Class Method Summary collapse
- .all_roots_valid? ⇒ Boolean
- .find_context_with_slug!(context, slug) ⇒ Object
- .find_or_create_all_with_like_by_name(context, *list) ⇒ Object
- .find_or_create_with_like_by_name(context, name) ⇒ Object
- .left_and_rights_valid? ⇒ Boolean
- .no_duplicates_for_columns? ⇒ Boolean
-
.rebuild! ⇒ Object
Rebuilds the left & rights if unset or invalid.
-
.root ⇒ Object
CLASS METHODS:.
- .treed_taggings_for(context, options = {}) ⇒ Object
- .valid? ⇒ Boolean
Instance Method Summary collapse
-
#==(object) ⇒ Object
INSTANCE METHODS:.
-
#ancestors ⇒ Object
Returns an array of all parents.
-
#child? ⇒ Boolean
Returns true is this is a child node.
- #count ⇒ Object
-
#descendants ⇒ Object
Returns a set of all of its children and nested children.
- #is_ancestor_of?(other) ⇒ Boolean
- #is_descendant_of?(other) ⇒ Boolean
- #is_or_is_ancestor_of?(other) ⇒ Boolean
- #is_or_is_descendant_of?(other) ⇒ Boolean
- #leaf? ⇒ Boolean
-
#leaves ⇒ Object
Returns a set of all of its nested children which do not have children.
-
#left ⇒ Object
Value of the left column.
-
#left_sibling ⇒ Object
Find the first sibling to the left.
-
#level ⇒ Object
Returns the level of this object in the tree root level is 0.
-
#move_left ⇒ Object
Shorthand method for finding the left sibling and moving to the left of it.
- #move_possible?(target) ⇒ Boolean
-
#move_right ⇒ Object
Shorthand method for finding the right sibling and moving to the right of it.
-
#move_to_child_of(node) ⇒ Object
Move the node to the child of another node (you can pass id only).
-
#move_to_left_of(node) ⇒ Object
Move the node to the left of another node (you can pass id only).
-
#move_to_right_of(node) ⇒ Object
Move the node to the left of another node (you can pass id only).
-
#move_to_root ⇒ Object
Move the node to root nodes.
-
#parent_id ⇒ Object
Value of the parent column.
-
#right ⇒ Object
Value of the right column.
-
#right_sibling ⇒ Object
Find the first sibling to the right.
-
#root? ⇒ Boolean
Returns true if this is a root node.
-
#same_scope?(other) ⇒ Boolean
Check if other model is in the same scope.
-
#self_and_ancestors ⇒ Object
Returns the array of all parents and self.
-
#self_and_descendants ⇒ Object
Returns a set of itself and all of its nested children.
-
#self_and_siblings ⇒ Object
Returns the scope of all children of the parent, including self.
-
#siblings ⇒ Object
Returns the array of all children of the parent, except self.
- #to_s ⇒ Object
Instance Attribute Details
#skip_before_destroy ⇒ Object
Returns the value of attribute skip_before_destroy.
4 5 6 |
# File 'lib/taxonomy/tag.rb', line 4 def skip_before_destroy @skip_before_destroy end |
Class Method Details
.all_roots_valid? ⇒ Boolean
115 116 117 118 119 120 121 122 123 |
# File 'lib/taxonomy/tag.rb', line 115 def self.all_roots_valid? left = right = 0 roots.all? do |root| g_returning(root.left > left && root.right > right) do left = root.left right = root.right end end end |
.find_context_with_slug!(context, slug) ⇒ Object
65 66 67 68 69 |
# File 'lib/taxonomy/tag.rb', line 65 def self.find_context_with_slug!(context, slug) ret = self.where(:context => context, :slug => slug).first raise ActiveRecord::RecordNotFound if ret.nil? ret end |
.find_or_create_all_with_like_by_name(context, *list) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/taxonomy/tag.rb', line 75 def self.find_or_create_all_with_like_by_name(context, *list) list = [list].flatten return [] if list.empty? = Tag.named_any(context, list).all new_tag_names = list.reject { |name| .any? { |tag| tag.name.downcase == name.downcase } } = new_tag_names.map { |name| Tag.create(:context => "#{context.singularize.to_s}", :name => name) } + end |
.find_or_create_with_like_by_name(context, name) ⇒ Object
71 72 73 |
# File 'lib/taxonomy/tag.rb', line 71 def self.find_or_create_with_like_by_name(context, name) named_like(context, name).first || create(:context => "#{context.singularize.to_s}", :name => name) end |
.left_and_rights_valid? ⇒ Boolean
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/taxonomy/tag.rb', line 95 def self.left_and_rights_valid? self.base_class.joins("LEFT OUTER JOIN #{quoted_table_name} AS parent ON " + "#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:parent_column])} = parent.#{primary_key}").where( "#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} IS NULL OR " + "#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:right_column])} IS NULL OR " + "#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} >= " + "#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:right_column])} OR " + "(#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:parent_column])} IS NOT NULL AND " + "(#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} <= parent.#{connection.quote_column_name(Taxonomy.[:left_column])} OR " + "#{quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:right_column])} >= parent.#{connection.quote_column_name(Taxonomy.[:right_column])}))" ).count == 0 end |
.no_duplicates_for_columns? ⇒ Boolean
108 109 110 111 112 113 |
# File 'lib/taxonomy/tag.rb', line 108 def self.no_duplicates_for_columns? [connection.quote_column_name(Taxonomy.[:left_column]), connection.quote_column_name(Taxonomy.[:right_column])].all? do |column| # No duplicates self.base_class.select("#{column}, COUNT(#{column})").group("#{column} HAVING COUNT(#{column}) > 1").first.nil? end end |
.rebuild! ⇒ Object
Rebuilds the left & rights if unset or invalid. Also very useful for converting from acts_as_tree.
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 |
# File 'lib/taxonomy/tag.rb', line 126 def self.rebuild! # Don't rebuild a valid tree. return true if valid? scope = lambda{|node|} if Taxonomy.[:scope] scope = lambda{|node| scope_column_names.inject(""){|str, column_name| str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} " } } end indices = {} set_left_and_rights = lambda do |node| # set left node[Taxonomy.[:left_column]] = indices[scope.call(node)] += 1 # find find(:all, :conditions => ["#{connection.quote_column_name(Taxonomy.[:parent_column])} = ? #{scope.call(node)}", node], :order => "#{connection.quote_column_name(Taxonomy.[:left_column])}, #{connection.quote_column_name(Taxonomy.[:right_column])}, id").each{|n| set_left_and_rights.call(n) } # set right node[Taxonomy.[:right_column]] = indices[scope.call(node)] += 1 node.save! end # Find root node(s) root_nodes = find(:all, :conditions => "#{connection.quote_column_name(Taxonomy.[:parent_column])} IS NULL", :order => "#{connection.quote_column_name(Taxonomy.[:left_column])}, #{connection.quote_column_name(Taxonomy.[:right_column])}, id").each do |root_node| # setup index for this scope indices[scope.call(root_node)] ||= 0 set_left_and_rights.call(root_node) end end |
.root ⇒ Object
CLASS METHODS:
61 62 63 |
# File 'lib/taxonomy/tag.rb', line 61 def self.root roots.first end |
.treed_taggings_for(context, options = {}) ⇒ Object
91 92 93 |
# File 'lib/taxonomy/tag.rb', line 91 def self.treed_taggings_for(context, = {}) self.where("tags.context" => context.to_s.singularize) end |
.valid? ⇒ Boolean
87 88 89 |
# File 'lib/taxonomy/tag.rb', line 87 def self.valid? left_and_rights_valid? && no_duplicates_for_columns? && all_roots_valid? end |
Instance Method Details
#==(object) ⇒ Object
INSTANCE METHODS:
160 161 162 |
# File 'lib/taxonomy/tag.rb', line 160 def ==(object) super || (object.is_a?(Tag) && name == object.name) end |
#ancestors ⇒ Object
Returns an array of all parents
244 245 246 |
# File 'lib/taxonomy/tag.rb', line 244 def ancestors without_self(self_and_ancestors) end |
#child? ⇒ Boolean
Returns true is this is a child node
204 205 206 |
# File 'lib/taxonomy/tag.rb', line 204 def child? !parent_id.nil? end |
#count ⇒ Object
168 169 170 |
# File 'lib/taxonomy/tag.rb', line 168 def count read_attribute(:count).to_i end |
#descendants ⇒ Object
Returns a set of all of its children and nested children
239 240 241 |
# File 'lib/taxonomy/tag.rb', line 239 def descendants without_self(self_and_descendants) end |
#is_ancestor_of?(other) ⇒ Boolean
301 302 303 304 |
# File 'lib/taxonomy/tag.rb', line 301 def is_ancestor_of?(other) self.reload self.left < other.left && other.left < self.right && same_scope?(other) end |
#is_descendant_of?(other) ⇒ Boolean
291 292 293 294 |
# File 'lib/taxonomy/tag.rb', line 291 def is_descendant_of?(other) other.reload other.left < self.left && self.left < other.right && same_scope?(other) end |
#is_or_is_ancestor_of?(other) ⇒ Boolean
306 307 308 309 |
# File 'lib/taxonomy/tag.rb', line 306 def is_or_is_ancestor_of?(other) self.reload self.left <= other.left && other.left < self.right && same_scope?(other) end |
#is_or_is_descendant_of?(other) ⇒ Boolean
296 297 298 299 |
# File 'lib/taxonomy/tag.rb', line 296 def is_or_is_descendant_of?(other) other.reload other.left <= self.left && self.left < other.right && same_scope?(other) end |
#leaf? ⇒ Boolean
199 200 201 |
# File 'lib/taxonomy/tag.rb', line 199 def leaf? !new_record? && right - left == 1 end |
#leaves ⇒ Object
Returns a set of all of its nested children which do not have children
234 235 236 |
# File 'lib/taxonomy/tag.rb', line 234 def leaves descendants.where "#{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:right_column])} - #{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} = 1" end |
#left ⇒ Object
Value of the left column
184 185 186 |
# File 'lib/taxonomy/tag.rb', line 184 def left self[Taxonomy.[:left_column]] end |
#left_sibling ⇒ Object
Find the first sibling to the left
259 260 261 262 |
# File 'lib/taxonomy/tag.rb', line 259 def left_sibling siblings.where("#{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} < ?", left).order( "#{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} DESC").first end |
#level ⇒ Object
Returns the level of this object in the tree root level is 0
195 196 197 |
# File 'lib/taxonomy/tag.rb', line 195 def level parent_id.nil? ? 0 : ancestors.count end |
#move_left ⇒ Object
Shorthand method for finding the left sibling and moving to the left of it.
278 279 280 |
# File 'lib/taxonomy/tag.rb', line 278 def move_left move_to_left_of left_sibling end |
#move_possible?(target) ⇒ Boolean
312 313 314 315 316 317 318 |
# File 'lib/taxonomy/tag.rb', line 312 def move_possible?(target) self != target && # Can't target self same_scope?(target) && # can't be in different scopes # !(left..right).include?(target.left..target.right) # this needs tested more # detect impossible move !((left <= target.left && right >= target.left) or (left <= target.right && right >= target.right)) end |
#move_right ⇒ Object
Shorthand method for finding the right sibling and moving to the right of it.
282 283 284 |
# File 'lib/taxonomy/tag.rb', line 282 def move_right move_to_right_of right_sibling end |
#move_to_child_of(node) ⇒ Object
Move the node to the child of another node (you can pass id only)
254 255 256 |
# File 'lib/taxonomy/tag.rb', line 254 def move_to_child_of(node) move_to node, :child end |
#move_to_left_of(node) ⇒ Object
Move the node to the left of another node (you can pass id only)
270 271 272 |
# File 'lib/taxonomy/tag.rb', line 270 def move_to_left_of(node) move_to node, :left end |
#move_to_right_of(node) ⇒ Object
Move the node to the left of another node (you can pass id only)
274 275 276 |
# File 'lib/taxonomy/tag.rb', line 274 def move_to_right_of(node) move_to node, :right end |
#move_to_root ⇒ Object
Move the node to root nodes
287 288 289 |
# File 'lib/taxonomy/tag.rb', line 287 def move_to_root move_to nil, :root end |
#parent_id ⇒ Object
Value of the parent column
179 180 181 |
# File 'lib/taxonomy/tag.rb', line 179 def parent_id self[Taxonomy.[:parent_column]] end |
#right ⇒ Object
Value of the right column
189 190 191 |
# File 'lib/taxonomy/tag.rb', line 189 def right self[Taxonomy.[:right_column]] end |
#right_sibling ⇒ Object
Find the first sibling to the right
265 266 267 |
# File 'lib/taxonomy/tag.rb', line 265 def right_sibling siblings.where("#{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} > ?", left).first end |
#root? ⇒ Boolean
Returns true if this is a root node
175 176 177 |
# File 'lib/taxonomy/tag.rb', line 175 def root? parent_id.nil? end |
#same_scope?(other) ⇒ Boolean
Check if other model is in the same scope
227 228 229 230 231 |
# File 'lib/taxonomy/tag.rb', line 227 def same_scope?(other) Array(Taxonomy.[:scope]).all? do |attr| self.send(attr) == other.send(attr) end end |
#self_and_ancestors ⇒ Object
Returns the array of all parents and self
209 210 211 212 |
# File 'lib/taxonomy/tag.rb', line 209 def self_and_ancestors self.reload nested_set_scope.where("#{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} <= ? AND #{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:right_column])} >= ?", left, right) end |
#self_and_descendants ⇒ Object
Returns a set of itself and all of its nested children
215 216 217 218 |
# File 'lib/taxonomy/tag.rb', line 215 def self_and_descendants self.reload nested_set_scope.where("#{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:left_column])} >= ? AND #{self.class.quoted_table_name}.#{connection.quote_column_name(Taxonomy.[:right_column])} <= ?", left, right) end |
#self_and_siblings ⇒ Object
Returns the scope of all children of the parent, including self
221 222 223 224 |
# File 'lib/taxonomy/tag.rb', line 221 def self_and_siblings # Rails 3, but not really. scoped.where(Taxonomy.nested_set_options[:parent_column] => parent_id) nested_set_scope.where(["#{Taxonomy.[:parent_column]} == #{parent_id}"]) end |
#siblings ⇒ Object
Returns the array of all children of the parent, except self
249 250 251 |
# File 'lib/taxonomy/tag.rb', line 249 def siblings without_self(self_and_siblings) end |
#to_s ⇒ Object
164 165 166 |
# File 'lib/taxonomy/tag.rb', line 164 def to_s name end |