closure_tree 1.0.0.beta2 → 1.0.0.beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -79,17 +79,17 @@ Then:
79
79
  puts grandparent.self_and_descendants.collect{ |t| t.name }.join(" > ")
80
80
  "grandparent > parent > child"
81
81
 
82
- child.ancestry_names
82
+ child.ancestry_path
83
83
  ["grandparent", "parent", "child"]
84
84
 
85
85
  === <code>find_or_create_by_path</code>
86
86
 
87
- If your model has a single string column that can build a given node (like a "name" or a "title"),
88
- you can use that to find_or_create:
87
+ We can do all the node creation and add_child calls from the prior section with one method call:
88
+ child = Tag.find_or_create_by_path "grandparent", "parent", "child"
89
89
 
90
- Tag.find_or_create_by_path %w{one two three}
90
+ You can <code>find</code> as well as <code>find_or_create</code> by "ancestry paths". Ancestry paths may be built using any column in your model. The default column is <code>name</code>, which can be changed with the :name_column option provided to <code>acts_as_tree</code>.
91
91
 
92
- You can customize the column name with the :name_column option in <code>acts_as_tree</code>.
92
+ Note that the other columns will be null if nodes are created, other than auto-generated columns like ID and created_at timestamp. Only the specified column will receive the path element value.
93
93
 
94
94
  == Accessing Data
95
95
 
@@ -91,10 +91,11 @@ module ClosureTree #:nodoc:
91
91
  [self].concat ancestors.to_a
92
92
  end
93
93
 
94
- # Returns an array, root first, of self_and_ancestors' +name_column+ values
95
- # (so child.ancestry_names == +%w{grandparent parent child}+
96
- def ancestry_names
97
- self_and_ancestors.reverse.collect { |n| n.send name_column.to_sym }
94
+ # Returns an array, root first, of self_and_ancestors' values of the +to_s_column+, which defaults
95
+ # to the +name_column+.
96
+ # (so child.ancestry_path == +%w{grandparent parent child}+
97
+ def ancestry_path to_s_column = name_column
98
+ self_and_ancestors.reverse.collect { |n| n.send to_s_column.to_sym }
98
99
  end
99
100
 
100
101
  def self_and_descendants
@@ -128,22 +129,25 @@ module ClosureTree #:nodoc:
128
129
  new_parent.add_child self
129
130
  end
130
131
 
131
- # Find a child node whose +ancestry_names+ minus self.ancestry_names is +path+
132
- def find_by_path path
133
- _find_or_create_by_path path, "find_by_#{name_column}".to_sym
132
+ # Find a child node whose +ancestry_path+ minus self.ancestry_path is +path+.
133
+ # If the first argument is a symbol, it will be used as the column to search by
134
+ def find_by_path *path
135
+ _find_or_create_by_path "find", path
134
136
  end
135
137
 
136
- # Find a child node whose +ancestry_names+ minus self.ancestry_names is +path+
137
- def find_or_create_by_path path
138
- _find_or_create_by_path path, "find_or_create_by_#{name_column}".to_sym
138
+ # Find a child node whose +ancestry_path+ minus self.ancestry_path is +path+
139
+ def find_or_create_by_path *path
140
+ _find_or_create_by_path "find_or_create", path
139
141
  end
140
142
 
141
143
  protected
142
144
 
143
- def _find_or_create_by_path path, methodname
145
+ def _find_or_create_by_path method_prefix, path
146
+ to_s_column = path.first.is_a?(Symbol) ? path.shift.to_s : name_column
147
+ path.flatten!
144
148
  node = self
145
- while (name = path.shift and node)
146
- node = node.children.send(methodname, name)
149
+ while (s = path.shift and node)
150
+ node = node.children.send("#{method_prefix}_by_#{to_s_column}".to_sym, s)
147
151
  end
148
152
  node
149
153
  end
@@ -170,27 +174,29 @@ module ClosureTree #:nodoc:
170
174
  nil
171
175
  end
172
176
 
173
- # Find the node whose +ancestry_names+ is +path+
174
- def find_by_path path
175
- self.where(name_sym => path.last).each do |n|
176
- return n if path == n.ancestry_names
177
+ # Find the node whose +ancestry_path+ is +path+
178
+ # If the first argument is a symbol, it will be used as the column to search by
179
+ def find_by_path *path
180
+ to_s_column = path.first.is_a?(Symbol) ? path.shift.to_s : name_column
181
+ path.flatten!
182
+ self.where(to_s_column => path.last).each do |n|
183
+ return n if path == n.ancestry_path(to_s_column)
177
184
  end
178
185
  nil
179
186
  end
180
187
 
181
- # Find or create nodes such that the +ancestry_names+ is +path+
182
- def find_or_create_by_path path
188
+ # Find or create nodes such that the +ancestry_path+ is +path+
189
+ def find_or_create_by_path *path
183
190
  # short-circuit if we can:
184
191
  n = find_by_path path
185
192
  return n if n
186
193
 
