Changeset 7
- Timestamp:
- 08/15/06 00:58:32 (2 years ago)
- Files:
-
- trunk/Rakefile.rb (modified) (1 diff)
- trunk/init.rb (modified) (1 diff)
- trunk/lib/better_nested_set.rb (modified) (6 diffs)
- trunk/lib/better_nested_set_helper.rb (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Rakefile.rb
r2 r7 6 6 task :default => :test 7 7 8 desc 'Test the plugin.'8 desc 'Test the better_nested_set plugin.' 9 9 Rake::TestTask.new(:test) do |t| 10 10 t.libs << 'lib' 11 t.test_files = ['test/preload_active_support.rb'] + FileList['test/t_*.rb'] + FileList[' activesupport_mb/test/multibyte/*.rb']11 t.test_files = ['test/preload_active_support.rb'] + FileList['test/t_*.rb'] + FileList['lib/*.rb'] 12 12 t.verbose = true 13 13 end trunk/init.rb
r5 r7 4 4 # 5 5 require 'better_nested_set' 6 require 'better_nested_set_helper' 6 7 7 8 ActiveRecord::Base.class_eval do 8 9 include SymetrieCom::Acts::NestedSet 9 10 end 10 # later... ActionView::Base.send :include,BetterNestedSetHelper11 ActionView::Base.send :include, SymetrieCom::Acts::BetterNestedSetHelper trunk/lib/better_nested_set.rb
r6 r7 65 65 # * +left_column+ - column name for left boundry data, default "lft" 66 66 # * +right_column+ - column name for right boundry data, default "rgt" 67 # * +text_column+ - column name for the title field (optional). Used as default in the 68 # {your-class}_options_for_select helper method. If empty, will use the first string field 69 # of your model class. 67 70 # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id" 68 71 # (if that hasn't been already) and use that as the foreign key restriction. It's also possible … … 83 86 :left_column => (options[:left_column] || 'lft'), 84 87 :right_column => (options[:right_column] || 'rgt'), 85 :scope => (options[:scope] || '1 = 1') } ) 88 :scope => (options[:scope] || '1 = 1'), 89 :text_column => (options[:text_column] || columns.collect{|c| (c.type == :string) ? c.name : nil }.compact.first) 90 } ) 86 91 87 92 class_inheritable_reader :acts_as_nested_set_options … … 97 102 end 98 103 def #{acts_as_nested_set_options[:right_column]}=(x) 99 raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{acts_as_nested_set_options[:right_column]}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead."104 raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{acts_as_nested_set_options[:right_column]}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead." 100 105 end 101 106 def #{acts_as_nested_set_options[:parent_column]}=(x) 102 raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{acts_as_nested_set_options[:parent_column]}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead."107 raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{acts_as_nested_set_options[:parent_column]}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead." 103 108 end 104 109 end_eval … … 106 111 include SymetrieCom::Acts::NestedSet::InstanceMethods 107 112 extend SymetrieCom::Acts::NestedSet::ClassMethods 113 114 # adds the helper for the class 115 # ActionView::Base.send(:define_method, "#{Inflector.underscore(self.class)}_options_for_select") { special=nil 116 # "#{acts_as_nested_set_options[:text_column]} || "#{self.class} id #{id}" 117 # } 118 108 119 end 109 end 110 111 module ClassMethods 112 # Returns the single root 113 def root 114 self.find(:first, :conditions => "(#{acts_as_nested_set_options[:scope]} AND #{acts_as_nested_set_options[:parent_column]} IS NULL)") 115 end 116 # Returns roots when multiple roots (or virtual root, which is the same) 117 def roots 118 self.find(:all, :conditions => "(#{acts_as_nested_set_options[:scope]} AND #{acts_as_nested_set_options[:parent_column]} IS NULL)", :order => "#{acts_as_nested_set_options[:left_column]}") 119 end 120 121 # Returns the single root 122 def root 123 self.find(:first, :conditions => "(#{acts_as_nested_set_options[:scope]} AND #{acts_as_nested_set_options[:parent_column]} IS NULL)") 124 end 125 126 # Returns roots when multiple roots (or virtual root, which is the same) 127 def roots 128 self.find(:all, :conditions => "(#{acts_as_nested_set_options[:scope]} AND #{acts_as_nested_set_options[:parent_column]} IS NULL)", :order => "#{acts_as_nested_set_options[:left_column]}") 129 end 120 130 end 121 131 … … 252 262 253 263 # Returns a set of itself and all of its nested children 254 def full_set 264 # Pass :exclude => item, or id, or [items or id] to exclude some parts of the tree 265 def full_set(special=nil) 255 266 return [self] if new_record? or self[acts_as_nested_set_options[:right_column]]-self[acts_as_nested_set_options[:left_column]] == 1 256 self.class.find(:all, :conditions => "#{acts_as_nested_set_options[:scope]} AND (#{acts_as_nested_set_options[:left_column]} BETWEEN #{self[acts_as_nested_set_options[:left_column]]} and #{self[acts_as_nested_set_options[:right_column]]})", :order => acts_as_nested_set_options[:left_column]) 267 # self.class.find(:all, :conditions => "#{acts_as_nested_set_options[:scope]} AND (#{acts_as_nested_set_options[:left_column]} BETWEEN #{self[acts_as_nested_set_options[:left_column]]} and #{self[acts_as_nested_set_options[:right_column]]})", :order => acts_as_nested_set_options[:left_column]) 268 [self] + all_children(special) 257 269 end 258 270 259 271 # Returns a set of all of its children and nested children 260 def all_children 272 # Pass :exclude => item, or id, or [items or id] to exclude some parts of the tree 273 def all_children(special=nil) 274 if special && special[:exclude] 275 transaction do 276 # exclude some items and all their children 277 special[:exclude] = [special[:exclude]] if !special[:exclude].is_a?(Array) 278 # get objects for ids 279 special[:exclude].collect! {|s| s.is_a?(self.class) ? s : self.class.find(s)} 280 # get all subtrees and flatten the list 281 exclude_list = special[:exclude].map{|e| e.full_set.map{|ee| ee.id}}.flatten.uniq.join(',') 282 if exclude_list.blank? 283 self.class.find(:all, :conditions => "#{acts_as_nested_set_options[:scope]} AND (#{acts_as_nested_set_options[:left_column]} > #{self[acts_as_nested_set_options[:left_column]]}) and (#{acts_as_nested_set_options[:right_column]} < #{self[acts_as_nested_set_options[:right_column]]})", :order => acts_as_nested_set_options[:left_column]) 284 else 285 self.class.find(:all, :conditions => "#{acts_as_nested_set_options[:scope]} AND id NOT IN (#{exclude_list}) AND (#{acts_as_nested_set_options[:left_column]} > #{self[acts_as_nested_set_options[:left_column]]}) and (#{acts_as_nested_set_options[:right_column]} < #{self[acts_as_nested_set_options[:right_column]]})", :order => acts_as_nested_set_options[:left_column]) 286 end 287 end 288 else 261 289 self.class.find(:all, :conditions => "#{acts_as_nested_set_options[:scope]} AND (#{acts_as_nested_set_options[:left_column]} > #{self[acts_as_nested_set_options[:left_column]]}) and (#{acts_as_nested_set_options[:right_column]} < #{self[acts_as_nested_set_options[:right_column]]})", :order => acts_as_nested_set_options[:left_column]) 290 end 262 291 end 263 292 … … 383 412 384 413 end 414 385 415 end 386 416 end
