lalala 4.0.0.dev.136 → 4.0.0.dev.141

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/lalala.gemspec +2 -6
  4. data/lib/lalala/version.rb +1 -1
  5. data/lib/lalala.rb +0 -1
  6. metadata +19 -53
  7. data/vendor/deps/closure_tree/.gitignore +0 -12
  8. data/vendor/deps/closure_tree/.travis.yml +0 -22
  9. data/vendor/deps/closure_tree/.yardopts +0 -3
  10. data/vendor/deps/closure_tree/Gemfile +0 -2
  11. data/vendor/deps/closure_tree/MIT-LICENSE +0 -19
  12. data/vendor/deps/closure_tree/README.md +0 -641
  13. data/vendor/deps/closure_tree/Rakefile +0 -26
  14. data/vendor/deps/closure_tree/ci/Gemfile.rails-3.0.x +0 -5
  15. data/vendor/deps/closure_tree/ci/Gemfile.rails-3.1.x +0 -4
  16. data/vendor/deps/closure_tree/ci/Gemfile.rails-3.2.x +0 -4
  17. data/vendor/deps/closure_tree/closure_tree.gemspec +0 -31
  18. data/vendor/deps/closure_tree/lib/closure_tree/acts_as_tree.rb +0 -55
  19. data/vendor/deps/closure_tree/lib/closure_tree/columns.rb +0 -123
  20. data/vendor/deps/closure_tree/lib/closure_tree/deterministic_ordering.rb +0 -49
  21. data/vendor/deps/closure_tree/lib/closure_tree/model.rb +0 -386
  22. data/vendor/deps/closure_tree/lib/closure_tree/numeric_deterministic_ordering.rb +0 -93
  23. data/vendor/deps/closure_tree/lib/closure_tree/version.rb +0 -3
  24. data/vendor/deps/closure_tree/lib/closure_tree/with_advisory_lock.rb +0 -18
  25. data/vendor/deps/closure_tree/lib/closure_tree.rb +0 -8
  26. data/vendor/deps/closure_tree/spec/cuisine_type_spec.rb +0 -30
  27. data/vendor/deps/closure_tree/spec/db/database.yml +0 -19
  28. data/vendor/deps/closure_tree/spec/db/schema.rb +0 -109
  29. data/vendor/deps/closure_tree/spec/fixtures/labels.yml +0 -55
  30. data/vendor/deps/closure_tree/spec/fixtures/tags.yml +0 -98
  31. data/vendor/deps/closure_tree/spec/hash_tree_spec.rb +0 -91
  32. data/vendor/deps/closure_tree/spec/label_spec.rb +0 -356
  33. data/vendor/deps/closure_tree/spec/namespace_type_spec.rb +0 -13
  34. data/vendor/deps/closure_tree/spec/parallel_prepend_sibling_spec.rb +0 -45
  35. data/vendor/deps/closure_tree/spec/parallel_spec.rb +0 -59
  36. data/vendor/deps/closure_tree/spec/spec_helper.rb +0 -57
  37. data/vendor/deps/closure_tree/spec/support/models.rb +0 -74
  38. data/vendor/deps/closure_tree/spec/tag_spec.rb +0 -469
  39. data/vendor/deps/closure_tree/spec/user_spec.rb +0 -136
  40. data/vendor/deps/closure_tree/tests.sh +0 -19
