closure_tree 3.5.2 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Closure Tree [![Build Status](https://secure.travis-ci.org/mceachen/closure_tree.png?branch=master)](http://travis-ci.org/mceachen/closure_tree)
1
+ # Closure Tree
2
2
 
3
3
  Closure Tree is a mostly-API-compatible replacement for the
4
4
  [ancestry](https://github.com/stefankroes/ancestry),
@@ -18,6 +18,17 @@ See [Bill Karwin](http://karwin.blogspot.com/)'s excellent
18
18
  [Models for hierarchical data presentation](http://www.slideshare.net/billkarwin/models-for-hierarchical-data)
19
19
  for a description of different tree storage algorithms.
20
20
 
21
+ ## Table of Contents
22
+
23
+ - [Installation](#installation)
24
+ - [Usage](#usage)
25
+ - [Accessing Data](#accessing-data)
26
+ - [Polymorphic hierarchies with STI](#sti)
27
+ - [Deterministic ordering](#deterministic-ordering)
28
+ - [FAQ](#faq)
29
+ - [Testing](#testing)
30
+ - [Change log](#change-log)
31
+
21
32
  ## Installation
22
33
 
23
34
  Note that closure_tree only supports Rails 3.0 and later, and has test coverage for MySQL, PostgreSQL, and SQLite.
@@ -187,7 +198,8 @@ HT: [ancestry](https://github.com/stefankroes/ancestry#arrangement) and [elhoyos
187
198
  When you include ```acts_as_tree``` in your model, you can provide a hash to override the following defaults:
188
199
 
189
200
  * ```:parent_column_name``` to override the column name of the parent foreign key in the model's table. This defaults to "parent_id".
190
- * ```:hierarchy_table_name``` to override the hierarchy table name. This defaults to the singular name of the model + "_hierarchies".
201
+ * ```:hierarchy_table_name``` to override the hierarchy class name. This defaults to the singular name of the model + "Hierarchy", like ```TagHierarchy```.
202
+ * ```:hierarchy_table_name``` to override the hierarchy table name. This defaults to the singular name of the model + "_hierarchies", like ```tag_hierarchies```.
191
203
  * ```:dependent``` determines what happens when a node is destroyed. Defaults to ```nullify```.
192
204
  * ```:nullify``` will simply set the parent column to null. Each child node will be considered a "root" node. This is the default.
193
205
  * ```:delete_all``` will delete all descendant nodes (which circumvents the destroy hooks)
@@ -321,6 +333,15 @@ root.children.collect(&:name)
321
333
  => ["a", "b", "c"]
322
334
  ```
323
335
 
336
+ ## FAQ
337
+
338
+ ### Does this gem support multiple parents?
339
+
340
+ No. This gem's API is based on the assumption that each node has either 0 or 1 parent.
341
+
342
+ The underlying closure tree structure will support multiple parents, but there would be many
343
+ breaking-API changes to support it. I'm open to suggestions and pull requests.
344
+
324
345
  ## Testing
325
346
 
326
347
  Closure tree is [tested under every combination](http://travis-ci.org/#!/mceachen/closure_tree) of
@@ -331,6 +352,13 @@ Closure tree is [tested under every combination](http://travis-ci.org/#!/mceache
331
352
 
332
353
  ## Change log
333
354
 
355
+ ### 3.6.0
356
+
357
+ * Added support for:
358
+ * ```:hierarchy_class_name``` as an option
359
+ * ActiveRecord::Base.table_name_prefix
360
+ * ActiveRecord::Base.table_name_suffix
361
+
334
362
  ### 3.5.2
335
363
 
336
364
  * Added ```find_all_by_generation```
data/Rakefile CHANGED
@@ -16,5 +16,11 @@ RSpec::Core::RakeTask.new(:spec)
16
16
 
17
17
  task :default => :spec
18
18
 
19
+ task :specs_with_db_ixes do
20
+ [["", ""], ["db_prefix_", ""], ["", "_db_suffix"], ["abc_", "_123"]].each do |prefix, suffix|
21
+ fail unless system("rake spec DB_PREFIX=#{prefix} DB_SUFFIX=#{suffix}")
22
+ end
23
+ end
24
+
19
25
  # Run the specs using all the different database engines:
20
- # for DB in sqlite3 mysql postgresql ; do rake ; done
26
+ # for DB in sqlite3 mysql postgresql ; do rake ; done
@@ -31,6 +31,8 @@ module ClosureTree
31
31
  alias :eql? :==
32
32
  RUBY
33
33
 
34
+ self.hierarchy_class.table_name = hierarchy_table_name
35
+
34
36
  unless order_option.nil?
35
37
  include ClosureTree::DeterministicOrdering
36
38
  include ClosureTree::DeterministicNumericOrdering if order_is_numeric
@@ -388,12 +390,17 @@ module ClosureTree
388
390
  end
389
391
 
390
392
  def hierarchy_table_name
391
- # We need to use the table_name, not ct_class.to_s.demodulize, because they may have overridden the table name
392
- closure_tree_options[:hierarchy_table_name] || ct_table_name.singularize + "_hierarchies"
393
+ # We need to use the table_name, not something like ct_class.to_s.demodulize + "_hierarchies",
394
+ # because they may have overridden the table name, which is what we want to be consistent with
395
+ # in order for the schema to make sense.
396
+ tablename = closure_tree_options[:hierarchy_table_name] ||
397
+ remove_prefix_and_suffix(ct_table_name).singularize + "_hierarchies"
398
+
399
+ ActiveRecord::Base.table_name_prefix + tablename + ActiveRecord::Base.table_name_suffix
393
400
  end
394
401
 
395
402
  def hierarchy_class_name
396
- hierarchy_table_name.singularize.camelize
403
+ closure_tree_options[:hierarchy_class_name] || ct_class.to_s + "Hierarchy"
397
404
  end
398
405
 
399
406
  def quoted_hierarchy_table_name
@@ -445,6 +452,12 @@ module ClosureTree
445
452
  def quoted_table_name
446
453
  connection.quote_column_name ct_table_name
447
454
  end
455
+
456
+ def remove_prefix_and_suffix(table_name)
457
+ prefix = Regexp.escape(ActiveRecord::Base.table_name_prefix)
458
+ suffix = Regexp.escape(ActiveRecord::Base.table_name_suffix)
459
+ table_name.gsub(/^#{prefix}(.+)#{suffix}$/, "\\1")
460
+ end
448
461
  end
449
462
 
450
463
  module DeterministicOrdering
@@ -1,3 +1,3 @@
1
1
  module ClosureTree
2
- VERSION = "3.5.2" unless defined?(::ClosureTree::VERSION)
2
+ VERSION = "3.6.0" unless defined?(::ClosureTree::VERSION)
3
3
  end
@@ -25,6 +25,6 @@ describe CuisineType do
25
25
  end
26
26
 
27
27
  it "sets the table_name of the hierarchy class properly" do
28
- CuisineTypeHierarchy.table_name.should == "cuisine_type_hierarchies"
28
+ CuisineTypeHierarchy.table_name.should == ActiveRecord::Base.table_name_prefix + "cuisine_type_hierarchies" + ActiveRecord::Base.table_name_suffix
29
29
  end
30
30
  end
@@ -1,72 +1,82 @@
1
1
  # encoding: UTF-8
2
+ class ActiveRecord::ConnectionAdapters::AbstractAdapter
3
+ def force_add_index(table_name, columns, options = {})
4
+ begin
5
+ remove_index!(table_name, options[:name])
6
+ rescue ActiveRecord::StatementInvalid, ArgumentError
7
+ end
8
+ add_index table_name, columns, options
9
+ end
10
+ end
11
+
2
12
  ActiveRecord::Schema.define(:version => 0) do
3
13
 
4
14
  create_table "tags", :force => true do |t|
5
- t.string "name"
6
- t.string "title"
7
- t.integer "parent_id"
8
- t.integer "sort_order"
15
+ t.string "name"
16
+ t.string "title"
17
+ t.integer "parent_id"
18
+ t.integer "sort_order"
9
19
  t.datetime "created_at"
10
20
  t.datetime "updated_at"
11
21
  end
12
22
 
13
23
  create_table "tag_hierarchies", :id => false, :force => true do |t|
14
- t.integer "ancestor_id", :null => false
24
+ t.integer "ancestor_id", :null => false
15
25
  t.integer "descendant_id", :null => false
16
- t.integer "generations", :null => false
26
+ t.integer "generations", :null => false
17
27
  end
18
28
 
19
29
  create_table "destroyed_tags", :force => true do |t|
20
- t.string "name"
30
+ t.string "name"
21
31
  end
22
32
 
23
- add_index :tag_hierarchies, [:ancestor_id, :descendant_id], :unique => true
24
- add_index :tag_hierarchies, [:descendant_id]
33
+ force_add_index "tag_hierarchies", [:ancestor_id, :descendant_id], :unique => true, :name => "tag_anc_desc_idx"
34
+ force_add_index "tag_hierarchies", [:descendant_id], :name => "tag_desc_idx"
25
35
 
26
36
  create_table "users", :force => true do |t|
27
- t.string "email"
28
- t.integer "referrer_id"
37
+ t.string "email"
38
+ t.integer "referrer_id"
29
39
  t.datetime "created_at"
30
40
  t.datetime "updated_at"
31
41
  end
32
42
 
33
43
  create_table "contracts", :force => true do |t|
34
- t.integer "user_id", :null => false
44
+ t.integer "user_id", :null => false
35
45
  end
36
46
 
37
47
  create_table "referral_hierarchies", :id => false, :force => true do |t|
38
- t.integer "ancestor_id", :null => false
48
+ t.integer "ancestor_id", :null => false
39
49
  t.integer "descendant_id", :null => false
40
- t.integer "generations", :null => false
50
+ t.integer "generations", :null => false
41
51
  end
42
52
 
43
- add_index :referral_hierarchies, [:ancestor_id, :descendant_id], :unique => true
44
- add_index :referral_hierarchies, [:descendant_id]
53
+ force_add_index "referral_hierarchies", [:ancestor_id, :descendant_id], :unique => true, :name => "ref_anc_desc_idx"
54
+ force_add_index "referral_hierarchies", [:descendant_id], :name => "ref_desc_idx"
45
55
 
46
56
  create_table "labels", :force => true do |t|
47
- t.string "name"
48
- t.string "type"
49
- t.integer "sort_order"
50
- t.integer "mother_id"
57
+ t.string "name"
58
+ t.string "type"
59
+ t.integer "sort_order"
60
+ t.integer "mother_id"
51
61
  end
52
62
 
53
63
  create_table "label_hierarchies", :id => false, :force => true do |t|
54
- t.integer "ancestor_id", :null => false
64
+ t.integer "ancestor_id", :null => false
55
65
  t.integer "descendant_id", :null => false
56
- t.integer "generations", :null => false
66
+ t.integer "generations", :null => false
57
67
  end
58
68
 
59
- add_index :label_hierarchies, [:ancestor_id, :descendant_id], :unique => true
60
- add_index :label_hierarchies, [:descendant_id]
69
+ force_add_index "label_hierarchies", [:ancestor_id, :descendant_id], :unique => true, :name => "lh_anc_desc_idx"
70
+ force_add_index "label_hierarchies", [:descendant_id], :name => "lh_desc_idx"
61
71
 
62
72
  create_table "cuisine_types", :force => true do |t|
63
- t.string "name"
64
- t.integer "parent_id"
73
+ t.string "name"
74
+ t.integer "parent_id"
65
75
  end
66
76
 
67
77
  create_table "cuisine_type_hierarchies", :id => false, :force => true do |t|
68
- t.integer "ancestor_id", :null => false
78
+ t.integer "ancestor_id", :null => false
69
79
  t.integer "descendant_id", :null => false
70
- t.integer "generations", :null => false
80
+ t.integer "generations", :null => false
71
81
  end
72
82
  end
@@ -14,21 +14,19 @@ require 'action_controller' # rspec-rails needs this :(
14
14
 
15
15
  require 'closure_tree'
16
16
 
17
- log = Logger.new(plugin_test_dir + "/debug.log")
18
- log.sev_threshold = Logger::DEBUG
19
- log.datetime_format = "%Y-%m-%d %H:%M:%S"
20
- log.formatter = Logger::Formatter.new
21
-
22
- ActiveRecord::Base.logger = log
17
+ #log = Logger.new(STDOUT)
18
+ #log.sev_threshold = Logger::DEBUG
19
+ #ActiveRecord::Base.logger = log
23
20
 
24
21
  require 'yaml'
25
22
  require 'erb'
26
23
  ENV["DB"] ||= "sqlite3mem"
24
+ ActiveRecord::Base.table_name_prefix = ENV['DB_PREFIX'].to_s
25
+ ActiveRecord::Base.table_name_suffix = ENV['DB_SUFFIX'].to_s
27
26
  ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(plugin_test_dir + "/db/database.yml")).result)
28
27
  ActiveRecord::Base.establish_connection(ENV["DB"])
29
28
  ActiveRecord::Migration.verbose = false
30
- load(File.join(plugin_test_dir, "db", "schema.rb"))
31
-
29
+ require 'db/schema'
32
30
  require 'support/models'
33
31
  require 'rspec/rails' # TODO: clean this up-- I don't want to pull the elephant through the mouse hole just for fixture support
34
32
 
@@ -20,6 +20,7 @@ end
20
20
  class User < ActiveRecord::Base
21
21
  acts_as_tree :parent_column_name => "referrer_id",
22
22
  :name_column => 'email',
23
+ :hierarchy_class_name => 'ReferralHierarchy',
23
24
  :hierarchy_table_name => 'referral_hierarchies'
24
25
 
25
26
  has_many :contracts
@@ -390,7 +390,7 @@ end
390
390
  describe "Tag with AR whitelisted attributes enabled" do
391
391
  before(:all) do
392
392
  ActiveRecord::Base.attr_accessible(nil) # turn on whitelisted attributes
393
- ActiveRecord::Base.subclasses.each{|ea|ea.reset_column_information}
393
+ ActiveRecord::Base.descendants.each{|ea|ea.reset_column_information}
394
394
  end
395
395
  it_behaves_like Tag
396
396
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: closure_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.2
4
+ version: 3.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-04 00:00:00.000000000 Z
12
+ date: 2012-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -192,7 +192,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
192
  version: '0'
193
193
  segments:
194
194
  - 0
195
- hash: 4543577055875281407
195
+ hash: 1756781626803345033
196
196
  required_rubygems_version: !ruby/object:Gem::Requirement
197
197
  none: false
198
198
  requirements:
@@ -201,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
201
  version: '0'
202
202
  segments:
203
203
  - 0
204
- hash: 4543577055875281407
204
+ hash: 1756781626803345033
205
205
  requirements: []
206
206
  rubyforge_project:
207
207
  rubygems_version: 1.8.23