187
- name = path.shift
188
- node = roots.where(name_sym => name).first
189
- node = create!(name_sym => name) unless node
190
- while (name = path.shift)
191
- node = node.children.send("find_or_create_by_#{name_column}".to_sym, name)
192
- end
193
- node
194
+ column_sym = path.first.is_a?(Symbol) ? path.shift : name_sym
195
+ path.flatten!
196
+ s = path.shift
197
+ node = roots.where(column_sym => s).first
198
+ node = create!(column_sym => s) unless node
199
+ node.find_or_create_by_path column_sym, path
194
200
  end
195
201
 
196
202
  private
@@ -1,3 +1,3 @@
1
1
  module ClosureTree
2
- VERSION = "1.0.0.beta2" unless defined?(::ClosureTree::VERSION)
2
+ VERSION = "1.0.0.beta3" unless defined?(::ClosureTree::VERSION)
3
3
  end
@@ -3,6 +3,7 @@ class CreateTags < ActiveRecord::Migration
3
3
 
4
4
  create_table :tags do |t|
5
5
  t.string :name
6
+ t.string :title
6
7
  t.integer :parent_id
7
8
  t.timestamps
8
9
  end
@@ -14,6 +14,7 @@ ActiveRecord::Schema.define(:version => 20110522004834) do
14
14
 
15
15
  create_table "tags", :force => true do |t|
16
16
  t.string "name"
17
+ t.string "title"
17
18
  t.integer "parent_id"
18
19
  t.datetime "created_at"
19
20
  t.datetime "updated_at"
@@ -2,15 +2,17 @@
2
2
 
3
3
  grandparent:
4
4
  name: grandparent
5
+ title: Nonnie
5
6
 
6
7
  parent:
7
8
  name: parent
8
9
  parent: grandparent
10
+ title: Mom
9
11
 
10
12
  child:
11
13
  name: child
12
14
  parent: parent
13
-
15
+ title: Kid
14
16
 
15
17
  people:
16
18
  name: people
@@ -57,26 +57,32 @@ class TagTest < ActiveSupport::TestCase
57
57
  end
58
58
 
59
59
  def test_ancestry_path
60
- assert_equal %w{grandparent parent child}, tags(:child).ancestry_names
60
+ assert_equal %w{grandparent parent child}, tags(:child).ancestry_path
61
+ assert_equal %w{grandparent parent child}, tags(:child).ancestry_path(:name)
62
+ assert_equal %w{Nonnie Mom Kid}, tags(:child).ancestry_path(:title)
61
63
  end
62
64
 
63
65
  def test_find_by_path
64
66
  # class method:
65
67
  assert_equal tags(:child), Tag.find_by_path(%w{grandparent parent child})
66
- assert_equal tags(:child), Tag.find_or_create_by_path(%w{grandparent parent child})
68
+ assert_equal tags(:child), Tag.find_by_path(:title, %w{Nonnie Mom Kid})
67
69
  # instance method:
68
70
  assert_equal tags(:child), tags(:parent).find_by_path(%w{child})
71
+ assert_equal tags(:child), tags(:parent).find_by_path(:title, %w{Kid})
69
72
  assert_equal tags(:child), tags(:grandparent).find_by_path(%w{parent child})
73
+ assert_equal tags(:child), tags(:grandparent).find_by_path(:title, %w{Mom Kid})
70
74
  assert_nil tags(:parent).find_by_path(%w{child larvae})
71
75
  end
72
76
 
73
77
  def test_find_or_create_by_path
74
78
  # class method:
75
- assert_equal %w{events anniversary}, Tag.find_or_create_by_path(%w{events anniversary}).ancestry_names
79
+ assert_equal tags(:child), Tag.find_or_create_by_path(%w{grandparent parent child})
80
+ assert_equal tags(:child), Tag.find_or_create_by_path(:title, %w{Nonnie Mom Kid})
81
+ assert_equal %w{events anniversary}, Tag.find_or_create_by_path(%w{events anniversary}).ancestry_path
76
82
  a = Tag.find_or_create_by_path(%w{a})
77
- assert_equal %w{a}, a.ancestry_names
83
+ assert_equal %w{a}, a.ancestry_path
78
84
  # instance method:
79
- assert_equal %w{a b c}, a.find_or_create_by_path(%w{b c}).ancestry_names
85
+ assert_equal %w{a b c}, a.find_or_create_by_path(%w{b c}).ancestry_path
80
86
  end
81
87
 
82
88
  def test_descendants
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: closure_tree
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 6
5
- version: 1.0.0.beta2
5
+ version: 1.0.0.beta3
6
6
  platform: ruby
7
7
  authors: []
8
8
 
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-25 00:00:00 -07:00
13
+ date: 2011-05-26 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -73,7 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - ">="
75
75
  - !ruby/object:Gem::Version
76
- hash: -1571970483886197148
76
+ hash: 2257595380188246970
77
77
  segments:
78
78
  - 0
79
79
  version: "0"