@@ -1,641 +0,0 @@
1
- # Closure Tree [![Build Status](https://secure.travis-ci.org/mceachen/closure_tree.png?branch=master)](http://travis-ci.org/mceachen/closure_tree)
2
-
3
- ### Closure_tree lets your ActiveRecord models act as nodes in a [tree data structure](http://en.wikipedia.org/wiki/Tree_%28data_structure%29)
4
-
5
- Common applications include modeling hierarchical data, like tags, page graphs in CMSes,
6
- and tracking user referrals.
7
-
8
- Mostly API-compatible with other popular nesting gems for Rails, like
9
- [ancestry](https://github.com/stefankroes/ancestry),
10
- [acts_as_tree](https://github.com/amerine/acts_as_tree) and
11
- [awesome_nested_set](https://github.com/collectiveidea/awesome_nested_set/),
12
- closure_tree has some great features:
13
-
14
- * __Best-in-class select performance__:
15
- * Fetch your whole ancestor lineage in 1 SELECT.
16
- * Grab all your descendants in 1 SELECT.
17
- * Get all your siblings in 1 SELECT.
18
- * Fetch all [descendants as a nested hash](#nested-hashes) in 1 SELECT.
19
- * [Find a node by ancestry path](#find_or_create_by_path) in 1 SELECT.
20
- * __Best-in-class mutation performance__:
21
- * 2 SQL INSERTs on node creation
22
- * 3 SQL INSERT/UPDATEs on node reparenting
23
- * Support for reparenting children (and all their progeny)
24
- * Support for [concurrency](#concurrency) (using [with_advisory_lock](https://github/mceachen/with_advisory_lock))
25
- * Support for polymorphism [STI](#sti) within the hierarchy
26
- * ```find_or_create_by_path``` for [building out hierarchies quickly and conveniently](#find_or_create_by_path)
27
- * Support for [deterministic ordering](#deterministic-ordering) of children
28
- * Support for [preordered](http://en.wikipedia.org/wiki/Tree_traversal#Pre-order) traversal of descendants
29
- * Excellent [test coverage](#testing) in a variety of environments
30
-
31
- See [Bill Karwin](http://karwin.blogspot.com/)'s excellent
32
- [Models for hierarchical data presentation](http://www.slideshare.net/billkarwin/models-for-hierarchical-data)
33
- for a description of different tree storage algorithms.
34
-
35
- ## Table of Contents
36
-
37
- - [Installation](#installation)
38
- - [Usage](#usage)
39
- - [Accessing Data](#accessing-data)
40
- - [Polymorphic hierarchies with STI](#polymorphic-hierarchies-with-sti)
41
- - [Deterministic ordering](#deterministic-ordering)
42
- - [Concurrency](#concurrency)
43
- - [FAQ](#faq)
44
- - [Testing](#testing)
45
- - [Change log](#change-log)
46
-
47
- ## Installation
48
-
49
- Note that closure_tree only supports Rails 3.0 and later, and has test coverage for MySQL, PostgreSQL, and SQLite.
50
-
51
- 1. Add this to your Gemfile: ```gem 'closure_tree'```
52
-
53
- 2. Run ```bundle install```
54
-
55
- 3. Add ```acts_as_tree``` to your hierarchical model(s). There are a number of [options](#available-options) you can pass in, too.
56
-
57
- 4. Add a migration to add a ```parent_id``` column to the model you want to act_as_tree.
58
- You may want to also [add a column for deterministic ordering of children](#sort_order), but that's optional.
59
-
60
- ```ruby
61
- class AddParentIdToTag < ActiveRecord::Migration
62
- def change
63
- add_column :tag, :parent_id, :integer
64
- end
65
- end
66
- ```
67
-
68
- Note that if the column is null, the tag will be considered a root node.
69
-
70
- 5. Add a database migration to store the hierarchy for your model. By
71
- default the table name will be the model's table name, followed by
72
- "_hierarchies". Note that by calling ```acts_as_tree```, a "virtual model" (in this case, ```TagHierarchy```)
73
- will be added automatically, so you don't need to create it.
74
-
75
- ```ruby
76
- class CreateTagHierarchies < ActiveRecord::Migration
77
- def change
78
- create_table :tag_hierarchies, :id => false do |t|
79
- t.integer :ancestor_id, :null => false # ID of the parent/grandparent/great-grandparent/... tag
80
- t.integer :descendant_id, :null => false # ID of the target tag
81
- t.integer :generations, :null => false # Number of generations between the ancestor and the descendant. Parent/child = 1, for example.
82
- end
83
-
84
- # For "all progeny of…" selects:
85
- add_index :tag_hierarchies, [:ancestor_id, :descendant_id], :unique => true
86
-
87
- # For "all ancestors of…" selects
88
- add_index :tag_hierarchies, [:descendant_id]
89
- end
90
- end
91
- ```
92
-
93
- 6. Run ```rake db:migrate```
94
-
95
- 7. If you're migrating from another system where your model already has a
96
- ```parent_id``` column, run ```Tag.rebuild!``` and the
97
- …_hierarchy table will be truncated and rebuilt.
98
-
99
- If you're starting from scratch you don't need to call ```rebuild!```.
100
-
101
- ## Usage
102
-
103
- ### Creation
104
-
105
- Create a root node:
106
-
107
- ```ruby
108
- grandparent = Tag.create(:name => 'Grandparent')
109
- ```
110
-
111
- Child nodes are created by appending to the children collection:
112
-
113
- ```ruby
114
- parent = grandparent.children.create(:name => 'Parent')
115
- ```
116
-
117
- Or by appending to the children collection:
118
-
119
- ```ruby
120
- child2 = Tag.new(:name => 'Second Child')
121
- parent.children << child2
122
- ```
123
-
124
- Or by calling the "add_child" method:
125
-
126
- ```ruby
127
- child3 = Tag.new(:name => 'Third Child')
128
- parent.add_child child3
129
- ```
130
-
131
- Then:
132
-
133
- ```ruby
134
- grandparent.self_and_descendants.collect(&:name)
135
- => ["Grandparent", "Parent", "First Child", "Second Child", "Third Child"]
136
-
137
- child1.ancestry_path
138
- => ["Grandparent", "Parent", "First Child"]
139
- ```
140
-
141
- ### find_or_create_by_path
142
-
143
- We can do all the node creation and add_child calls with one method call:
144
-
145
- ```ruby
146
- child = Tag.find_or_create_by_path(["grandparent", "parent", "child"])
147
- ```
148
-
149
- You can ```find``` as well as ```find_or_create``` by "ancestry paths".
150
- Ancestry paths may be built using any column in your model. The default
151
- column is ```name```, which can be changed with the :name_column option
152
- provided to ```acts_as_tree```.
153
-
154
- Note that any other AR fields can be set with the second, optional ```attributes``` argument.
155
-
156
- ```ruby
157
- child = Tag.find_or_create_by_path(%w{home chuck Photos"}, {:tag_type => "File"})
158
- ```
159
- This will pass the attribute hash of ```{:name => "home", :tag_type => "File"}``` to
160
- ```Tag.find_or_create_by_name``` if the root directory doesn't exist (and
161
- ```{:name => "chuck", :tag_type => "File"}``` if the second-level tag doesn't exist, and so on).
162
-
163
- ### Moving nodes around the tree
164
-
165
- Nodes can be moved around to other parents, and closure_tree moves the node's descendancy to the new parent for you:
166
-
167
- ```ruby
168
- d = Tag.find_or_create_by_path %w(a b c d)
169
- h = Tag.find_or_create_by_path %w(e f g h)
170
- e = h.root
171
- d.add_child(e) # "d.children << e" would work too, of course
172
- h.ancestry_path
173
- => ["a", "b", "c", "d", "e", "f", "g", "h"]
174
- ```
175
-
176
- ### Nested hashes
177
-
178
- ```hash_tree``` provides a method for rendering a subtree as an
179
- ordered nested hash:
180
-
181
- ```ruby
182
- b = Tag.find_or_create_by_path %w(a b)
183
- a = b.parent
184
- b2 = Tag.find_or_create_by_path %w(a b2)
185
- d1 = b.find_or_create_by_path %w(c1 d1)
186
- c1 = d1.parent
187
- d2 = b.find_or_create_by_path %w(c2 d2)
188
- c2 = d2.parent
189
-
190
- Tag.hash_tree
191
- => {a => {b => {c1 => {d1 => {}}, c2 => {d2 => {}}}, b2 => {}}}
192
-
193
- Tag.hash_tree(:limit_depth => 2)
194
- => {a => {b => {}, b2 => {}}}
195
-
196
- b.hash_tree
197
- => {b => {c1 => {d1 => {}}, c2 => {d2 => {}}}}
198
-
199
- b.hash_tree(:limit_depth => 2)
200
- => {b => {c1 => {}, c2 => {}}}
201
- ```
202
-
203
- **If your tree is large (or might become so), use :limit_depth.**
204
-
205
- Without this option, ```hash_tree``` will load the entire contents of that table into RAM. Your
206
- server may not be happy trying to do this.
207
-
208
- HT: [ancestry](https://github.com/stefankroes/ancestry#arrangement) and [elhoyos](https://github.com/mceachen/closure_tree/issues/11)
209
-
210
- ### <a id="options"></a>Available options
211
-
212
- When you include ```acts_as_tree``` in your model, you can provide a hash to override the following defaults:
213
-
214
- * ```:parent_column_name``` to override the column name of the parent foreign key in the model's table. This defaults to "parent_id".
215
- * ```:hierarchy_table_name``` to override the hierarchy class name. This defaults to the singular name of the model + "Hierarchy", like ```TagHierarchy```.
216
- * ```:hierarchy_table_name``` to override the hierarchy table name. This defaults to the singular name of the model + "_hierarchies", like ```tag_hierarchies```.
217
- * ```:dependent``` determines what happens when a node is destroyed. Defaults to ```nullify```.
218
- * ```:nullify``` will simply set the parent column to null. Each child node will be considered a "root" node. This is the default.
219
- * ```:delete_all``` will delete all descendant nodes (which circumvents the destroy hooks)
220
- * ```:destroy``` will destroy all descendant nodes (which runs the destroy hooks on each child node)
221
- * ```:name_column``` used by #```find_or_create_by_path```, #```find_by_path```, and ```ancestry_path``` instance methods. This is primarily useful if the model only has one required field (like a "tag").
222
- * ```:order``` used to set up [deterministic ordering](#deterministic-ordering)
223
-
224
- ## Accessing Data
225
-
226
- ### Class methods
227
-
228
- * ```Tag.root``` returns an arbitrary root node
229
- * ```Tag.roots``` returns all root nodes
230
- * ```Tag.leaves``` returns all leaf nodes
231
- * ```Tag.hash_tree``` returns an [ordered, nested hash](#nested-hashes) that can be depth-limited.
232
- * ```Tag.find_by_path(path)``` returns the node whose name path is ```path```. See (#find_or_create_by_path).
233
- * ```Tag.find_or_create_by_path(path)``` returns the node whose name path is ```path```, and will create the node if it doesn't exist already.See (#find_or_create_by_path).
234
- * ```Tag.find_all_by_generation(generation_level)``` returns the descendant nodes who are ```generation_level``` away from a root. ```Tag.find_all_by_generation(0)``` is equivalent to ```Tag.roots```.
235
-
236
- ### Instance methods
237
-
238
- * ```tag.root``` returns the root for this node
239
- * ```tag.root?``` returns true if this is a root node
240
- * ```tag.child?``` returns true if this is a child node. It has a parent.
241
- * ```tag.leaf?``` returns true if this is a leaf node. It has no children.
242
- * ```tag.leaves``` is scoped to all leaf nodes in self_and_descendants.
243
- * ```tag.depth``` returns the depth, or "generation", for this node in the tree. A root node will have a value of 0.
244
- * ```tag.parent``` returns the node's immediate parent. Root nodes will return nil.
245
- * ```tag.children``` is a ```has_many``` of immediate children (just those nodes whose parent is the current node).
246
- * ```tag.child_ids``` is an array of the IDs of the children.
247
- * ```tag.ancestors``` is a ordered scope of [ parent, grandparent, great grandparent, … ]. Note that the size of this array will always equal ```tag.depth```.
248
- * ```tag.ancestor_ids``` is an array of the IDs of the ancestors.
249
- * ```tag.self_and_ancestors``` returns a scope containing self, parent, grandparent, great grandparent, etc.
250
- * ```tag.siblings``` returns a scope containing all nodes with the same parent as ```tag```, excluding self.
251
- * ```tag.sibling_ids``` returns an array of the IDs of the siblings.
252
- * ```tag.self_and_siblings``` returns a scope containing all nodes with the same parent as ```tag```, including self.
253
- * ```tag.descendants``` returns a scope of all children, childrens' children, etc., excluding self ordered by depth.
254
- * ```tag.descendant_ids``` returns an array of the IDs of the descendants.
255
- * ```tag.self_and_descendants``` returns a scope of all children, childrens' children, etc., including self, ordered by depth.
256
- * ```tag.hash_tree``` returns an [ordered, nested hash](#nested-hashes) that can be depth-limited.
257
- * ```tag.find_by_path(path)``` returns the node whose name path *from ```tag```* is ```path```. See (#find_or_create_by_path).
258
- * ```tag.find_or_create_by_path(path)``` returns the node whose name path *from ```tag```* is ```path```, and will create the node if it doesn't exist already.See (#find_or_create_by_path).
259
- * ```tag.find_all_by_generation(generation_level)``` returns the descendant nodes who are ```generation_level``` away from ```tag```.
260
- * ```tag.find_all_by_generation(0).to_a``` == ```[tag]```
261
- * ```tag.find_all_by_generation(1)``` == ```tag.children```
262
- * ```tag.find_all_by_generation(2)``` will return the tag's grandchildren, and so on.
263
- * ```tag.destroy``` will destroy a node and do <em>something</em> to its children, which is determined by the ```:dependent``` option passed to ```acts_as_tree```.
264
-
265
- ## Polymorphic hierarchies with STI
266
-
267
- Polymorphic models using single table inheritance (STI) are supported:
268
-
269
- 1. Create a db migration that adds a String ```type``` column to your model
270
- 2. Subclass the model class. You only need to add ```acts_as_tree``` to your base class:
271
-
272
- ```ruby
273
- class Tag < ActiveRecord::Base
274
- acts_as_tree
275
- end
276
- class WhenTag < Tag ; end
277
- class WhereTag < Tag ; end
278
- class WhatTag < Tag ; end
279
- ```
280
-
281
- Please note that Rails (<= 3.2) doesn't handle polymorphic associations correctly if
282
- you use the ```:type``` attribute, so **this doesn't work**:
283
-
284
- ```ruby
285
- # BAD: ActiveRecord ignores the :type attribute:
286
- root.children.create(:name => "child", :type => "WhenTag")
287
- ```
288
-
289
- Instead, use either ```.add_child``` or ```children <<```:
290
-
291
- ```ruby
292
- # GOOD!
293
- a = Tag.create!(:name => "a")
294
- b = WhenTag.new(:name => "b")
295
- a.children << b
296
- c = WhatTag.new(:name => "c")
297
- b.add_child(c)
298
- ```
299
-
300
- See [issue 43](https://github.com/mceachen/closure_tree/issues/43) for more information.
301
-
302
- ## Deterministic ordering
303
-
304
- By default, children will be ordered by your database engine, which may not be what you want.
305
-
306
- If you want to order children alphabetically, and your model has a ```name``` column, you'd do this:
307
-
308
- ```ruby
309
- class Tag < ActiveRecord::Base
310
- acts_as_tree :order => 'name'
311
- end
312
- ```
313
-
314
- If you want a specific order, add a new integer column to your model in a migration:
315
-
316
- ```ruby
317
- t.integer :sort_order
318
- ```
319
-
320
- and in your model:
321
-
322
- ```ruby
323
- class OrderedTag < ActiveRecord::Base
324
- acts_as_tree :order => 'sort_order'
325
- end
326
- ```
327
-
328
- When you enable ```order```, you'll also have the following new methods injected into your model:
329
-
330
- * ```tag.siblings_before``` is a scope containing all nodes with the same parent as ```tag```,
331
- whose sort order column is less than ```self```. These will be ordered properly, so the ```last```
332
- element in scope will be the sibling immediately before ```self```
333
- * ```tag.siblings_after``` is a scope containing all nodes with the same parent as ```tag```,
334
- whose sort order column is more than ```self```. These will be ordered properly, so the ```first```
335
- element in scope will be the sibling immediately "after" ```self```
336
-
337
- If your ```order``` column is an integer attribute, you'll also have these:
338
-
339
- * The class method ```#roots_and_descendants_preordered```, which returns all nodes in your tree,
340
- [pre-ordered](http://en.wikipedia.org/wiki/Tree_traversal#Pre-order).
341
-
342
- * ```node1.self_and_descendants_preordered``` which will return descendants,
343
- [pre-ordered](http://en.wikipedia.org/wiki/Tree_traversal#Pre-order).
344
-
345
- * ```node1.prepend_sibling(node2)``` which will
346
- 1. set ```node2``` to the same parent as ```node1```,
347
- 2. set ```node2```'s order column to 1 less than ```node1```'s value, and
348
- 3. decrement the order_column of all children of node1's parents whose order_column is <>>= node2's new value by 1.
349
-
350
- * ```node1.append_sibling(node2)``` which will
351
- 1. set ```node2``` to the same parent as ```node1```,
352
- 2. set ```node2```'s order column to 1 more than ```node1```'s value, and
353
- 3. increment the order_column of all children of node1's parents whose order_column is >= node2's new value by 1.
354
-
355
- ```ruby
356
-
357
- root = OrderedTag.create(:name => "root")
358
- a = OrderedTag.create(:name => "a", :parent => "root")
359
- b = OrderedTag.create(:name => "b")
360
- c = OrderedTag.create(:name => "c")
361
-
362
- # We have to call 'root.reload.children' because root won't be in sync with the database otherwise:
363
-
364
- a.append_sibling(b)
365
- root.reload.children.collect(&:name)
366
- => ["a", "b"]
367
-
368
- a.prepend_sibling(b)
369
- root.reload.children.collect(&:name)
370
- => ["b", "a"]
371
-
372
- a.append_sibling(c)
373
- root.reload.children.collect(&:name)
374
- => ["b", "a", "c"]
375
-
376
- b.append_sibling(c)
377
- root.reload.children.collect(&:name)
378
- => ["b", "c", "a"]
379
- ```
380
-
381
- ## Concurrency
382
-
383
- Several methods, especially ```#rebuild``` and ```#find_or_create_by_path```, cannot run concurrently correctly.
384
- ```#find_or_create_by_path```, for example, may create duplicate nodes.
385
-
386
- Database row-level locks work correctly with PostgreSQL, but MySQL's row-level locking is broken, and
387
- erroneously reports deadlocks where there are none. To work around this, and have a consistent implementation
388
- for both MySQL and PostgreSQL, [with_advisory_lock](https://github.com/mceachen/with_advisory_lock)
389
- is used automatically to ensure correctness.
390
-
391
- If you are already managing concurrency elsewhere in your application, and want to disable the use
392
- of with_advisory_lock, pass ```:with_advisory_lock => false``` in the options hash:
393
-
394
- ```ruby
395
- class Tag
396
- acts_as_tree :with_advisory_lock => false
397
- end
398
- ```
399
-
400
- Note that you *will eventually have data corruption* if you disable advisory locks, write to your
401
- database with multiple threads, and don't provide an alternative mutex.
402
-
403
-
404
- ## FAQ
405
-
406
- ### Does this gem support multiple parents?
407
-
408
- No. This gem's API is based on the assumption that each node has either 0 or 1 parent.
409
-
410
- The underlying closure tree structure will support multiple parents, but there would be many
411
- breaking-API changes to support it. I'm open to suggestions and pull requests.
412
-
413
- ### How do I use this with test fixtures?
414
-
415
- Test fixtures aren't going to be running your ```after_save``` hooks after inserting all your
416
- fixture data, so you need to call ```.rebuild!``` before your test runs. There's an example in
417
- the spec ```tag_spec.rb```:
418
-
419
- ```ruby
420
- describe "Tag with fixtures" do
421
- fixtures :tags
422
- before :each do
423
- Tag.rebuild! # <- required if you use fixtures
424
- end
425
- ```
426
-
427
- **However, if you're just starting with Rails, may I humbly suggest you adopt a factory library**,
428
- rather than using fixtures? [Lots of people have written about this already](https://www.google.com/search?q=fixtures+versus+factories).
429
-
430
-
431
- ## Testing
432
-
433
- Closure tree is [tested under every combination](http://travis-ci.org/#!/mceachen/closure_tree) of
434
-
435
- * Ruby 1.8.7 and Ruby 1.9.3
436
- * The latest Rails 3.0, 3.1, and 3.2 branches, and
437
- * MySQL and PostgreSQL. SQLite works in a single-threaded environment.
438
-
439
- Assuming you're using [rbenv](https://github.com/sstephenson/rbenv), you can use ```tests.sh``` to
440
- run the test matrix locally.
441
-
442
- Parallelism is not tested with Rails 3.0.x nor 3.1.x due to this
443
- [known issue](https://github.com/rails/rails/issues/7538).
444
-
445
- ## Change log
446
-
447
- ### 3.10.0
448
-
449
- * Added ```#roots_and_descendants_preordered```.
450
- Thanks for the suggestion, [Leonel Galan](https://github.com/leonelgalan)!
451
-
452
- ### 3.9.0
453
-
454
- * Added ```.child_ids```.
455
- * Removed ```dependent => destroy``` on the descendant_hierarchy and ancestor_hierarchy collections
456
- (they were a mistake).
457
- * Clarified documentation for creation and child associations.
458
- Because ```Tag.create!(:parent => ...)``` requires a ```.reload```, I removed it as an example.
459
-
460
- All three of these improvements were suggested by Andrew Bromwich. Thanks!
461
-
462
- ### 3.8.2
463
-
464
- * find_by_path uses 1 SELECT now. BOOM.
465
-
466
- ### 3.8.1
467
-
468
- * Double-check locking for find_or_create_by_path
469
-
470
- ### 3.8.0
471
-
472
- * Support for preordered descendants. This requires a numeric sort order column.
473
- Resolves [feature request 38](https://github.com/mceachen/closure_tree/issues/38).
474
- * Moved modules from ```acts_as_tree``` into separate files
475
-
476
- ### 3.7.3
477
-
478
- Due to MySQL's inability to lock rows properly, I've switched to advisory_locks for
479
- all write paths. This will prevent deadlocks, addressing
480
- [issue 41](https://github.com/mceachen/closure_tree/issues/41).
481
-
482
- ### 3.7.2
483
-
484
- * Support for UUID primary keys. Addresses
485
- [issue 40](https://github.com/mceachen/closure_tree/issues/40). Thanks for the pull request,
486
- [Julien](https://github.com/calexicoz)!
487
-
488
- ### 3.7.1
489
-
490
- * Moved requires into ActiveSupport.on_load
491
- * Added ```require 'with_advisory_lock'```
492
-
493
- ### 3.7.0
494
-
495
- **Thread safety!**
496
- * [Advisory locks](https://github.com/mceachen/with_advisory_lock) were
497
- integrated with the class-level ```find_or_create_by_path``` and ```rebuild!```.
498
- * Pessimistic locking is used by the instance-level ```find_or_create_by_path```.
499
-
500
- ### 3.6.9
501
-
502
- * [Don Morrison](https://github.com/elskwid) massaged the [#hash_tree](#nested-hashes) query to
503
- be more efficient, and found a bug in ```hash_tree```'s query that resulted in duplicate rows,
504
- wasting time on the ruby side.
505
-
506
- ### 3.6.7
507
-
508
- * Added workaround for ActiveRecord::Observer usage pre-db-creation. Addresses
509
- [issue 32](https://github.com/mceachen/closure_tree/issues/32).
510
- Thanks, [Don Morrison](https://github.com/elskwid)!
511
-
512
- ### 3.6.6
513
-
514
- * Added support for Rails 4's [strong parameter](https://github.com/rails/strong_parameters).
515
- Thanks, [James Miller](https://github.com/bensie)!
516
-
517
- ### 3.6.5
518
-
519
- * Use ```quote_table_name``` instead of ```quote_column_name```. Addresses
520
- [issue 29](https://github.com/mceachen/closure_tree/issues/29). Thanks,
521
- [Marcello Barnaba](https://github.com/vjt)!
522
-
523
- ### 3.6.4
524
-
525
- * Use ```.pluck``` when available for ```.ids_from```. Addresses
526
- [issue 26](https://github.com/mceachen/closure_tree/issues/26). Thanks,
527
- [Chris Sturgill](https://github.com/sturgill)!
528
-
529
- ### 3.6.3
530
-
531
- * Fixed [issue 24](https://github.com/mceachen/closure_tree/issues/24), which optimized ```#hash_tree```
532
- for roots. Thanks, [Saverio Trioni](https://github.com/rewritten)!
533
-
534
- ### 3.6.2
535
-
536
- * Fixed [issue 23](https://github.com/mceachen/closure_tree/issues/23), which added support for ```#siblings```
537
- when sort_order wasn't specified. Thanks, [Gary Greyling](https://github.com/garygreyling)!
538
-
539
- ### 3.6.1
540
-
541
- * Fixed [issue 20](https://github.com/mceachen/closure_tree/issues/20), which affected
542
- deterministic ordering when siblings where different STI classes. Thanks, [edwinramirez](https://github.com/edwinramirez)!
543
-
544
- ### 3.6.0
545
-
546
- Added support for:
547
- * ```:hierarchy_class_name``` as an option
548
- * ActiveRecord::Base.table_name_prefix
549
- * ActiveRecord::Base.table_name_suffix
550
-
551
- This addresses [issue 21](https://github.com/mceachen/closure_tree/issues/21). Thanks, [Judd Blair](https://github.com/juddblair)!
552
-
553
- ### 3.5.2
554
-
555
- * Added ```find_all_by_generation```
556
- for [feature request 17](https://github.com/mceachen/closure_tree/issues/17).
557
-
558
- ### 3.4.2
559
-
560
- * Fixed [issue 18](https://github.com/mceachen/closure_tree/issues/18), which affected
561
- append_node/prepend_node ordering when the first node didn't have an explicit order_by value
562
-
563
- ### 3.4.1
564
-
565
- * Reverted .gemspec mistake that changed add_development_dependency to add_runtime_dependency
566
-
567
- ### 3.4.0
568
-
569
- Fixed [issue 15](https://github.com/mceachen/closure_tree/issues/15):
570
- * "parent" is now attr_accessible, which adds support for constructor-provided parents.
571
- * updated readme accordingly
572
-
573
- ### 3.3.2
574
-
575
- * Merged calebphillips' patch for a more efficient leaves query
576
-
577
- ### 3.3.1
578
-
579
- * Added support for partially-unsaved hierarchies [issue 13](https://github.com/mceachen/closure_tree/issues/13):
580
- ```
581
- a = Tag.new(name: "a")
582
- b = Tag.new(name: "b")
583
- a.children << b
584
- a.save
585
- ```
586
-
587
- ### 3.3.0
588
-
589
- * Added [```hash_tree```](#nested-hashes).
590
-
591
- ### 3.2.1
592
-
593
- * Added ```ancestor_ids```, ```descendant_ids```, and ```sibling_ids```
594
- * Added example spec to solve [issue 9](https://github.com/mceachen/closure_tree/issues/9)
595
-
596
- ### 3.2.0
597
-
598
- * Added support for deterministic ordering of nodes.
599
-
600
- ### 3.1.0
601
-
602
- * Switched to using ```has_many :though``` rather than ```has_and_belongs_to_many```
603
-
604
- ### 3.0.4
605
-
606
- * Merged [pull request](https://github.com/mceachen/closure_tree/pull/8) to fix ```.siblings``` and ```.self_and_siblings```
607
- (Thanks, [eljojo](https://github.com/eljojo)!)
608
-
609
- ### 3.0.3
610
-
611
- * Added support for ActiveRecord's whitelist_attributes
612
- (Make sure you read [the Rails Security Guide](http://guides.rubyonrails.org/security.html), and
613
- enable ```config.active_record.whitelist_attributes``` in your ```config/application.rb``` ASAP!)
614
-
615
- ### 3.0.2
616
-
617
- * Fix for ancestry-loop detection (performed by a validation, not through raising an exception in before_save)
618
-
619
- ### 3.0.1
620
-
621
- * Support 3.2.0's fickle deprecation of InstanceMethods (Thanks, [jheiss](https://github.com/mceachen/closure_tree/pull/5))!
622
-
623
- ### 3.0.0
624
-
625
- * Support for polymorphic trees
626
- * ```find_by_path``` and ```find_or_create_by_path``` signatures changed to support constructor attributes
627
- * tested against Rails 3.1.3
628
-
629
- ### 2.0.0
630
-
631
- * Had to increment the major version, as rebuild! will need to be called by prior consumers to support the new ```leaves``` class and instance methods.
632
- * Tag deletion is supported now along with ```:dependent => :destroy``` and ```:dependent => :delete_all```
633
- * Switched from default rails plugin directory structure to rspec
634
- * Support for running specs under different database engines: ```export DB ; for DB in sqlite3 mysql postgresql ; do rake ; done```
635
-
636
- ## Thanks to
637
-
638
- * https://github.com/collectiveidea/awesome_nested_set
639
- * https://github.com/patshaughnessy/class_factory
640
- * JetBrains, which provides an [open-source license](http://www.jetbrains.com/ruby/buy/buy.jsp#openSource) to
641
- [RubyMine](http://www.jetbrains.com/ruby/features/) for the development of this project.
@@ -1,26 +0,0 @@
1
- begin
2
- require 'bundler/setup'
3
- rescue LoadError
4
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
- end
6
-
7
- Bundler::GemHelper.install_tasks
8
-
9
- require 'yard'
10
- YARD::Rake::YardocTask.new do |t|
11
- t.files = ['lib/**/*.rb', 'README.md']
12
- end
13
-
14
- require "rspec/core/rake_task"
15
- RSpec::Core::RakeTask.new(:spec)
16
-
17
- task :default => :spec
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
-
25
- # Run the specs using all the different database engines:
26
- # for DB in sqlite3 mysql postgresql ; do rake ; done
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec :path => '..'
3
-
4
- gem 'activerecord', '~> 3.0.0'
5
- gem 'mysql2', '< 0.3.0' # See https://github.com/brianmario/mysql2/issues/155
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec :path => '..'
3
-
4
- gem 'activerecord', '~> 3.1.0'
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec :path => '..'
3
-
4
- gem 'activerecord', '~> 3.2.0'