Revision 12687
Added by Toshi MARUYAMA over 11 years ago
trunk/lib/plugins/awesome_nested_set/init.rb | ||
---|---|---|
1 |
require File.dirname(__FILE__) + '/lib/awesome_nested_set' |
trunk/lib/plugins/awesome_nested_set/.travis.yml | ||
---|---|---|
1 |
before_install: gem install bundler --pre
|
|
1 |
language: ruby
|
|
2 | 2 |
notifications: |
3 | 3 |
email: |
4 | 4 |
- [email protected] |
5 |
script: bundle exec rspec spec |
|
5 | 6 |
env: |
6 | 7 |
- DB=sqlite3 |
7 | 8 |
- DB=sqlite3mem |
9 |
- DB=postgresql |
|
10 |
- DB=mysql |
|
8 | 11 |
rvm: |
12 |
- 2.0.0 |
|
13 |
- 1.9.3 |
|
9 | 14 |
- 1.8.7 |
10 |
- 1.9.2
|
|
11 |
- 1.9.3
|
|
12 |
- rbx |
|
13 |
- jruby |
|
15 |
- rbx-19mode
|
|
16 |
- jruby-19mode
|
|
17 |
- rbx-18mode
|
|
18 |
- jruby-18mode
|
|
14 | 19 |
gemfile: |
15 | 20 |
- gemfiles/Gemfile.rails-3.0.rb |
16 | 21 |
- gemfiles/Gemfile.rails-3.1.rb |
17 |
- gemfiles/Gemfile.rails-3.2.rb |
|
22 |
- gemfiles/Gemfile.rails-3.2.rb |
trunk/lib/plugins/awesome_nested_set/CHANGELOG | ||
---|---|---|
1 |
2.1.6 |
|
2 |
* Fixed rebuild! when there is a default_scope with order [Adrian Serafin] |
|
3 |
* Testing with stable bundler, ruby 2.0, MySQL and PostgreSQL [Philip Arndt] |
|
4 |
* Optimized move_to for large trees [ericsmith66] |
|
5 |
|
|
1 | 6 |
2.1.5 |
2 | 7 |
* Worked around issues where AR#association wasn't present on Rails 3.0.x. [Philip Arndt] |
3 | 8 |
* Adds option 'order_column' which defaults to 'left_column_name'. [gudata] |
trunk/lib/plugins/awesome_nested_set/Rakefile | ||
---|---|---|
4 | 4 |
require 'bundler/setup' |
5 | 5 |
require 'awesome_nested_set/version' |
6 | 6 |
|
7 |
require "rspec/core/rake_task" |
|
8 |
RSpec::Core::RakeTask.new(:spec) |
|
9 |
|
|
10 | 7 |
task :default => :spec |
11 | 8 |
|
9 |
task :spec do |
|
10 |
%w(3.0 3.1 3.2).each do |rails_version| |
|
11 |
puts "\n" + (cmd = "BUNDLE_GEMFILE='gemfiles/Gemfile.rails-#{rails_version}.rb' bundle exec rspec spec") |
|
12 |
system cmd |
|
13 |
end |
|
14 |
end |
|
15 |
|
|
12 | 16 |
task :build do |
13 | 17 |
system "gem build awesome_nested_set.gemspec" |
14 | 18 |
end |
trunk/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec | ||
---|---|---|
1 | 1 |
# -*- encoding: utf-8 -*- |
2 |
lib = File.expand_path('../lib/', __FILE__) |
|
3 |
$:.unshift lib unless $:.include?(lib) |
|
4 |
require 'awesome_nested_set/version' |
|
2 |
require File.expand_path('../lib/awesome_nested_set/version', __FILE__) |
|
5 | 3 |
|
6 | 4 |
Gem::Specification.new do |s| |
7 | 5 |
s.name = %q{awesome_nested_set} |
... | ... | |
9 | 7 |
s.authors = ["Brandon Keepers", "Daniel Morrison", "Philip Arndt"] |
10 | 8 |
s.description = %q{An awesome nested set implementation for Active Record} |
11 | 9 |
s.email = %q{[email protected]} |
12 |
s.extra_rdoc_files = [ |
|
13 |
"README.rdoc" |
|
14 |
] |
|
10 |
s.extra_rdoc_files = %w[README.rdoc] |
|
15 | 11 |
s.files = Dir.glob("lib/**/*") + %w(MIT-LICENSE README.rdoc CHANGELOG) |
16 | 12 |
s.homepage = %q{http://github.com/collectiveidea/awesome_nested_set} |
17 | 13 |
s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"] |
18 | 14 |
s.require_paths = ["lib"] |
19 | 15 |
s.rubygems_version = %q{1.3.6} |
20 | 16 |
s.summary = %q{An awesome nested set implementation for Active Record} |
17 |
s.license = %q{MIT} |
|
18 |
|
|
21 | 19 |
s.add_runtime_dependency 'activerecord', '>= 3.0.0' |
22 |
s.add_development_dependency 'rspec-rails', '~> 2.8' |
|
20 |
|
|
21 |
s.add_development_dependency 'rspec-rails', '~> 2.12' |
|
22 |
s.add_development_dependency 'rake', '~> 10' |
|
23 |
s.add_development_dependency 'combustion', '>= 0.3.3' |
|
23 | 24 |
end |
trunk/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb | ||
---|---|---|
181 | 181 |
# Rebuilds the left & rights if unset or invalid. |
182 | 182 |
# Also very useful for converting from acts_as_tree. |
183 | 183 |
def rebuild!(validate_nodes = true) |
184 |
# Don't rebuild a valid tree. |
|
185 |
return true if valid? |
|
184 |
# default_scope with order may break database queries so we do all operation without scope |
|
185 |
unscoped do |
|
186 |
# Don't rebuild a valid tree. |
|
187 |
return true if valid? |
|
186 | 188 |
|
187 |
scope = lambda{|node|} |
|
188 |
if acts_as_nested_set_options[:scope] |
|
189 |
scope = lambda{|node| |
|
190 |
scope_column_names.inject(""){|str, column_name| |
|
191 |
str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} " |
|
189 |
scope = lambda{|node|} |
|
190 |
if acts_as_nested_set_options[:scope] |
|
191 |
scope = lambda{|node| |
|
192 |
scope_column_names.inject(""){|str, column_name| |
|
193 |
str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} " |
|
194 |
} |
|
192 | 195 |
} |
193 |
} |
|
194 |
end |
|
195 |
indices = {} |
|
196 |
end |
|
197 |
indices = {} |
|
196 | 198 |
|
197 |
set_left_and_rights = lambda do |node| |
|
198 |
# set left |
|
199 |
node[left_column_name] = indices[scope.call(node)] += 1 |
|
200 |
# find |
|
201 |
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) } |
|
202 |
# set right |
|
203 |
node[right_column_name] = indices[scope.call(node)] += 1 |
|
204 |
node.save!(:validate => validate_nodes) |
|
205 |
end |
|
199 |
set_left_and_rights = lambda do |node|
|
|
200 |
# set left
|
|
201 |
node[left_column_name] = indices[scope.call(node)] += 1
|
|
202 |
# find
|
|
203 |
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) }
|
|
204 |
# set right
|
|
205 |
node[right_column_name] = indices[scope.call(node)] += 1
|
|
206 |
node.save!(:validate => validate_nodes)
|
|
207 |
end
|
|
206 | 208 |
|
207 |
# Find root node(s) |
|
208 |
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| |
|
209 |
# setup index for this scope |
|
210 |
indices[scope.call(root_node)] ||= 0 |
|
211 |
set_left_and_rights.call(root_node) |
|
209 |
# Find root node(s) |
|
210 |
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| |
|
211 |
# setup index for this scope |
|
212 |
indices[scope.call(root_node)] ||= 0 |
|
213 |
set_left_and_rights.call(root_node) |
|
214 |
end |
|
212 | 215 |
end |
213 | 216 |
end |
214 | 217 |
|
... | ... | |
590 | 593 |
["#{quoted_right_column_name} = (#{quoted_right_column_name} - ?)", diff] |
591 | 594 |
) |
592 | 595 |
|
593 |
# Reload is needed because children may have updated their parent (self) during deletion. |
|
594 |
reload |
|
595 | 596 |
# Don't allow multiple calls to destroy to corrupt the set |
596 | 597 |
self.skip_before_destroy = true |
597 | 598 |
end |
... | ... | |
654 | 655 |
else target[parent_column_name] |
655 | 656 |
end |
656 | 657 |
|
657 |
self.nested_set_scope.update_all([ |
|
658 |
where_statement = ["not (#{quoted_left_column_name} = CASE " + |
|
659 |
"WHEN #{quoted_left_column_name} BETWEEN :a AND :b " + |
|
660 |
"THEN #{quoted_left_column_name} + :d - :b " + |
|
661 |
"WHEN #{quoted_left_column_name} BETWEEN :c AND :d " + |
|
662 |
"THEN #{quoted_left_column_name} + :a - :c " + |
|
663 |
"ELSE #{quoted_left_column_name} END AND " + |
|
664 |
"#{quoted_right_column_name} = CASE " + |
|
665 |
"WHEN #{quoted_right_column_name} BETWEEN :a AND :b " + |
|
666 |
"THEN #{quoted_right_column_name} + :d - :b " + |
|
667 |
"WHEN #{quoted_right_column_name} BETWEEN :c AND :d " + |
|
668 |
"THEN #{quoted_right_column_name} + :a - :c " + |
|
669 |
"ELSE #{quoted_right_column_name} END AND " + |
|
670 |
"#{quoted_parent_column_name} = CASE " + |
|
671 |
"WHEN #{self.class.base_class.primary_key} = :id THEN :new_parent " + |
|
672 |
"ELSE #{quoted_parent_column_name} END)" , |
|
673 |
{:a => a, :b => b, :c => c, :d => d, :id => self.id, :new_parent => new_parent} ] |
|
674 |
|
|
675 |
|
|
676 |
|
|
677 |
|
|
678 |
self.nested_set_scope.where(*where_statement).update_all([ |
|
658 | 679 |
"#{quoted_left_column_name} = CASE " + |
659 | 680 |
"WHEN #{quoted_left_column_name} BETWEEN :a AND :b " + |
660 | 681 |
"THEN #{quoted_left_column_name} + :d - :b " + |
trunk/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb | ||
---|---|---|
1 | 1 |
module AwesomeNestedSet |
2 |
VERSION = '2.1.5' unless defined?(::AwesomeNestedSet::VERSION)
|
|
2 |
VERSION = '2.1.6' unless defined?(::AwesomeNestedSet::VERSION)
|
|
3 | 3 |
end |
trunk/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb | ||
---|---|---|
1 | 1 |
require 'spec_helper' |
2 |
require 'awesome_nested_set/helper' |
|
2 | 3 |
|
3 | 4 |
describe "Helper" do |
4 | 5 |
include CollectiveIdea::Acts::NestedSet::Helper |
trunk/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb | ||
---|---|---|
1006 | 1006 |
end |
1007 | 1007 |
end |
1008 | 1008 |
|
1009 |
describe 'rebuilding tree with a default scope ordering' do |
|
1010 |
it "doesn't throw exception" do |
|
1011 |
expect { Position.rebuild! }.not_to raise_error |
|
1012 |
end |
|
1013 |
end |
|
1014 |
|
|
1009 | 1015 |
describe 'creating roots with a default scope ordering' do |
1010 | 1016 |
it "assigns rgt and lft correctly" do |
1011 | 1017 |
alpha = Order.create(:name => 'Alpha') |
trunk/lib/plugins/awesome_nested_set/spec/db/database.yml | ||
---|---|---|
6 | 6 |
database: ":memory:" |
7 | 7 |
postgresql: |
8 | 8 |
adapter: postgresql |
9 |
encoding: unicode |
|
10 |
database: awesome_nested_set_plugin_test |
|
11 |
pool: 5 |
|
9 | 12 |
username: postgres |
10 | 13 |
password: postgres |
11 |
database: awesome_nested_set_plugin_test |
|
12 |
min_messages: ERROR |
|
14 |
min_messages: warning |
|
13 | 15 |
mysql: |
14 | 16 |
adapter: mysql2 |
15 | 17 |
host: localhost |
16 | 18 |
username: root |
17 |
password:
|
|
19 |
password: |
|
18 | 20 |
database: awesome_nested_set_plugin_test |
19 | 21 |
## Add DB Configuration to run Oracle tests |
20 | 22 |
oracle: |
21 | 23 |
adapter: oracle_enhanced |
22 | 24 |
host: localhost |
23 | 25 |
username: awesome_nested_set_dev |
24 |
password:
|
|
26 |
password: |
|
25 | 27 |
database: xe |
trunk/lib/plugins/awesome_nested_set/spec/db/schema.rb | ||
---|---|---|
56 | 56 |
t.column :depth, :integer |
57 | 57 |
end |
58 | 58 |
|
59 |
create_table :positions, :force => true do |t| |
|
60 |
t.column :name, :string |
|
61 |
t.column :parent_id, :integer |
|
62 |
t.column :lft, :integer |
|
63 |
t.column :rgt, :integer |
|
64 |
t.column :depth, :integer |
|
65 |
t.column :position, :integer |
|
66 |
end |
|
67 |
|
|
59 | 68 |
create_table :no_depths, :force => true do |t| |
60 | 69 |
t.column :name, :string |
61 | 70 |
t.column :parent_id, :integer |
trunk/lib/plugins/awesome_nested_set/spec/spec_helper.rb | ||
---|---|---|
1 |
$:.unshift(File.dirname(__FILE__) + '/../lib') |
|
2 | 1 |
plugin_test_dir = File.dirname(__FILE__) |
3 | 2 |
|
4 | 3 |
require 'rubygems' |
5 | 4 |
require 'bundler/setup' |
6 | 5 |
|
7 |
require 'rspec' |
|
8 | 6 |
require 'logger' |
9 |
|
|
10 |
require 'active_support' |
|
11 |
require 'active_model' |
|
12 | 7 |
require 'active_record' |
13 |
require 'action_controller' |
|
14 |
|
|
15 |
require 'awesome_nested_set' |
|
16 |
|
|
17 | 8 |
ActiveRecord::Base.logger = Logger.new(plugin_test_dir + "/debug.log") |
18 | 9 |
|
19 | 10 |
require 'yaml' |
20 | 11 |
require 'erb' |
21 | 12 |
ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(plugin_test_dir + "/db/database.yml")).result) |
22 |
ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite3mem") |
|
13 |
ActiveRecord::Base.establish_connection(ENV["DB"] ||= "sqlite3mem")
|
|
23 | 14 |
ActiveRecord::Migration.verbose = false |
15 |
|
|
16 |
require 'combustion/database' |
|
17 |
Combustion::Database.create_database(ActiveRecord::Base.configurations[ENV["DB"]]) |
|
24 | 18 |
load(File.join(plugin_test_dir, "db", "schema.rb")) |
25 | 19 |
|
20 |
require 'awesome_nested_set' |
|
26 | 21 |
require 'support/models' |
27 | 22 |
|
23 |
require 'action_controller' |
|
28 | 24 |
require 'rspec/rails' |
29 | 25 |
RSpec.configure do |config| |
30 | 26 |
config.fixture_path = "#{plugin_test_dir}/fixtures" |
31 | 27 |
config.use_transactional_fixtures = true |
28 |
config.after(:suite) do |
|
29 |
unless /sqlite/ === ENV['DB'] |
|
30 |
Combustion::Database.drop_database(ActiveRecord::Base.configurations[ENV['DB']]) |
|
31 |
end |
|
32 |
end |
|
32 | 33 |
end |
trunk/lib/plugins/awesome_nested_set/spec/support/models.rb | ||
---|---|---|
85 | 85 |
default_scope order(:name) |
86 | 86 |
end |
87 | 87 |
|
88 |
class Position < ActiveRecord::Base |
|
89 |
acts_as_nested_set |
|
90 |
|
|
91 |
default_scope order(:position) |
|
92 |
end |
|
93 |
|
|
88 | 94 |
class NoDepth < ActiveRecord::Base |
89 | 95 |
acts_as_nested_set |
90 | 96 |
end |
Also available in: Unified diff
import awesome_nested_set 2.1.6
https://github.com/collectiveidea/awesome_nested_set/commit/64cc8bc8cf93e8859a21bcf25c36675080e42ce6