import awesome_nested_set 2.1.6

64cc8bc8cf

git-svn-id: http://svn.redmine.org/redmine/trunk@12687 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Toshi MARUYAMA 2014-01-21 07:54:42 +00:00
parent bdfcfb35a3
commit 3f6a676622
13 changed files with 119 additions and 59 deletions

View File

@ -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
- gemfiles/Gemfile.rails-3.2.rb

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
require File.dirname(__FILE__) + '/lib/awesome_nested_set'

View File

@ -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 " +

View File

@ -1,3 +1,3 @@
module AwesomeNestedSet
VERSION = '2.1.5' unless defined?(::AwesomeNestedSet::VERSION)
VERSION = '2.1.6' unless defined?(::AwesomeNestedSet::VERSION)
end

View File

@ -1,4 +1,5 @@
require 'spec_helper'
require 'awesome_nested_set/helper'
describe "Helper" do
include CollectiveIdea::Acts::NestedSet::Helper

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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