summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhukl <hukl@berlin.ccc.de>2009-01-29 22:12:11 +0100
committerhukl <hukl@berlin.ccc.de>2009-01-29 22:12:11 +0100
commitbe47a4bbeac59d85af16b5e83e10ff242628519d (patch)
treee25870a53dc19d10e7112ece98b82112d64cfe02
parentd4dfdb40329b8e15e6bba022b966984a8a994a87 (diff)
added node model to make basic functional tests pass. added awesome_nested_set plugin
-rw-r--r--.gitmodules3
-rw-r--r--app/controllers/content_controller.rb7
-rw-r--r--app/models/node.rb3
-rw-r--r--app/views/layouts/application.html.erb0
-rw-r--r--db/migrate/20090129204750_create_nodes.rb14
-rw-r--r--db/migrate/20090129205013_add_missing_columns_for_nested_set_for_node.rb13
-rw-r--r--test/fixtures/nodes.yml8
-rw-r--r--test/functional/content_controller_test.rb23
-rw-r--r--test/unit/node_test.rb8
-rw-r--r--vendor/plugins/awesome_nested_set/.autotest13
-rw-r--r--vendor/plugins/awesome_nested_set/.gitignore5
-rw-r--r--vendor/plugins/awesome_nested_set/MIT-LICENSE20
-rw-r--r--vendor/plugins/awesome_nested_set/README.rdoc64
-rw-r--r--vendor/plugins/awesome_nested_set/Rakefile46
-rw-r--r--vendor/plugins/awesome_nested_set/awesome_nested_set.gemspec20
-rw-r--r--vendor/plugins/awesome_nested_set/init.rb1
-rw-r--r--vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb546
-rw-r--r--vendor/plugins/awesome_nested_set/lib/awesome_nested_set/compatability.rb29
-rw-r--r--vendor/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb40
-rw-r--r--vendor/plugins/awesome_nested_set/lib/awesome_nested_set/named_scope.rb140
-rw-r--r--vendor/plugins/awesome_nested_set/rails/init.rb13
-rw-r--r--vendor/plugins/awesome_nested_set/test/awesome_nested_set/helper_test.rb41
-rw-r--r--vendor/plugins/awesome_nested_set/test/awesome_nested_set_test.rb603
-rw-r--r--vendor/plugins/awesome_nested_set/test/fixtures/categories.yml34
-rw-r--r--vendor/plugins/awesome_nested_set/test/fixtures/category.rb15
-rw-r--r--vendor/plugins/awesome_nested_set/test/fixtures/departments.yml3
-rw-r--r--vendor/plugins/awesome_nested_set/test/fixtures/notes.yml38
-rw-r--r--vendor/plugins/awesome_nested_set/test/test_helper.rb31
28 files changed, 1770 insertions, 11 deletions
diff --git a/.gitmodules b/.gitmodules
index 5f43dd3..a4de19c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
1[submodule "vendor/rails"] 1[submodule "vendor/rails"]
2 path = vendor/rails 2 path = vendor/rails
3 url = git://github.com/rails/rails.git 3 url = git://github.com/rails/rails.git
4[submodule "vendor/awesome_nested_set"]
5 path = vendor/awesome_nested_set
6 url = git://github.com/collectiveidea/awesome_nested_set.git
diff --git a/app/controllers/content_controller.rb b/app/controllers/content_controller.rb
index afa093c..8059fab 100644
--- a/app/controllers/content_controller.rb
+++ b/app/controllers/content_controller.rb
@@ -1,5 +1,12 @@
1class ContentController < ApplicationController 1class ContentController < ApplicationController
2
2 def render_page 3 def render_page
4 path = params[:page_path].join('/')
5
6 @node = Node.find_by_unique_name(path)
7
8 # Replace with real 404
9 render :status => 404 unless @node
3 end 10 end
4 11
5end 12end
diff --git a/app/models/node.rb b/app/models/node.rb
new file mode 100644
index 0000000..82183c9
--- /dev/null
+++ b/app/models/node.rb
@@ -0,0 +1,3 @@
1class Node < ActiveRecord::Base
2 acts_as_nested_set
3end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/views/layouts/application.html.erb
diff --git a/db/migrate/20090129204750_create_nodes.rb b/db/migrate/20090129204750_create_nodes.rb
new file mode 100644
index 0000000..e7cd562
--- /dev/null
+++ b/db/migrate/20090129204750_create_nodes.rb
@@ -0,0 +1,14 @@
1class CreateNodes < ActiveRecord::Migration
2 def self.up
3 create_table :nodes do |t|
4 t.string :slug
5 t.string :unique_name
6
7 t.timestamps
8 end
9 end
10
11 def self.down
12 drop_table :nodes
13 end
14end
diff --git a/db/migrate/20090129205013_add_missing_columns_for_nested_set_for_node.rb b/db/migrate/20090129205013_add_missing_columns_for_nested_set_for_node.rb
new file mode 100644
index 0000000..f8f8404
--- /dev/null
+++ b/db/migrate/20090129205013_add_missing_columns_for_nested_set_for_node.rb
@@ -0,0 +1,13 @@
1class AddMissingColumnsForNestedSetForNode < ActiveRecord::Migration
2 def self.up
3 add_column :nodes, :lft, :integer
4 add_column :nodes, :rgt, :integer
5 add_column :nodes, :parent_id, :integer
6 end
7
8 def self.down
9 remove_column :nodes, :lft
10 remove_column :nodes, :rgt
11 remove_column :nodes, :parent_id
12 end
13end
diff --git a/test/fixtures/nodes.yml b/test/fixtures/nodes.yml
new file mode 100644
index 0000000..9879d9f
--- /dev/null
+++ b/test/fixtures/nodes.yml
@@ -0,0 +1,8 @@
1# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
3one:
4 id: 1
5 lft: 1
6 rgt: 2
7 slug: my_first_page
8 unique_name: root/my_first_page
diff --git a/test/functional/content_controller_test.rb b/test/functional/content_controller_test.rb
index c44b221..15e1299 100644
--- a/test/functional/content_controller_test.rb
+++ b/test/functional/content_controller_test.rb
@@ -7,15 +7,16 @@ class ContentControllerTest < ActionController::TestCase
7 assert_recognizes({ :controller => 'content', :action => 'render_page', :language => 'en', :pagepath => ['home'] }, '/en/home') 7 assert_recognizes({ :controller => 'content', :action => 'render_page', :language => 'en', :pagepath => ['home'] }, '/en/home')
8 end 8 end
9 9
10 # def test_rendering_a_page 10 def test_render_404_when_no_page_was_found
11 # Page.destroy_all 11 get :render_page, :language => 'de', :page_path => ["wrong_path"]
12 # load_atp 'content_controller' 12 assert_response 404
13 # Page.all.each {|x| x.update_unique_name; x.save} 13 end
14 # assert Page.valid? 14
15 # assert_not_nil Page.find_by_title("short name yo") 15 def test_rendering_a_page
16 # get :render_page, :language => 'de', :pagepath => ["shortname","barfoo"] 16 assert Node.valid?
17 # assert_response :success 17 assert_not_nil Node.find_by_slug("my_first_page")
18 # assert_template 'wtp_eins' 18 get :render_page, :language => 'de', :page_path => ["root", "my_first_page"]
19 # assert_equal "page_templates/layouts/screen", @response.layout 19 assert_response :success
20 # end 20 assert_equal "layouts/application", @response.layout
21 end
21end 22end
diff --git a/test/unit/node_test.rb b/test/unit/node_test.rb
new file mode 100644
index 0000000..a311b84
--- /dev/null
+++ b/test/unit/node_test.rb
@@ -0,0 +1,8 @@
1require 'test_helper'
2
3class NodeTest < ActiveSupport::TestCase
4 # Replace this with your real tests.
5 test "the truth" do
6 assert true
7 end
8end
diff --git a/vendor/plugins/awesome_nested_set/.autotest b/vendor/plugins/awesome_nested_set/.autotest
new file mode 100644
index 0000000..54518a4
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/.autotest
@@ -0,0 +1,13 @@
1Autotest.add_hook :initialize do |at|
2 at.clear_mappings
3
4 at.add_mapping %r%^lib/(.*)\.rb$% do |_, m|
5 at.files_matching %r%^test/#{m[1]}_test.rb$%
6 end
7
8 at.add_mapping(%r%^test/.*\.rb$%) {|filename, _| filename }
9
10 at.add_mapping %r%^test/fixtures/(.*)s.yml% do |_, _|
11 at.files_matching %r%^test/.*\.rb$%
12 end
13end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/.gitignore b/vendor/plugins/awesome_nested_set/.gitignore
new file mode 100644
index 0000000..df112b0
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/.gitignore
@@ -0,0 +1,5 @@
1awesome_nested_set.sqlite3.db
2test/debug.log
3rdoc
4coverage
5pkg
diff --git a/vendor/plugins/awesome_nested_set/MIT-LICENSE b/vendor/plugins/awesome_nested_set/MIT-LICENSE
new file mode 100644
index 0000000..570ecf8
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/MIT-LICENSE
@@ -0,0 +1,20 @@
1Copyright (c) 2007 [name of plugin creator]
2
3Permission is hereby granted, free of charge, to any person obtaining
4a copy of this software and associated documentation files (the
5"Software"), to deal in the Software without restriction, including
6without limitation the rights to use, copy, modify, merge, publish,
7distribute, sublicense, and/or sell copies of the Software, and to
8permit persons to whom the Software is furnished to do so, subject to
9the following conditions:
10
11The above copyright notice and this permission notice shall be
12included in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/plugins/awesome_nested_set/README.rdoc b/vendor/plugins/awesome_nested_set/README.rdoc
new file mode 100644
index 0000000..c093f75
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/README.rdoc
@@ -0,0 +1,64 @@
1= AwesomeNestedSet
2
3Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models. It is replacement for acts_as_nested_set and BetterNestedSet, but awesomer.
4
5== What makes this so awesome?
6
7This is a new implementation of nested set based off of BetterNestedSet that fixes some bugs, removes tons of duplication, adds a few useful methods, and adds STI support.
8
9== Installation
10
11If you are on Rails 2.1 or later:
12
13 script/plugin install git://github.com/collectiveidea/awesome_nested_set.git
14
15== Usage
16
17To make use of awesome_nested_set, your model needs to have 3 fields: lft, rgt, and parent_id:
18
19 class CreateCategories < ActiveRecord::Migration
20 def self.up
21 create_table :categories do |t|
22 t.string :name
23 t.integer :parent_id
24 t.integer :lft
25 t.integer :rgt
26 end
27 end
28
29 def self.down
30 drop_table :categories
31 end
32 end
33
34Enable the nested set functionality by declaring acts_as_nested_set on your model
35
36 class Category < ActiveRecord::Base
37 acts_as_nested_set
38 end
39
40Run `rake rdoc` to generate the API docs and see CollectiveIdea::Acts::NestedSet::SingletonMethods for more info.
41
42== View Helper
43
44The view helper is called #nested_set_options.
45
46Example usage:
47
48 <%= f.select :parent_id, nested_set_options(Category, @category) {|i| "#{'-' * i.level} #{i.name}" } %>
49
50 <%= select_tag 'parent_id', options_for_select(nested_set_options(Category) {|i| "#{'-' * i.level} #{i.name}" } ) %>
51
52See CollectiveIdea::Acts::NestedSet::Helper for more information about the helpers.
53
54== References
55
56You can learn more about nested sets at:
57
58 http://www.dbmsmag.com/9603d06.html
59 http://threebit.net/tutorials/nestedset/tutorial1.html
60 http://api.rubyonrails.com/classes/ActiveRecord/Acts/NestedSet/ClassMethods.html
61 http://opensource.symetrie.com/trac/better_nested_set/
62
63
64Copyright (c) 2008 Collective Idea, released under the MIT license \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/Rakefile b/vendor/plugins/awesome_nested_set/Rakefile
new file mode 100644
index 0000000..53906f6
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/Rakefile
@@ -0,0 +1,46 @@
1require 'rake'
2require 'rake/testtask'
3require 'rake/rdoctask'
4require 'rake/gempackagetask'
5require 'rcov/rcovtask'
6require "load_multi_rails_rake_tasks"
7
8spec = eval(File.read("#{File.dirname(__FILE__)}/awesome_nested_set.gemspec"))
9PKG_NAME = spec.name
10PKG_VERSION = spec.version
11
12Rake::GemPackageTask.new(spec) do |pkg|
13 pkg.need_zip = true
14 pkg.need_tar = true
15end
16
17
18desc 'Default: run unit tests.'
19task :default => :test
20
21desc 'Test the awesome_nested_set plugin.'
22Rake::TestTask.new(:test) do |t|
23 t.libs << 'lib'
24 t.pattern = 'test/**/*_test.rb'
25 t.verbose = true
26end
27
28desc 'Generate documentation for the awesome_nested_set plugin.'
29Rake::RDocTask.new(:rdoc) do |rdoc|
30 rdoc.rdoc_dir = 'rdoc'
31 rdoc.title = 'AwesomeNestedSet'
32 rdoc.options << '--line-numbers' << '--inline-source'
33 rdoc.rdoc_files.include('README.rdoc')
34 rdoc.rdoc_files.include('lib/**/*.rb')
35end
36
37namespace :test do
38 desc "just rcov minus html output"
39 Rcov::RcovTask.new(:coverage) do |t|
40 # t.libs << 'test'
41 t.test_files = FileList['test/**/*_test.rb']
42 t.output_dir = 'coverage'
43 t.verbose = true
44 t.rcov_opts = %w(--exclude test,/usr/lib/ruby,/Library/Ruby,lib/awesome_nested_set/named_scope.rb --sort coverage)
45 end
46end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/awesome_nested_set.gemspec b/vendor/plugins/awesome_nested_set/awesome_nested_set.gemspec
new file mode 100644
index 0000000..c5a1d49
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/awesome_nested_set.gemspec
@@ -0,0 +1,20 @@
1Gem::Specification.new do |s|
2 s.name = "awesome_nested_set"
3 s.version = "1.1.1"
4 s.summary = "An awesome replacement for acts_as_nested_set and better_nested_set."
5 s.description = s.summary
6
7 s.files = %w(init.rb MIT-LICENSE Rakefile README.rdoc lib/awesome_nested_set.rb lib/awesome_nested_set/compatability.rb lib/awesome_nested_set/helper.rb lib/awesome_nested_set/named_scope.rb rails/init.rb test/awesome_nested_set_test.rb test/test_helper.rb test/awesome_nested_set/helper_test.rb test/db/database.yml test/db/schema.rb test/fixtures/categories.yml test/fixtures/category.rb test/fixtures/departments.yml test/fixtures/notes.yml)
8
9 s.add_dependency "activerecord", ['>= 1.1']
10
11 s.has_rdoc = true
12 s.extra_rdoc_files = [ "README.rdoc"]
13 s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
14
15 s.test_files = %w(test/awesome_nested_set_test.rb test/test_helper.rb test/awesome_nested_set/helper_test.rb test/db/database.yml test/db/schema.rb test/fixtures/categories.yml test/fixtures/category.rb test/fixtures/departments.yml test/fixtures/notes.yml)
16 s.require_path = 'lib'
17 s.author = "Collective Idea"
18 s.email = "info@collectiveidea.com"
19 s.homepage = "http://collectiveidea.com"
20end
diff --git a/vendor/plugins/awesome_nested_set/init.rb b/vendor/plugins/awesome_nested_set/init.rb
new file mode 100644
index 0000000..43dc7c2
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/init.rb
@@ -0,0 +1 @@
require File.dirname(__FILE__) + "/rails/init"
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb
new file mode 100644
index 0000000..3e10891
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb
@@ -0,0 +1,546 @@
1module CollectiveIdea #:nodoc:
2 module Acts #:nodoc:
3 module NestedSet #:nodoc:
4 def self.included(base)
5 base.extend(SingletonMethods)
6 end
7
8 # This acts provides Nested Set functionality. Nested Set is a smart way to implement
9 # an _ordered_ tree, with the added feature that you can select the children and all of their
10 # descendants with a single query. The drawback is that insertion or move need some complex
11 # sql queries. But everything is done here by this module!
12 #
13 # Nested sets are appropriate each time you want either an orderd tree (menus,
14 # commercial categories) or an efficient way of querying big trees (threaded posts).
15 #
16 # == API
17 #
18 # Methods names are aligned with acts_as_tree as much as possible, to make replacment from one
19 # by another easier, except for the creation:
20 #
21 # in acts_as_tree:
22 # item.children.create(:name => "child1")
23 #
24 # in acts_as_nested_set:
25 # # adds a new item at the "end" of the tree, i.e. with child.left = max(tree.right)+1
26 # child = MyClass.new(:name => "child1")
27 # child.save
28 # # now move the item to its right place
29 # child.move_to_child_of my_item
30 #
31 # You can pass an id or an object to:
32 # * <tt>#move_to_child_of</tt>
33 # * <tt>#move_to_right_of</tt>
34 # * <tt>#move_to_left_of</tt>
35 #
36 module SingletonMethods
37 # Configuration options are:
38 #
39 # * +:parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id)
40 # * +:left_column+ - column name for left boundry data, default "lft"
41 # * +:right_column+ - column name for right boundry data, default "rgt"
42 # * +:scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id"
43 # (if it hasn't been already) and use that as the foreign key restriction. You
44 # can also pass an array to scope by multiple attributes.
45 # Example: <tt>acts_as_nested_set :scope => [:notable_id, :notable_type]</tt>
46 # * +:dependent+ - behavior for cascading destroy. If set to :destroy, all the
47 # child objects are destroyed alongside this object by calling their destroy
48 # method. If set to :delete_all (default), all the child objects are deleted
49 # without calling their destroy method.
50 #
51 # See CollectiveIdea::Acts::NestedSet::ClassMethods for a list of class methods and
52 # CollectiveIdea::Acts::NestedSet::InstanceMethods for a list of instance methods added
53 # to acts_as_nested_set models
54 def acts_as_nested_set(options = {})
55 options = {
56 :parent_column => 'parent_id',
57 :left_column => 'lft',
58 :right_column => 'rgt',
59 :dependent => :delete_all, # or :destroy
60 }.merge(options)
61
62 if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
63 options[:scope] = "#{options[:scope]}_id".intern
64 end
65
66 write_inheritable_attribute :acts_as_nested_set_options, options
67 class_inheritable_reader :acts_as_nested_set_options
68
69 include Comparable
70 include Columns
71 include InstanceMethods
72 extend Columns
73 extend ClassMethods
74
75 # no bulk assignment
76 attr_protected left_column_name.intern,
77 right_column_name.intern,
78 parent_column_name.intern
79
80 before_create :set_default_left_and_right
81 before_destroy :prune_from_tree
82
83 # no assignment to structure fields
84 [left_column_name, right_column_name, parent_column_name].each do |column|
85 module_eval <<-"end_eval", __FILE__, __LINE__
86 def #{column}=(x)
87 raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{column}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead."
88 end
89 end_eval
90 end
91
92 named_scope :roots, :conditions => {parent_column_name => nil}, :order => quoted_left_column_name
93 named_scope :leaves, :conditions => "#{quoted_right_column_name} - #{quoted_left_column_name} = 1", :order => quoted_left_column_name
94 if self.respond_to?(:define_callbacks)
95 define_callbacks("before_move", "after_move")
96 end
97
98
99 end
100
101 end
102
103 module ClassMethods
104
105 # Returns the first root
106 def root
107 roots.find(:first)
108 end
109
110 def valid?
111 left_and_rights_valid? && no_duplicates_for_columns? && all_roots_valid?
112 end
113
114 def left_and_rights_valid?
115 count(
116 :joins => "LEFT OUTER JOIN #{quoted_table_name} AS parent ON " +
117 "#{quoted_table_name}.#{quoted_parent_column_name} = parent.#{primary_key}",
118 :conditions =>
119 "#{quoted_table_name}.#{quoted_left_column_name} IS NULL OR " +
120 "#{quoted_table_name}.#{quoted_right_column_name} IS NULL OR " +
121 "#{quoted_table_name}.#{quoted_left_column_name} >= " +
122 "#{quoted_table_name}.#{quoted_right_column_name} OR " +
123 "(#{quoted_table_name}.#{quoted_parent_column_name} IS NOT NULL AND " +
124 "(#{quoted_table_name}.#{quoted_left_column_name} <= parent.#{quoted_left_column_name} OR " +
125 "#{quoted_table_name}.#{quoted_right_column_name} >= parent.#{quoted_right_column_name}))"
126 ) == 0
127 end
128
129 def no_duplicates_for_columns?
130 scope_string = Array(acts_as_nested_set_options[:scope]).map do |c|
131 connection.quote_column_name(c)
132 end.push(nil).join(", ")
133 [quoted_left_column_name, quoted_right_column_name].all? do |column|
134 # No duplicates
135 find(:first,
136 :select => "#{scope_string}#{column}, COUNT(#{column})",
137 :group => "#{scope_string}#{column}
138 HAVING COUNT(#{column}) > 1").nil?
139 end
140 end
141
142 # Wrapper for each_root_valid? that can deal with scope.
143 def all_roots_valid?
144 if acts_as_nested_set_options[:scope]
145 roots(:group => scope_column_names).group_by{|record| scope_column_names.collect{|col| record.send(col.to_sym)}}.all? do |scope, grouped_roots|
146 each_root_valid?(grouped_roots)
147 end
148 else
149 each_root_valid?(roots)
150 end
151 end
152
153 def each_root_valid?(roots_to_validate)
154 left = right = 0
155 roots_to_validate.all? do |root|
156 returning(root.left > left && root.right > right) do
157 left = root.left
158 right = root.right
159 end
160 end
161 end
162
163 # Rebuilds the left & rights if unset or invalid. Also very useful for converting from acts_as_tree.
164 def rebuild!
165 # Don't rebuild a valid tree.
166 return true if valid?
167
168 scope = lambda{}
169 if acts_as_nested_set_options[:scope]
170 scope = lambda{|node|
171 scope_column_names.inject(""){|str, column_name|
172 str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} "
173 }
174 }
175 end
176 indices = {}
177
178 set_left_and_rights = lambda do |node|
179 # set left
180 node[left_column_name] = indices[scope.call(node)] += 1
181 # find
182 find(:all, :conditions => ["#{quoted_parent_column_name} = ? #{scope.call(node)}", node], :order => "#{quoted_left_column_name}, #{quoted_right_column_name}, id").each{|n| set_left_and_rights.call(n) }
183 # set right
184 node[right_column_name] = indices[scope.call(node)] += 1
185 node.save!
186 end
187
188 # Find root node(s)
189 root_nodes = find(:all, :conditions => "#{quoted_parent_column_name} IS NULL", :order => "#{quoted_left_column_name}, #{quoted_right_column_name}, id").each do |root_node|
190 # setup index for this scope
191 indices[scope.call(root_node)] ||= 0
192 set_left_and_rights.call(root_node)
193 end
194 end
195 end
196
197 # Mixed into both classes and instances to provide easy access to the column names
198 module Columns
199 def left_column_name
200 acts_as_nested_set_options[:left_column]
201 end
202
203 def right_column_name
204 acts_as_nested_set_options[:right_column]
205 end
206
207 def parent_column_name
208 acts_as_nested_set_options[:parent_column]
209 end
210
211 def scope_column_names
212 Array(acts_as_nested_set_options[:scope])
213 end
214
215 def quoted_left_column_name
216 connection.quote_column_name(left_column_name)
217 end
218
219 def quoted_right_column_name
220 connection.quote_column_name(right_column_name)
221 end
222
223 def quoted_parent_column_name
224 connection.quote_column_name(parent_column_name)
225 end
226
227 def quoted_scope_column_names
228 scope_column_names.collect {|column_name| connection.quote_column_name(column_name) }
229 end
230 end
231
232 # Any instance method that returns a collection makes use of Rails 2.1's named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.
233 #
234 # category.self_and_descendants.count
235 # category.ancestors.find(:all, :conditions => "name like '%foo%'")
236 module InstanceMethods
237 # Value of the parent column
238 def parent_id
239 self[parent_column_name]
240 end
241
242 # Value of the left column
243 def left
244 self[left_column_name]
245 end
246
247 # Value of the right column
248 def right
249 self[right_column_name]
250 end
251
252 # Returns true if this is a root node.
253 def root?
254 parent_id.nil?
255 end
256
257 def leaf?
258 right - left == 1
259 end
260
261 # Returns true is this is a child node
262 def child?
263 !parent_id.nil?
264 end
265
266 # order by left column
267 def <=>(x)
268 left <=> x.left
269 end
270
271 # Redefine to act like active record
272 def ==(comparison_object)
273 comparison_object.equal?(self) ||
274 (comparison_object.instance_of?(self.class) &&
275 comparison_object.id == id &&
276 !comparison_object.new_record?)
277 end
278
279 # Returns root
280 def root
281 self_and_ancestors.find(:first)
282 end
283
284 # Returns the immediate parent
285 def parent
286 nested_set_scope.find_by_id(parent_id) if parent_id
287 end
288
289 # Returns the array of all parents and self
290 def self_and_ancestors
291 nested_set_scope.scoped :conditions => [
292 "#{self.class.table_name}.#{quoted_left_column_name} <= ? AND #{self.class.table_name}.#{quoted_right_column_name} >= ?", left, right
293 ]
294 end
295
296 # Returns an array of all parents
297 def ancestors
298 without_self self_and_ancestors
299 end
300
301 # Returns the array of all children of the parent, including self
302 def self_and_siblings
303 nested_set_scope.scoped :conditions => {parent_column_name => parent_id}
304 end
305
306 # Returns the array of all children of the parent, except self
307 def siblings
308 without_self self_and_siblings
309 end
310
311 # Returns a set of all of its nested children which do not have children
312 def leaves
313 descendants.scoped :conditions => "#{self.class.table_name}.#{quoted_right_column_name} - #{self.class.table_name}.#{quoted_left_column_name} = 1"
314 end
315
316 # Returns the level of this object in the tree
317 # root level is 0
318 def level
319 parent_id.nil? ? 0 : ancestors.count
320 end
321
322 # Returns a set of itself and all of its nested children
323 def self_and_descendants
324 nested_set_scope.scoped :conditions => [
325 "#{self.class.table_name}.#{quoted_left_column_name} >= ? AND #{self.class.table_name}.#{quoted_right_column_name} <= ?", left, right
326 ]
327 end
328
329 # Returns a set of all of its children and nested children
330 def descendants
331 without_self self_and_descendants
332 end
333
334 # Returns a set of only this entry's immediate children
335 def children
336 nested_set_scope.scoped :conditions => {parent_column_name => self}
337 end
338
339 def is_descendant_of?(other)
340 other.left < self.left && self.left < other.right && same_scope?(other)
341 end
342
343 def is_or_is_descendant_of?(other)
344 other.left <= self.left && self.left < other.right && same_scope?(other)
345 end
346
347 def is_ancestor_of?(other)
348 self.left < other.left && other.left < self.right && same_scope?(other)
349 end
350
351 def is_or_is_ancestor_of?(other)
352 self.left <= other.left && other.left < self.right && same_scope?(other)
353 end
354
355 # Check if other model is in the same scope
356 def same_scope?(other)
357 Array(acts_as_nested_set_options[:scope]).all? do |attr|
358 self.send(attr) == other.send(attr)
359 end
360 end
361
362 # Find the first sibling to the left
363 def left_sibling
364 siblings.find(:first, :conditions => ["#{self.class.table_name}.#{quoted_left_column_name} < ?", left],
365 :order => "#{self.class.table_name}.#{quoted_left_column_name} DESC")
366 end
367
368 # Find the first sibling to the right
369 def right_sibling
370 siblings.find(:first, :conditions => ["#{self.class.table_name}.#{quoted_left_column_name} > ?", left])
371 end
372
373 # Shorthand method for finding the left sibling and moving to the left of it.
374 def move_left
375 move_to_left_of left_sibling
376 end
377
378 # Shorthand method for finding the right sibling and moving to the right of it.
379 def move_right
380 move_to_right_of right_sibling
381 end
382
383 # Move the node to the left of another node (you can pass id only)
384 def move_to_left_of(node)
385 move_to node, :left
386 end
387
388 # Move the node to the left of another node (you can pass id only)
389 def move_to_right_of(node)
390 move_to node, :right
391 end
392
393 # Move the node to the child of another node (you can pass id only)
394 def move_to_child_of(node)
395 move_to node, :child
396 end
397
398 # Move the node to root nodes
399 def move_to_root
400 move_to nil, :root
401 end
402
403 def move_possible?(target)
404 self != target && # Can't target self
405 same_scope?(target) && # can't be in different scopes
406 # !(left..right).include?(target.left..target.right) # this needs tested more
407 # detect impossible move
408 !((left <= target.left && right >= target.left) or (left <= target.right && right >= target.right))
409 end
410
411 def to_text
412 self_and_descendants.map do |node|
413 "#{'*'*(node.level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
414 end.join("\n")
415 end
416
417 protected
418
419 def without_self(scope)
420 scope.scoped :conditions => ["#{self.class.table_name}.#{self.class.primary_key} != ?", self]
421 end
422
423 # All nested set queries should use this nested_set_scope, which performs finds on
424 # the base ActiveRecord class, using the :scope declared in the acts_as_nested_set
425 # declaration.
426 def nested_set_scope
427 options = {:order => quoted_left_column_name}
428 scopes = Array(acts_as_nested_set_options[:scope])
429 options[:conditions] = scopes.inject({}) do |conditions,attr|
430 conditions.merge attr => self[attr]
431 end unless scopes.empty?
432 self.class.base_class.scoped options
433 end
434
435 # on creation, set automatically lft and rgt to the end of the tree
436 def set_default_left_and_right
437 maxright = nested_set_scope.maximum(right_column_name) || 0
438 # adds the new node to the right of all existing nodes
439 self[left_column_name] = maxright + 1
440 self[right_column_name] = maxright + 2
441 end
442
443 # Prunes a branch off of the tree, shifting all of the elements on the right
444 # back to the left so the counts still work.
445 def prune_from_tree
446 return if right.nil? || left.nil?
447 diff = right - left + 1
448
449 delete_method = acts_as_nested_set_options[:dependent] == :destroy ?
450 :destroy_all : :delete_all
451
452 self.class.base_class.transaction do
453 nested_set_scope.send(delete_method,
454 ["#{quoted_left_column_name} > ? AND #{quoted_right_column_name} < ?",
455 left, right]
456 )
457 nested_set_scope.update_all(
458 ["#{quoted_left_column_name} = (#{quoted_left_column_name} - ?)", diff],
459 ["#{quoted_left_column_name} >= ?", right]
460 )
461 nested_set_scope.update_all(
462 ["#{quoted_right_column_name} = (#{quoted_right_column_name} - ?)", diff],
463 ["#{quoted_right_column_name} >= ?", right]
464 )
465 end
466 end
467
468 # reload left, right, and parent
469 def reload_nested_set
470 reload(:select => "#{quoted_left_column_name}, " +
471 "#{quoted_right_column_name}, #{quoted_parent_column_name}")
472 end
473
474 def move_to(target, position)
475 raise ActiveRecord::ActiveRecordError, "You cannot move a new node" if self.new_record?
476 return if callback(:before_move) == false
477 transaction do
478 if target.is_a? self.class.base_class
479 target.reload_nested_set
480 elsif position != :root
481 # load object if node is not an object
482 target = nested_set_scope.find(target)
483 end
484 self.reload_nested_set
485
486 unless position == :root || move_possible?(target)
487 raise ActiveRecord::ActiveRecordError, "Impossible move, target node cannot be inside moved tree."
488 end
489
490 bound = case position
491 when :child; target[right_column_name]
492 when :left; target[left_column_name]
493 when :right; target[right_column_name] + 1
494 when :root; 1
495 else raise ActiveRecord::ActiveRecordError, "Position should be :child, :left, :right or :root ('#{position}' received)."
496 end
497
498 if bound > self[right_column_name]
499 bound = bound - 1
500 other_bound = self[right_column_name] + 1
501 else
502 other_bound = self[left_column_name] - 1
503 end
504
505 # there would be no change
506 return if bound == self[right_column_name] || bound == self[left_column_name]
507
508 # we have defined the boundaries of two non-overlapping intervals,
509 # so sorting puts both the intervals and their boundaries in order
510 a, b, c, d = [self[left_column_name], self[right_column_name], bound, other_bound].sort
511
512 new_parent = case position
513 when :child; target.id
514 when :root; nil
515 else target[parent_column_name]
516 end
517
518 self.class.base_class.update_all([
519 "#{quoted_left_column_name} = CASE " +
520 "WHEN #{quoted_left_column_name} BETWEEN :a AND :b " +
521 "THEN #{quoted_left_column_name} + :d - :b " +
522 "WHEN #{quoted_left_column_name} BETWEEN :c AND :d " +
523 "THEN #{quoted_left_column_name} + :a - :c " +
524 "ELSE #{quoted_left_column_name} END, " +
525 "#{quoted_right_column_name} = CASE " +
526 "WHEN #{quoted_right_column_name} BETWEEN :a AND :b " +
527 "THEN #{quoted_right_column_name} + :d - :b " +
528 "WHEN #{quoted_right_column_name} BETWEEN :c AND :d " +
529 "THEN #{quoted_right_column_name} + :a - :c " +
530 "ELSE #{quoted_right_column_name} END, " +
531 "#{quoted_parent_column_name} = CASE " +
532 "WHEN #{self.class.base_class.primary_key} = :id THEN :new_parent " +
533 "ELSE #{quoted_parent_column_name} END",
534 {:a => a, :b => b, :c => c, :d => d, :id => self.id, :new_parent => new_parent}
535 ], nested_set_scope.proxy_options[:conditions])
536 end
537 target.reload_nested_set if target
538 self.reload_nested_set
539 callback(:after_move)
540 end
541
542 end
543
544 end
545 end
546end
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/compatability.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/compatability.rb
new file mode 100644
index 0000000..2d11da3
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/compatability.rb
@@ -0,0 +1,29 @@
1# Rails <2.x doesn't define #except
2class Hash #:nodoc:
3 # Returns a new hash without the given keys.
4 def except(*keys)
5 clone.except!(*keys)
6 end unless method_defined?(:except)
7
8 # Replaces the hash without the given keys.
9 def except!(*keys)
10 keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
11 keys.each { |key| delete(key) }
12 self
13 end unless method_defined?(:except!)
14end
15
16# NamedScope is new to Rails 2.1
17unless defined? ActiveRecord::NamedScope
18 require 'awesome_nested_set/named_scope'
19 ActiveRecord::Base.class_eval do
20 include CollectiveIdea::NamedScope
21 end
22end
23
24# Rails 1.2.x doesn't define #quoted_table_name
25class ActiveRecord::Base #:nodoc:
26 def self.quoted_table_name
27 self.connection.quote_column_name(self.table_name)
28 end unless methods.include?('quoted_table_name')
29end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb
new file mode 100644
index 0000000..09c803f
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb
@@ -0,0 +1,40 @@
1module CollectiveIdea #:nodoc:
2 module Acts #:nodoc:
3 module NestedSet #:nodoc:
4 # This module provides some helpers for the model classes using acts_as_nested_set.
5 # It is included by default in all views.
6 #
7 module Helper
8 # Returns options for select.
9 # You can exclude some items from the tree.
10 # You can pass a block receiving an item and returning the string displayed in the select.
11 #
12 # == Params
13 # * +class_or_item+ - Class name or top level times
14 # * +mover+ - The item that is being move, used to exlude impossible moves
15 # * +&block+ - a block that will be used to display: { |item| ... item.name }
16 #
17 # == Usage
18 #
19 # <%= f.select :parent_id, nested_set_options(Category, @category) {|i|
20 # "#{'–' * i.level} #{i.name}"
21 # }) %>
22 #
23 def nested_set_options(class_or_item, mover = nil)
24 class_or_item = class_or_item.roots if class_or_item.is_a?(Class)
25 items = Array(class_or_item)
26 result = []
27 items.each do |root|
28 result += root.self_and_descendants.map do |i|
29 if mover.nil? || mover.new_record? || mover.move_possible?(i)
30 [yield(i), i.id]
31 end
32 end.compact
33 end
34 result
35 end
36
37 end
38 end
39 end
40end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/named_scope.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/named_scope.rb
new file mode 100644
index 0000000..1836498
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/named_scope.rb
@@ -0,0 +1,140 @@
1# Taken from Rails 2.1
2module CollectiveIdea #:nodoc:
3 module NamedScope #:nodoc:
4 # All subclasses of ActiveRecord::Base have two named_scopes:
5 # * <tt>all</tt>, which is similar to a <tt>find(:all)</tt> query, and
6 # * <tt>scoped</tt>, which allows for the creation of anonymous scopes, on the fly:
7 #
8 # Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)
9 #
10 # These anonymous scopes tend to be useful when procedurally generating complex queries, where passing
11 # intermediate values (scopes) around as first-class objects is convenient.
12 def self.included(base)
13 base.class_eval do
14 extend ClassMethods
15 named_scope :scoped, lambda { |scope| scope }
16 end
17 end
18
19 module ClassMethods #:nodoc:
20 def scopes
21 read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
22 end
23
24 # Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query,
25 # such as <tt>:conditions => {:color => :red}, :select => 'shirts.*', :include => :washing_instructions</tt>.
26 #
27 # class Shirt < ActiveRecord::Base
28 # named_scope :red, :conditions => {:color => 'red'}
29 # named_scope :dry_clean_only, :joins => :washing_instructions, :conditions => ['washing_instructions.dry_clean_only = ?', true]
30 # end
31 #
32 # The above calls to <tt>named_scope</tt> define class methods <tt>Shirt.red</tt> and <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>,
33 # in effect, represents the query <tt>Shirt.find(:all, :conditions => {:color => 'red'})</tt>.
34 #
35 # Unlike Shirt.find(...), however, the object returned by <tt>Shirt.red</tt> is not an Array; it resembles the association object
36 # constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.find(:first)</tt>, <tt>Shirt.red.count</tt>,
37 # <tt>Shirt.red.find(:all, :conditions => {:size => 'small'})</tt>. Also, just
38 # as with the association objects, name scopes acts like an Array, implementing Enumerable; <tt>Shirt.red.each(&block)</tt>,
39 # <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if Shirt.red really were an Array.
40 #
41 # These named scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.
42 # Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt> returns the number of garments
43 # for which these criteria obtain. Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
44 #
45 # All scopes are available as class methods on the ActiveRecord descendent upon which the scopes were defined. But they are also available to
46 # <tt>has_many</tt> associations. If,
47 #
48 # class Person < ActiveRecord::Base
49 # has_many :shirts
50 # end
51 #
52 # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
53 # only shirts.
54 #
55 # Named scopes can also be procedural.
56 #
57 # class Shirt < ActiveRecord::Base
58 # named_scope :colored, lambda { |color|
59 # { :conditions => { :color => color } }
60 # }
61 # end
62 #
63 # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
64 #
65 # Named scopes can also have extensions, just as with <tt>has_many</tt> declarations:
66 #
67 # class Shirt < ActiveRecord::Base
68 # named_scope :red, :conditions => {:color => 'red'} do
69 # def dom_id
70 # 'red_shirts'
71 # end
72 # end
73 # end
74 #
75 #
76 # For testing complex named scopes, you can examine the scoping options using the
77 # <tt>proxy_options</tt> method on the proxy itself.
78 #
79 # class Shirt < ActiveRecord::Base
80 # named_scope :colored, lambda { |color|
81 # { :conditions => { :color => color } }
82 # }
83 # end
84 #
85 # expected_options = { :conditions => { :colored => 'red' } }
86 # assert_equal expected_options, Shirt.colored('red').proxy_options
87 def named_scope(name, options = {}, &block)
88 scopes[name] = lambda do |parent_scope, *args|
89 Scope.new(parent_scope, case options
90 when Hash
91 options
92 when Proc
93 options.call(*args)
94 end, &block)
95 end
96 (class << self; self end).instance_eval do
97 define_method name do |*args|
98 scopes[name].call(self, *args)
99 end
100 end
101 end
102 end
103
104 class Scope #:nodoc:
105 attr_reader :proxy_scope, :proxy_options
106 [].methods.each { |m| delegate m, :to => :proxy_found unless m =~ /(^__|^nil\?|^send|class|extend|find|count|sum|average|maximum|minimum|paginate)/ }
107 delegate :scopes, :with_scope, :to => :proxy_scope
108
109 def initialize(proxy_scope, options, &block)
110 [options[:extend]].flatten.each { |extension| extend extension } if options[:extend]
111 extend Module.new(&block) if block_given?
112 @proxy_scope, @proxy_options = proxy_scope, options.except(:extend)
113 end
114
115 def reload
116 load_found; self
117 end
118
119 protected
120 def proxy_found
121 @found || load_found
122 end
123
124 private
125 def method_missing(method, *args, &block)
126 if scopes.include?(method)
127 scopes[method].call(self, *args)
128 else
129 with_scope :find => proxy_options do
130 proxy_scope.send(method, *args, &block)
131 end
132 end
133 end
134
135 def load_found
136 @found = find(:all)
137 end
138 end
139 end
140end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/rails/init.rb b/vendor/plugins/awesome_nested_set/rails/init.rb
new file mode 100644
index 0000000..e0a4e8b
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/rails/init.rb
@@ -0,0 +1,13 @@
1require 'awesome_nested_set/compatability'
2require 'awesome_nested_set'
3
4ActiveRecord::Base.class_eval do
5 include CollectiveIdea::Acts::NestedSet
6end
7
8if defined?(ActionView)
9 require 'awesome_nested_set/helper'
10 ActionView::Base.class_eval do
11 include CollectiveIdea::Acts::NestedSet::Helper
12 end
13end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/test/awesome_nested_set/helper_test.rb b/vendor/plugins/awesome_nested_set/test/awesome_nested_set/helper_test.rb
new file mode 100644
index 0000000..6122a0e
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/test/awesome_nested_set/helper_test.rb
@@ -0,0 +1,41 @@
1require File.dirname(__FILE__) + '/../test_helper'
2
3module CollectiveIdea
4 module Acts #:nodoc:
5 module NestedSet #:nodoc:
6 class AwesomeNestedSetTest < Test::Unit::TestCase
7 include Helper
8 fixtures :categories
9
10 def test_nested_set_options
11 expected = [
12 [" Top Level", 1],
13 ["- Child 1", 2],
14 ['- Child 2', 3],
15 ['-- Child 2.1', 4],
16 ['- Child 3', 5],
17 [" Top Level 2", 6]
18 ]
19 actual = nested_set_options(Category) do |c|
20 "#{'-' * c.level} #{c.name}"
21 end
22 assert_equal expected, actual
23 end
24
25 def test_nested_set_options_with_mover
26 expected = [
27 [" Top Level", 1],
28 ["- Child 1", 2],
29 ['- Child 3', 5],
30 [" Top Level 2", 6]
31 ]
32 actual = nested_set_options(Category, categories(:child_2)) do |c|
33 "#{'-' * c.level} #{c.name}"
34 end
35 assert_equal expected, actual
36 end
37
38 end
39 end
40 end
41end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/test/awesome_nested_set_test.rb b/vendor/plugins/awesome_nested_set/test/awesome_nested_set_test.rb
new file mode 100644
index 0000000..5252d80
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/test/awesome_nested_set_test.rb
@@ -0,0 +1,603 @@
1require File.dirname(__FILE__) + '/test_helper'
2
3class Note < ActiveRecord::Base
4 acts_as_nested_set :scope => [:notable_id, :notable_type]
5end
6
7class AwesomeNestedSetTest < Test::Unit::TestCase
8
9 class Default < ActiveRecord::Base
10 acts_as_nested_set
11 set_table_name 'categories'
12 end
13 class Scoped < ActiveRecord::Base
14 acts_as_nested_set :scope => :organization
15 set_table_name 'categories'
16 end
17
18 def test_left_column_default
19 assert_equal 'lft', Default.acts_as_nested_set_options[:left_column]
20 end
21
22 def test_right_column_default
23 assert_equal 'rgt', Default.acts_as_nested_set_options[:right_column]
24 end
25
26 def test_parent_column_default
27 assert_equal 'parent_id', Default.acts_as_nested_set_options[:parent_column]
28 end
29
30 def test_scope_default
31 assert_nil Default.acts_as_nested_set_options[:scope]
32 end
33
34 def test_left_column_name
35 assert_equal 'lft', Default.left_column_name
36 assert_equal 'lft', Default.new.left_column_name
37 end
38
39 def test_right_column_name
40 assert_equal 'rgt', Default.right_column_name
41 assert_equal 'rgt', Default.new.right_column_name
42 end
43
44 def test_parent_column_name
45 assert_equal 'parent_id', Default.parent_column_name
46 assert_equal 'parent_id', Default.new.parent_column_name
47 end
48
49 def test_quoted_left_column_name
50 quoted = Default.connection.quote_column_name('lft')
51 assert_equal quoted, Default.quoted_left_column_name
52 assert_equal quoted, Default.new.quoted_left_column_name
53 end
54
55 def test_quoted_right_column_name
56 quoted = Default.connection.quote_column_name('rgt')
57 assert_equal quoted, Default.quoted_right_column_name
58 assert_equal quoted, Default.new.quoted_right_column_name
59 end
60
61 def test_left_column_protected_from_assignment
62 assert_raises(ActiveRecord::ActiveRecordError) { Category.new.lft = 1 }
63 end
64
65 def test_right_column_protected_from_assignment
66 assert_raises(ActiveRecord::ActiveRecordError) { Category.new.rgt = 1 }
67 end
68
69 def test_parent_column_protected_from_assignment
70 assert_raises(ActiveRecord::ActiveRecordError) { Category.new.parent_id = 1 }
71 end
72
73 def test_colums_protected_on_initialize
74 c = Category.new(:lft => 1, :rgt => 2, :parent_id => 3)
75 assert_nil c.lft
76 assert_nil c.rgt
77 assert_nil c.parent_id
78 end
79
80 def test_scoped_appends_id
81 assert_equal :organization_id, Scoped.acts_as_nested_set_options[:scope]
82 end
83
84 def test_roots_class_method
85 assert_equal Category.find_all_by_parent_id(nil), Category.roots
86 end
87
88 def test_root_class_method
89 assert_equal categories(:top_level), Category.root
90 end
91
92 def test_root
93 assert_equal categories(:top_level), categories(:child_3).root
94 end
95
96 def test_root?
97 assert categories(:top_level).root?
98 assert categories(:top_level_2).root?
99 end
100
101 def test_leaves_class_method
102 assert_equal Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1"), Category.leaves
103 assert_equal Category.leaves.count, 4
104 assert (Category.leaves.include? categories(:child_1))
105 assert (Category.leaves.include? categories(:child_2_1))
106 assert (Category.leaves.include? categories(:child_3))
107 assert (Category.leaves.include? categories(:top_level_2))
108 end
109
110 def test_leaf
111 assert categories(:child_1).leaf?
112 assert categories(:child_2_1).leaf?
113 assert categories(:child_3).leaf?
114 assert categories(:top_level_2).leaf?
115
116 assert !categories(:top_level).leaf?
117 assert !categories(:child_2).leaf?
118 end
119
120 def test_parent
121 assert_equal categories(:child_2), categories(:child_2_1).parent
122 end
123
124 def test_self_and_ancestors
125 child = categories(:child_2_1)
126 self_and_ancestors = [categories(:top_level), categories(:child_2), child]
127 assert_equal self_and_ancestors, child.self_and_ancestors
128 end
129
130 def test_ancestors
131 child = categories(:child_2_1)
132 ancestors = [categories(:top_level), categories(:child_2)]
133 assert_equal ancestors, child.ancestors
134 end
135
136 def test_self_and_siblings
137 child = categories(:child_2)
138 self_and_siblings = [categories(:child_1), child, categories(:child_3)]
139 assert_equal self_and_siblings, child.self_and_siblings
140 assert_nothing_raised do
141 tops = [categories(:top_level), categories(:top_level_2)]
142 assert_equal tops, categories(:top_level).self_and_siblings
143 end
144 end
145
146 def test_siblings
147 child = categories(:child_2)
148 siblings = [categories(:child_1), categories(:child_3)]
149 assert_equal siblings, child.siblings
150 end
151
152 def test_leaves
153 leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3), categories(:top_level_2)]
154 assert categories(:top_level).leaves, leaves
155 end
156
157 def test_level
158 assert_equal 0, categories(:top_level).level
159 assert_equal 1, categories(:child_1).level
160 assert_equal 2, categories(:child_2_1).level
161 end
162
163 def test_has_children?
164 assert categories(:child_2_1).children.empty?
165 assert !categories(:child_2).children.empty?
166 assert !categories(:top_level).children.empty?
167 end
168
169 def test_self_and_descendents
170 parent = categories(:top_level)
171 self_and_descendants = [parent, categories(:child_1), categories(:child_2),
172 categories(:child_2_1), categories(:child_3)]
173 assert_equal self_and_descendants, parent.self_and_descendants
174 assert_equal self_and_descendants, parent.self_and_descendants.count
175 end
176
177 def test_descendents
178 lawyers = Category.create!(:name => "lawyers")
179 us = Category.create!(:name => "United States")
180 us.move_to_child_of(lawyers)
181 patent = Category.create!(:name => "Patent Law")
182 patent.move_to_child_of(us)
183 lawyers.reload
184
185 assert_equal 1, lawyers.children.size
186 assert_equal 1, us.children.size
187 assert_equal 2, lawyers.descendants.size
188 end
189
190 def test_self_and_descendents
191 parent = categories(:top_level)
192 descendants = [categories(:child_1), categories(:child_2),
193 categories(:child_2_1), categories(:child_3)]
194 assert_equal descendants, parent.descendants
195 end
196
197 def test_children
198 category = categories(:top_level)
199 category.children.each {|c| assert_equal category.id, c.parent_id }
200 end
201
202 def test_is_or_is_ancestor_of?
203 assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_1))
204 assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1))
205 assert categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1))
206 assert !categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2))
207 assert !categories(:child_1).is_or_is_ancestor_of?(categories(:child_2))
208 assert categories(:child_1).is_or_is_ancestor_of?(categories(:child_1))
209 end
210
211 def test_is_ancestor_of?
212 assert categories(:top_level).is_ancestor_of?(categories(:child_1))
213 assert categories(:top_level).is_ancestor_of?(categories(:child_2_1))
214 assert categories(:child_2).is_ancestor_of?(categories(:child_2_1))
215 assert !categories(:child_2_1).is_ancestor_of?(categories(:child_2))
216 assert !categories(:child_1).is_ancestor_of?(categories(:child_2))
217 assert !categories(:child_1).is_ancestor_of?(categories(:child_1))
218 end
219
220 def test_is_or_is_ancestor_of_with_scope
221 root = Scoped.root
222 child = root.children.first
223 assert root.is_or_is_ancestor_of?(child)
224 child.update_attribute :organization_id, 'different'
225 assert !root.is_or_is_ancestor_of?(child)
226 end
227
228 def test_is_or_is_descendant_of?
229 assert categories(:child_1).is_or_is_descendant_of?(categories(:top_level))
230 assert categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level))
231 assert categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2))
232 assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1))
233 assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_1))
234 assert categories(:child_1).is_or_is_descendant_of?(categories(:child_1))
235 end
236
237 def test_is_descendant_of?
238 assert categories(:child_1).is_descendant_of?(categories(:top_level))
239 assert categories(:child_2_1).is_descendant_of?(categories(:top_level))
240 assert categories(:child_2_1).is_descendant_of?(categories(:child_2))
241 assert !categories(:child_2).is_descendant_of?(categories(:child_2_1))
242 assert !categories(:child_2).is_descendant_of?(categories(:child_1))
243 assert !categories(:child_1).is_descendant_of?(categories(:child_1))
244 end
245
246 def test_is_or_is_descendant_of_with_scope
247 root = Scoped.root
248 child = root.children.first
249 assert child.is_or_is_descendant_of?(root)
250 child.update_attribute :organization_id, 'different'
251 assert !child.is_or_is_descendant_of?(root)
252 end
253
254 def test_same_scope?
255 root = Scoped.root
256 child = root.children.first
257 assert child.same_scope?(root)
258 child.update_attribute :organization_id, 'different'
259 assert !child.same_scope?(root)
260 end
261
262 def test_left_sibling
263 assert_equal categories(:child_1), categories(:child_2).left_sibling
264 assert_equal categories(:child_2), categories(:child_3).left_sibling
265 end
266
267 def test_left_sibling_of_root
268 assert_nil categories(:top_level).left_sibling
269 end
270
271 def test_left_sibling_without_siblings
272 assert_nil categories(:child_2_1).left_sibling
273 end
274
275 def test_left_sibling_of_leftmost_node
276 assert_nil categories(:child_1).left_sibling
277 end
278
279 def test_right_sibling
280 assert_equal categories(:child_3), categories(:child_2).right_sibling
281 assert_equal categories(:child_2), categories(:child_1).right_sibling
282 end
283
284 def test_right_sibling_of_root
285 assert_equal categories(:top_level_2), categories(:top_level).right_sibling
286 assert_nil categories(:top_level_2).right_sibling
287 end
288
289 def test_right_sibling_without_siblings
290 assert_nil categories(:child_2_1).right_sibling
291 end
292
293 def test_right_sibling_of_rightmost_node
294 assert_nil categories(:child_3).right_sibling
295 end
296
297 def test_move_left
298 categories(:child_2).move_left
299 assert_nil categories(:child_2).left_sibling
300 assert_equal categories(:child_1), categories(:child_2).right_sibling
301 assert Category.valid?
302 end
303
304 def test_move_right
305 categories(:child_2).move_right
306 assert_nil categories(:child_2).right_sibling
307 assert_equal categories(:child_3), categories(:child_2).left_sibling
308 assert Category.valid?
309 end
310
311 def test_move_to_left_of
312 categories(:child_3).move_to_left_of(categories(:child_1))
313 assert_nil categories(:child_3).left_sibling
314 assert_equal categories(:child_1), categories(:child_3).right_sibling
315 assert Category.valid?
316 end
317
318 def test_move_to_right_of
319 categories(:child_1).move_to_right_of(categories(:child_3))
320 assert_nil categories(:child_1).right_sibling
321 assert_equal categories(:child_3), categories(:child_1).left_sibling
322 assert Category.valid?
323 end
324
325 def test_move_to_root
326 categories(:child_2).move_to_root
327 assert_nil categories(:child_2).parent
328 assert_equal 0, categories(:child_2).level
329 assert_equal 1, categories(:child_2_1).level
330 assert_equal 1, categories(:child_2).left
331 assert_equal 4, categories(:child_2).right
332 assert Category.valid?
333 end
334
335 def test_move_to_child_of
336 categories(:child_1).move_to_child_of(categories(:child_3))
337 assert_equal categories(:child_3).id, categories(:child_1).parent_id
338 assert Category.valid?
339 end
340
341 def test_move_to_child_of_appends_to_end
342 child = Category.create! :name => 'New Child'
343 child.move_to_child_of categories(:top_level)
344 assert_equal child, categories(:top_level).children.last
345 end
346
347 def test_subtree_move_to_child_of
348 assert_equal 4, categories(:child_2).left
349 assert_equal 7, categories(:child_2).right
350
351 assert_equal 2, categories(:child_1).left
352 assert_equal 3, categories(:child_1).right
353
354 categories(:child_2).move_to_child_of(categories(:child_1))
355 assert Category.valid?
356 assert_equal categories(:child_1).id, categories(:child_2).parent_id
357
358 assert_equal 3, categories(:child_2).left
359 assert_equal 6, categories(:child_2).right
360 assert_equal 2, categories(:child_1).left
361 assert_equal 7, categories(:child_1).right
362 end
363
364 def test_slightly_difficult_move_to_child_of
365 assert_equal 11, categories(:top_level_2).left
366 assert_equal 12, categories(:top_level_2).right
367
368 # create a new top-level node and move single-node top-level tree inside it.
369 new_top = Category.create(:name => 'New Top')
370 assert_equal 13, new_top.left
371 assert_equal 14, new_top.right
372
373 categories(:top_level_2).move_to_child_of(new_top)
374
375 assert Category.valid?
376 assert_equal new_top.id, categories(:top_level_2).parent_id
377
378 assert_equal 12, categories(:top_level_2).left
379 assert_equal 13, categories(:top_level_2).right
380 assert_equal 11, new_top.left
381 assert_equal 14, new_top.right
382 end
383
384 def test_difficult_move_to_child_of
385 assert_equal 1, categories(:top_level).left
386 assert_equal 10, categories(:top_level).right
387 assert_equal 5, categories(:child_2_1).left
388 assert_equal 6, categories(:child_2_1).right
389
390 # create a new top-level node and move an entire top-level tree inside it.
391 new_top = Category.create(:name => 'New Top')
392 categories(:top_level).move_to_child_of(new_top)
393 categories(:child_2_1).reload
394 assert Category.valid?
395 assert_equal new_top.id, categories(:top_level).parent_id
396
397 assert_equal 4, categories(:top_level).left
398 assert_equal 13, categories(:top_level).right
399 assert_equal 8, categories(:child_2_1).left
400 assert_equal 9, categories(:child_2_1).right
401 end
402
403 #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent
404 def test_move_to_child_more_than_once_per_parent_rebuild
405 root1 = Category.create(:name => 'Root1')
406 root2 = Category.create(:name => 'Root2')
407 root3 = Category.create(:name => 'Root3')
408
409 root2.move_to_child_of root1
410 root3.move_to_child_of root1
411
412 output = Category.roots.last.to_text
413 Category.update_all('lft = null, rgt = null')
414 Category.rebuild!
415
416 assert_equal Category.roots.last.to_text, output
417 end
418
419 # doing move_to_child twice onto same parent from the furthest right first
420 def test_move_to_child_more_than_once_per_parent_outside_in
421 node1 = Category.create(:name => 'Node-1')
422 node2 = Category.create(:name => 'Node-2')
423 node3 = Category.create(:name => 'Node-3')
424
425 node2.move_to_child_of node1
426 node3.move_to_child_of node1
427
428 output = Category.roots.last.to_text
429 Category.update_all('lft = null, rgt = null')
430 Category.rebuild!
431
432 assert_equal Category.roots.last.to_text, output
433 end
434
435
436 def test_valid_with_null_lefts
437 assert Category.valid?
438 Category.update_all('lft = null')
439 assert !Category.valid?
440 end
441
442 def test_valid_with_null_rights
443 assert Category.valid?
444 Category.update_all('rgt = null')
445 assert !Category.valid?
446 end
447
448 def test_valid_with_missing_intermediate_node
449 # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.
450 assert Category.valid?
451 Category.delete(categories(:child_2).id)
452 assert Category.valid?
453 end
454
455 def test_valid_with_overlapping_and_rights
456 assert Category.valid?
457 categories(:top_level_2)['lft'] = 0
458 categories(:top_level_2).save
459 assert !Category.valid?
460 end
461
462 def test_rebuild
463 assert Category.valid?
464 before_text = Category.root.to_text
465 Category.update_all('lft = null, rgt = null')
466 Category.rebuild!
467 assert Category.valid?
468 assert_equal before_text, Category.root.to_text
469 end
470
471 def test_move_possible_for_sibling
472 assert categories(:child_2).move_possible?(categories(:child_1))
473 end
474
475 def test_move_not_possible_to_self
476 assert !categories(:top_level).move_possible?(categories(:top_level))
477 end
478
479 def test_move_not_possible_to_parent
480 categories(:top_level).descendants.each do |descendant|
481 assert !categories(:top_level).move_possible?(descendant)
482 assert descendant.move_possible?(categories(:top_level))
483 end
484 end
485
486 def test_is_or_is_ancestor_of?
487 [:child_1, :child_2, :child_2_1, :child_3].each do |c|
488 assert categories(:top_level).is_or_is_ancestor_of?(categories(c))
489 end
490 assert !categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2))
491 end
492
493 def test_left_and_rights_valid_with_blank_left
494 assert Category.left_and_rights_valid?
495 categories(:child_2)[:lft] = nil
496 categories(:child_2).save(false)
497 assert !Category.left_and_rights_valid?
498 end
499
500 def test_left_and_rights_valid_with_blank_right
501 assert Category.left_and_rights_valid?
502 categories(:child_2)[:rgt] = nil
503 categories(:child_2).save(false)
504 assert !Category.left_and_rights_valid?
505 end
506
507 def test_left_and_rights_valid_with_equal
508 assert Category.left_and_rights_valid?
509 categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]
510 categories(:top_level_2).save(false)
511 assert !Category.left_and_rights_valid?
512 end
513
514 def test_left_and_rights_valid_with_left_equal_to_parent
515 assert Category.left_and_rights_valid?
516 categories(:child_2)[:lft] = categories(:top_level)[:lft]
517 categories(:child_2).save(false)
518 assert !Category.left_and_rights_valid?
519 end
520
521 def test_left_and_rights_valid_with_right_equal_to_parent
522 assert Category.left_and_rights_valid?
523 categories(:child_2)[:rgt] = categories(:top_level)[:rgt]
524 categories(:child_2).save(false)
525 assert !Category.left_and_rights_valid?
526 end
527
528 def test_moving_dirty_objects_doesnt_invalidate_tree
529 r1 = Category.create
530 r2 = Category.create
531 r3 = Category.create
532 r4 = Category.create
533 nodes = [r1, r2, r3, r4]
534
535 r2.move_to_child_of(r1)
536 assert Category.valid?
537
538 r3.move_to_child_of(r1)
539 assert Category.valid?
540
541 r4.move_to_child_of(r2)
542 assert Category.valid?
543 end
544
545 def test_multi_scoped_no_duplicates_for_columns?
546 assert_nothing_raised do
547 Note.no_duplicates_for_columns?
548 end
549 end
550
551 def test_multi_scoped_all_roots_valid?
552 assert_nothing_raised do
553 Note.all_roots_valid?
554 end
555 end
556
557 def test_multi_scoped
558 note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')
559 note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')
560 note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')
561
562 assert_equal [note1, note2], note1.self_and_siblings
563 assert_equal [note3], note3.self_and_siblings
564 end
565
566 def test_multi_scoped_rebuild
567 root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')
568 child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')
569 child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')
570
571 child1.move_to_child_of root
572 child2.move_to_child_of root
573
574 Note.update_all('lft = null, rgt = null')
575 Note.rebuild!
576
577 assert_equal Note.roots.find_by_body('A'), root
578 assert_equal [child1, child2], Note.roots.find_by_body('A').children
579 end
580
581 def test_same_scope_with_multi_scopes
582 assert_nothing_raised do
583 notes(:scope1).same_scope?(notes(:child_1))
584 end
585 assert notes(:scope1).same_scope?(notes(:child_1))
586 assert notes(:child_1).same_scope?(notes(:scope1))
587 assert !notes(:scope1).same_scope?(notes(:scope2))
588 end
589
590 def test_quoting_of_multi_scope_column_names
591 assert_equal ["\"notable_id\"", "\"notable_type\""], Note.quoted_scope_column_names
592 end
593
594 def test_equal_in_same_scope
595 assert_equal notes(:scope1), notes(:scope1)
596 assert_not_equal notes(:scope1), notes(:child_1)
597 end
598
599 def test_equal_in_different_scopes
600 assert_not_equal notes(:scope1), notes(:scope2)
601 end
602
603end
diff --git a/vendor/plugins/awesome_nested_set/test/fixtures/categories.yml b/vendor/plugins/awesome_nested_set/test/fixtures/categories.yml
new file mode 100644
index 0000000..bc8e078
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/test/fixtures/categories.yml
@@ -0,0 +1,34 @@
1top_level:
2 id: 1
3 name: Top Level
4 lft: 1
5 rgt: 10
6child_1:
7 id: 2
8 name: Child 1
9 parent_id: 1
10 lft: 2
11 rgt: 3
12child_2:
13 id: 3
14 name: Child 2
15 parent_id: 1
16 lft: 4
17 rgt: 7
18child_2_1:
19 id: 4
20 name: Child 2.1
21 parent_id: 3
22 lft: 5
23 rgt: 6
24child_3:
25 id: 5
26 name: Child 3
27 parent_id: 1
28 lft: 8
29 rgt: 9
30top_level_2:
31 id: 6
32 name: Top Level 2
33 lft: 11
34 rgt: 12
diff --git a/vendor/plugins/awesome_nested_set/test/fixtures/category.rb b/vendor/plugins/awesome_nested_set/test/fixtures/category.rb
new file mode 100644
index 0000000..506b0da
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/test/fixtures/category.rb
@@ -0,0 +1,15 @@
1class Category < ActiveRecord::Base
2 acts_as_nested_set
3
4 def to_s
5 name
6 end
7
8 def recurse &block
9 block.call self, lambda{
10 self.children.each do |child|
11 child.recurse &block
12 end
13 }
14 end
15end \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/test/fixtures/departments.yml b/vendor/plugins/awesome_nested_set/test/fixtures/departments.yml
new file mode 100644
index 0000000..e50a944
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/test/fixtures/departments.yml
@@ -0,0 +1,3 @@
1top:
2 id: 1
3 name: Top \ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/test/fixtures/notes.yml b/vendor/plugins/awesome_nested_set/test/fixtures/notes.yml
new file mode 100644
index 0000000..004a533
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/test/fixtures/notes.yml
@@ -0,0 +1,38 @@
1scope1:
2 id: 1
3 body: Top Level
4 lft: 1
5 rgt: 10
6 notable_id: 1
7 notable_type: Category
8child_1:
9 id: 2
10 body: Child 1
11 parent_id: 1
12 lft: 2
13 rgt: 3
14 notable_id: 1
15 notable_type: Category
16child_2:
17 id: 3
18 body: Child 2
19 parent_id: 1
20 lft: 4
21 rgt: 7
22 notable_id: 1
23 notable_type: Category
24child_3:
25 id: 4
26 body: Child 3
27 parent_id: 1
28 lft: 8
29 rgt: 9
30 notable_id: 1
31 notable_type: Category
32scope2:
33 id: 5
34 body: Top Level 2
35 lft: 1
36 rgt: 2
37 notable_id: 1
38 notable_type: Departments
diff --git a/vendor/plugins/awesome_nested_set/test/test_helper.rb b/vendor/plugins/awesome_nested_set/test/test_helper.rb
new file mode 100644
index 0000000..6939822
--- /dev/null
+++ b/vendor/plugins/awesome_nested_set/test/test_helper.rb
@@ -0,0 +1,31 @@
1$:.unshift(File.dirname(__FILE__) + '/../lib')
2plugin_test_dir = File.dirname(__FILE__)
3
4require 'rubygems'
5require 'test/unit'
6require 'multi_rails_init'
7# gem 'activerecord', '>= 2.0'
8require 'active_record'
9require 'action_controller'
10require 'action_view'
11require 'active_record/fixtures'
12
13require plugin_test_dir + '/../init.rb'
14
15ActiveRecord::Base.logger = Logger.new(plugin_test_dir + "/debug.log")
16
17ActiveRecord::Base.configurations = YAML::load(IO.read(plugin_test_dir + "/db/database.yml"))
18ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite3mem")
19ActiveRecord::Migration.verbose = false
20load(File.join(plugin_test_dir, "db", "schema.rb"))
21
22Dir["#{plugin_test_dir}/fixtures/*.rb"].each {|file| require file }
23
24
25class Test::Unit::TestCase #:nodoc:
26 self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
27 self.use_transactional_fixtures = true
28 self.use_instantiated_fixtures = false
29
30 fixtures :categories, :notes, :departments
31end \ No newline at end of file