closure_tree 1.0.0.beta2 → 1.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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"