diff --git a/lib/plugins/awesome_nested_set/.travis.yml b/lib/plugins/awesome_nested_set/.travis.yml index c821cce8d..23152319f 100644 --- a/lib/plugins/awesome_nested_set/.travis.yml +++ b/lib/plugins/awesome_nested_set/.travis.yml @@ -1,17 +1,22 @@ -before_install: gem install bundler --pre +language: ruby notifications: email: - parndt@gmail.com +script: bundle exec rspec spec env: - DB=sqlite3 - DB=sqlite3mem + - DB=postgresql + - DB=mysql rvm: - - 1.8.7 - - 1.9.2 + - 2.0.0 - 1.9.3 - - rbx - - jruby + - 1.8.7 + - rbx-19mode + - jruby-19mode + - rbx-18mode + - jruby-18mode gemfile: - gemfiles/Gemfile.rails-3.0.rb - gemfiles/Gemfile.rails-3.1.rb - - gemfiles/Gemfile.rails-3.2.rb \ No newline at end of file + - gemfiles/Gemfile.rails-3.2.rb diff --git a/lib/plugins/awesome_nested_set/CHANGELOG b/lib/plugins/awesome_nested_set/CHANGELOG index 18fd59d55..a805bfb17 100644 --- a/lib/plugins/awesome_nested_set/CHANGELOG +++ b/lib/plugins/awesome_nested_set/CHANGELOG @@ -1,3 +1,8 @@ +2.1.6 +* Fixed rebuild! when there is a default_scope with order [Adrian Serafin] +* Testing with stable bundler, ruby 2.0, MySQL and PostgreSQL [Philip Arndt] +* Optimized move_to for large trees [ericsmith66] + 2.1.5 * Worked around issues where AR#association wasn't present on Rails 3.0.x. [Philip Arndt] * Adds option 'order_column' which defaults to 'left_column_name'. [gudata] diff --git a/lib/plugins/awesome_nested_set/Rakefile b/lib/plugins/awesome_nested_set/Rakefile index b913bc5e2..d5c79129a 100644 --- a/lib/plugins/awesome_nested_set/Rakefile +++ b/lib/plugins/awesome_nested_set/Rakefile @@ -4,11 +4,15 @@ require 'rubygems' require 'bundler/setup' require 'awesome_nested_set/version' -require "rspec/core/rake_task" -RSpec::Core::RakeTask.new(:spec) - task :default => :spec +task :spec do + %w(3.0 3.1 3.2).each do |rails_version| + puts "\n" + (cmd = "BUNDLE_GEMFILE='gemfiles/Gemfile.rails-#{rails_version}.rb' bundle exec rspec spec") + system cmd + end +end + task :build do system "gem build awesome_nested_set.gemspec" end diff --git a/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec b/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec index 528e37b44..f30dcc611 100644 --- a/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec +++ b/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec @@ -1,7 +1,5 @@ # -*- encoding: utf-8 -*- -lib = File.expand_path('../lib/', __FILE__) -$:.unshift lib unless $:.include?(lib) -require 'awesome_nested_set/version' +require File.expand_path('../lib/awesome_nested_set/version', __FILE__) Gem::Specification.new do |s| s.name = %q{awesome_nested_set} @@ -9,15 +7,18 @@ Gem::Specification.new do |s| s.authors = ["Brandon Keepers", "Daniel Morrison", "Philip Arndt"] s.description = %q{An awesome nested set implementation for Active Record} s.email = %q{info@collectiveidea.com} - s.extra_rdoc_files = [ - "README.rdoc" - ] + s.extra_rdoc_files = %w[README.rdoc] s.files = Dir.glob("lib/**/*") + %w(MIT-LICENSE README.rdoc CHANGELOG) s.homepage = %q{http://github.com/collectiveidea/awesome_nested_set} s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"] s.require_paths = ["lib"] s.rubygems_version = %q{1.3.6} s.summary = %q{An awesome nested set implementation for Active Record} + s.license = %q{MIT} + s.add_runtime_dependency 'activerecord', '>= 3.0.0' - s.add_development_dependency 'rspec-rails', '~> 2.8' + + s.add_development_dependency 'rspec-rails', '~> 2.12' + s.add_development_dependency 'rake', '~> 10' + s.add_development_dependency 'combustion', '>= 0.3.3' end diff --git a/lib/plugins/awesome_nested_set/init.rb b/lib/plugins/awesome_nested_set/init.rb deleted file mode 100644 index 8e2cf36ef..000000000 --- a/lib/plugins/awesome_nested_set/init.rb +++ /dev/null @@ -1 +0,0 @@ -require File.dirname(__FILE__) + '/lib/awesome_nested_set' diff --git a/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb b/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb index 797ce2ab5..c831c48fc 100644 --- a/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb +++ b/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb @@ -181,34 +181,37 @@ module CollectiveIdea #:nodoc: # Rebuilds the left & rights if unset or invalid. # Also very useful for converting from acts_as_tree. def rebuild!(validate_nodes = true) - # Don't rebuild a valid tree. - return true if valid? + # default_scope with order may break database queries so we do all operation without scope + unscoped do + # Don't rebuild a valid tree. + return true if valid? - scope = lambda{|node|} - if acts_as_nested_set_options[: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))} " + scope = lambda{|node|} + if acts_as_nested_set_options[: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 = {} + end + indices = {} - set_left_and_rights = lambda do |node| - # set left - node[left_column_name] = indices[scope.call(node)] += 1 - # find - where(["#{quoted_parent_column_full_name} = ? #{scope.call(node)}", node]).order("#{quoted_left_column_full_name}, #{quoted_right_column_full_name}, id").each{|n| set_left_and_rights.call(n) } - # set right - node[right_column_name] = indices[scope.call(node)] += 1 - node.save!(:validate => validate_nodes) - end + set_left_and_rights = lambda do |node| + # set left + node[left_column_name] = indices[scope.call(node)] += 1 + # find + where(["#{quoted_parent_column_full_name} = ? #{scope.call(node)}", node]).order("#{quoted_left_column_full_name}, #{quoted_right_column_full_name}, id").each{|n| set_left_and_rights.call(n) } + # set right + node[right_column_name] = indices[scope.call(node)] += 1 + node.save!(:validate => validate_nodes) + end - # Find root node(s) - root_nodes = where("#{quoted_parent_column_full_name} IS NULL").order("#{quoted_left_column_full_name}, #{quoted_right_column_full_name}, id").each do |root_node| - # setup index for this scope - indices[scope.call(root_node)] ||= 0 - set_left_and_rights.call(root_node) + # Find root node(s) + root_nodes = where("#{quoted_parent_column_full_name} IS NULL").order("#{quoted_left_column_full_name}, #{quoted_right_column_full_name}, 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 end @@ -590,8 +593,6 @@ module CollectiveIdea #:nodoc: ["#{quoted_right_column_name} = (#{quoted_right_column_name} - ?)", diff] ) - # Reload is needed because children may have updated their parent (self) during deletion. - reload # Don't allow multiple calls to destroy to corrupt the set self.skip_before_destroy = true end @@ -654,7 +655,27 @@ module CollectiveIdea #:nodoc: else target[parent_column_name] end - self.nested_set_scope.update_all([ + where_statement = ["not (#{quoted_left_column_name} = CASE " + + "WHEN #{quoted_left_column_name} BETWEEN :a AND :b " + + "THEN #{quoted_left_column_name} + :d - :b " + + "WHEN #{quoted_left_column_name} BETWEEN :c AND :d " + + "THEN #{quoted_left_column_name} + :a - :c " + + "ELSE #{quoted_left_column_name} END AND " + + "#{quoted_right_column_name} = CASE " + + "WHEN #{quoted_right_column_name} BETWEEN :a AND :b " + + "THEN #{quoted_right_column_name} + :d - :b " + + "WHEN #{quoted_right_column_name} BETWEEN :c AND :d " + + "THEN #{quoted_right_column_name} + :a - :c " + + "ELSE #{quoted_right_column_name} END AND " + + "#{quoted_parent_column_name} = CASE " + + "WHEN #{self.class.base_class.primary_key} = :id THEN :new_parent " + + "ELSE #{quoted_parent_column_name} END)" , + {:a => a, :b => b, :c => c, :d => d, :id => self.id, :new_parent => new_parent} ] + + + + + self.nested_set_scope.where(*where_statement).update_all([ "#{quoted_left_column_name} = CASE " + "WHEN #{quoted_left_column_name} BETWEEN :a AND :b " + "THEN #{quoted_left_column_name} + :d - :b " + diff --git a/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb b/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb index 2e83be8dd..74cac55b8 100644 --- a/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb +++ b/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb @@ -1,3 +1,3 @@ module AwesomeNestedSet - VERSION = '2.1.5' unless defined?(::AwesomeNestedSet::VERSION) + VERSION = '2.1.6' unless defined?(::AwesomeNestedSet::VERSION) end diff --git a/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb b/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb index cfb6aeeef..0be767f6c 100644 --- a/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb +++ b/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'awesome_nested_set/helper' describe "Helper" do include CollectiveIdea::Acts::NestedSet::Helper diff --git a/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb b/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb index 5de1048b8..105bac1ca 100644 --- a/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb +++ b/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb @@ -1006,6 +1006,12 @@ describe "AwesomeNestedSet" do end end + describe 'rebuilding tree with a default scope ordering' do + it "doesn't throw exception" do + expect { Position.rebuild! }.not_to raise_error + end + end + describe 'creating roots with a default scope ordering' do it "assigns rgt and lft correctly" do alpha = Order.create(:name => 'Alpha') diff --git a/lib/plugins/awesome_nested_set/spec/db/database.yml b/lib/plugins/awesome_nested_set/spec/db/database.yml index ece1a4d91..5218975a4 100644 --- a/lib/plugins/awesome_nested_set/spec/db/database.yml +++ b/lib/plugins/awesome_nested_set/spec/db/database.yml @@ -6,20 +6,22 @@ sqlite3mem: database: ":memory:" postgresql: adapter: postgresql + encoding: unicode + database: awesome_nested_set_plugin_test + pool: 5 username: postgres password: postgres - database: awesome_nested_set_plugin_test - min_messages: ERROR + min_messages: warning mysql: adapter: mysql2 host: localhost username: root - password: + password: database: awesome_nested_set_plugin_test ## Add DB Configuration to run Oracle tests oracle: adapter: oracle_enhanced host: localhost username: awesome_nested_set_dev - password: + password: database: xe diff --git a/lib/plugins/awesome_nested_set/spec/db/schema.rb b/lib/plugins/awesome_nested_set/spec/db/schema.rb index 15a903086..b37322b14 100644 --- a/lib/plugins/awesome_nested_set/spec/db/schema.rb +++ b/lib/plugins/awesome_nested_set/spec/db/schema.rb @@ -56,6 +56,15 @@ ActiveRecord::Schema.define(:version => 0) do t.column :depth, :integer end + create_table :positions, :force => true do |t| + t.column :name, :string + t.column :parent_id, :integer + t.column :lft, :integer + t.column :rgt, :integer + t.column :depth, :integer + t.column :position, :integer + end + create_table :no_depths, :force => true do |t| t.column :name, :string t.column :parent_id, :integer diff --git a/lib/plugins/awesome_nested_set/spec/spec_helper.rb b/lib/plugins/awesome_nested_set/spec/spec_helper.rb index c9cf43d88..d28de5663 100644 --- a/lib/plugins/awesome_nested_set/spec/spec_helper.rb +++ b/lib/plugins/awesome_nested_set/spec/spec_helper.rb @@ -1,32 +1,33 @@ -$:.unshift(File.dirname(__FILE__) + '/../lib') plugin_test_dir = File.dirname(__FILE__) require 'rubygems' require 'bundler/setup' -require 'rspec' require 'logger' - -require 'active_support' -require 'active_model' require 'active_record' -require 'action_controller' - -require 'awesome_nested_set' - ActiveRecord::Base.logger = Logger.new(plugin_test_dir + "/debug.log") require 'yaml' require 'erb' ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(plugin_test_dir + "/db/database.yml")).result) -ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite3mem") +ActiveRecord::Base.establish_connection(ENV["DB"] ||= "sqlite3mem") ActiveRecord::Migration.verbose = false + +require 'combustion/database' +Combustion::Database.create_database(ActiveRecord::Base.configurations[ENV["DB"]]) load(File.join(plugin_test_dir, "db", "schema.rb")) +require 'awesome_nested_set' require 'support/models' +require 'action_controller' require 'rspec/rails' RSpec.configure do |config| config.fixture_path = "#{plugin_test_dir}/fixtures" config.use_transactional_fixtures = true + config.after(:suite) do + unless /sqlite/ === ENV['DB'] + Combustion::Database.drop_database(ActiveRecord::Base.configurations[ENV['DB']]) + end + end end diff --git a/lib/plugins/awesome_nested_set/spec/support/models.rb b/lib/plugins/awesome_nested_set/spec/support/models.rb index ab37cf028..c54ff3e2c 100644 --- a/lib/plugins/awesome_nested_set/spec/support/models.rb +++ b/lib/plugins/awesome_nested_set/spec/support/models.rb @@ -85,6 +85,12 @@ class Order < ActiveRecord::Base default_scope order(:name) end +class Position < ActiveRecord::Base + acts_as_nested_set + + default_scope order(:position) +end + class NoDepth < ActiveRecord::Base acts_as_nested_set end