closure_tree 4.0.0 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +20 -7
- data/lib/closure_tree/model.rb +10 -4
- data/lib/closure_tree/numeric_deterministic_ordering.rb +20 -26
- data/lib/closure_tree/support.rb +10 -13
- data/lib/closure_tree/version.rb +1 -1
- data/spec/label_spec.rb +10 -6
- data/spec/support/models.rb +2 -2
- data/spec/user_spec.rb +2 -2
- metadata +166 -191
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NzBiMzczYWMyY2IwMzMyMGFiMDE4ZWZiZGE5NDdmYjAwNWFlNmY5Ng==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NmNmMDYzNDcwZmM4MzBmNjA4ZTgxOGQxZjFmZGJlMTY5MGFjMTAyYg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YWJmYWZkOWFlMDM2ZGQwZTlmMDZiYjAxOWYwZTJiMGI5NDQ2ZmNjNzliZWY2
|
10
|
+
OTlhYWYxMGViMTY1ZGJmNGE1YzZlM2EwNDA5ZTE3YTZlMDgxOWY1MjA3YjM1
|
11
|
+
NjkxOGIwMjk2NzVmYmIxOGNjY2ZlMDczOWYyNTdkMTYyZmVmMjQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Zjg1MmExYzAxZjc0MDIxOTE3YzczMTllYTc1NGVmZjQyM2JkNTQ5YWE1MDJl
|
14
|
+
MTBlMzUyM2RmZTA3ZTg1MDUyNjY4YzgwMjljOWZmMTAyYWYwMmRjNzlkYThi
|
15
|
+
MTYyMTNhZWQ2ZGQzZmY4YWU5OGQ3NDIyMzYxNjk4ZTliYTNjMjg=
|
data/README.md
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
-
# Closure Tree
|
1
|
+
# Closure Tree
|
2
2
|
|
3
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
4
|
|
5
5
|
Common applications include modeling hierarchical data, like tags, page graphs in CMSes,
|
6
6
|
and tracking user referrals.
|
7
7
|
|
8
|
-
|
9
|
-
[
|
10
|
-
|
11
|
-
|
8
|
+
[![Build Status](https://secure.travis-ci.org/mceachen/closure_tree.png?branch=master)](http://travis-ci.org/mceachen/closure_tree)
|
9
|
+
[![Gem Version](https://badge.fury.io/rb/closure_tree.png)](http://rubygems.org/gems/closure_tree)
|
10
|
+
|
11
|
+
Substantially more efficient than
|
12
|
+
[ancestry](https://github.com/stefankroes/ancestry) and
|
13
|
+
[acts_as_tree](https://github.com/amerine/acts_as_tree), and even more
|
14
|
+
awesome than [awesome_nested_set](https://github.com/collectiveidea/awesome_nested_set/),
|
12
15
|
closure_tree has some great features:
|
13
16
|
|
14
17
|
* __Best-in-class select performance__:
|
@@ -93,8 +96,8 @@ Note that closure_tree only supports Rails 3.0 and later, and has test coverage
|
|
93
96
|
6. Run ```rake db:migrate```
|
94
97
|
|
95
98
|
7. If you're migrating from another system where your model already has a
|
96
|
-
```parent_id``` column, run ```Tag.rebuild!``` and
|
97
|
-
|
99
|
+
```parent_id``` column, run ```Tag.rebuild!``` and your
|
100
|
+
```tag_hierarchies``` table will be truncated and rebuilt.
|
98
101
|
|
99
102
|
If you're starting from scratch you don't need to call ```rebuild!```.
|
100
103
|
|
@@ -444,6 +447,16 @@ Parallelism is not tested with Rails 3.0.x nor 3.1.x due to this
|
|
444
447
|
|
445
448
|
## Change log
|
446
449
|
|
450
|
+
### 4.0.1
|
451
|
+
|
452
|
+
* Numeric, deterministically ordered siblings will always be [0..#{self_and_siblings.count}]
|
453
|
+
(previously, the sort order might use negative values, which broke the preordering).
|
454
|
+
Resolves [issue 49](https://github.com/mceachen/closure_tree/issues/49). Thanks for the help,
|
455
|
+
[Leonel Galan](https://github.com/leonelgalan), [Juan Hoyos](https://github.com/elhoyos), and
|
456
|
+
[Michael Elfassy](https://github.com/elfassy)!
|
457
|
+
|
458
|
+
* The ```order``` option can be a symbol now. Resolves [issue 46](https://github.com/mceachen/closure_tree/issues/46).
|
459
|
+
|
447
460
|
### 4.0.0
|
448
461
|
|
449
462
|
* Moved all of closure_tree's implementation-detail methods into a ```ClosureTree::Support```
|
data/lib/closure_tree/model.rb
CHANGED
@@ -45,6 +45,14 @@ module ClosureTree
|
|
45
45
|
:through => :descendant_hierarchies,
|
46
46
|
:source => :descendant,
|
47
47
|
:order => "#{_ct.quoted_hierarchy_table_name}.generations asc")
|
48
|
+
|
49
|
+
scope :without, lambda { |instance|
|
50
|
+
if instance.new_record?
|
51
|
+
scoped
|
52
|
+
else
|
53
|
+
where(["#{_ct.quoted_table_name}.#{_ct.base_class.primary_key} != ?", instance.id])
|
54
|
+
end
|
55
|
+
}
|
48
56
|
end
|
49
57
|
|
50
58
|
# Delegate to the Support instance on the class:
|
@@ -110,8 +118,7 @@ module ClosureTree
|
|
110
118
|
end
|
111
119
|
|
112
120
|
def self_and_siblings
|
113
|
-
|
114
|
-
_ct.order_option.present? ? s.order(_ct.quoted_order_column) : s
|
121
|
+
_ct.scope_with_order(_ct.base_class.where(_ct.parent_column_sym => parent_id))
|
115
122
|
end
|
116
123
|
|
117
124
|
def siblings
|
@@ -249,8 +256,7 @@ module ClosureTree
|
|
249
256
|
end
|
250
257
|
|
251
258
|
def without_self(scope)
|
252
|
-
|
253
|
-
scope.where(["#{_ct.quoted_table_name}.#{_ct.base_class.primary_key} != ?", self])
|
259
|
+
scope.without(self)
|
254
260
|
end
|
255
261
|
|
256
262
|
module ClassMethods
|
@@ -52,41 +52,35 @@ module ClosureTree
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
def append_sibling(sibling_node
|
56
|
-
add_sibling(sibling_node,
|
55
|
+
def append_sibling(sibling_node)
|
56
|
+
add_sibling(sibling_node, true)
|
57
57
|
end
|
58
58
|
|
59
|
-
def prepend_sibling(sibling_node
|
60
|
-
add_sibling(sibling_node,
|
59
|
+
def prepend_sibling(sibling_node)
|
60
|
+
add_sibling(sibling_node, false)
|
61
61
|
end
|
62
62
|
|
63
|
-
def add_sibling(sibling_node,
|
63
|
+
def add_sibling(sibling_node, add_after = true)
|
64
64
|
fail "can't add self as sibling" if self == sibling_node
|
65
65
|
# issue 40: we need to lock the parent to prevent deadlocks on parallel sibling additions
|
66
66
|
ct_with_advisory_lock do
|
67
|
-
|
68
|
-
|
69
|
-
sibling_node.order_value = self.order_value.to_i + (add_after ? 1 : -1)
|
70
|
-
# We need to incr the before_siblings to make room for sibling_node:
|
71
|
-
if use_update_all
|
72
|
-
col = _ct.quoted_order_column(false)
|
73
|
-
# issue 21: we have to use the base class, so STI doesn't get in the way of only updating the child class instances:
|
74
|
-
_ct.base_class.update_all(
|
75
|
-
["#{col} = #{col} #{add_after ? '+' : '-'} 1", "updated_at = now()"],
|
76
|
-
["#{_ct.quoted_parent_column_name} = ? AND #{col} #{add_after ? '>=' : '<='} ?",
|
77
|
-
parent_id,
|
78
|
-
sibling_node.order_value])
|
79
|
-
else
|
80
|
-
last_value = sibling_node.order_value.to_i
|
81
|
-
(add_after ? siblings_after : siblings_before.reverse).each do |ea|
|
82
|
-
last_value += (add_after ? 1 : -1)
|
83
|
-
ea.order_value = last_value
|
84
|
-
ea.save!
|
85
|
-
end
|
67
|
+
if self.order_value.nil? || siblings_before.without(sibling_node).empty?
|
68
|
+
update_attribute(:order_value, 0)
|
86
69
|
end
|
87
70
|
sibling_node.parent = self.parent
|
88
|
-
|
89
|
-
sibling_node.
|
71
|
+
starting_order_value = self.order_value.to_i
|
72
|
+
to_reorder = siblings_after.without(sibling_node).to_a
|
73
|
+
if add_after
|
74
|
+
to_reorder.unshift(sibling_node)
|
75
|
+
else
|
76
|
+
to_reorder.unshift(self)
|
77
|
+
sibling_node.update_attribute(:order_value, starting_order_value)
|
78
|
+
end
|
79
|
+
|
80
|
+
to_reorder.each_with_index do |ea, idx|
|
81
|
+
ea.update_attribute(:order_value, starting_order_value + idx + 1)
|
82
|
+
end
|
83
|
+
sibling_node.reload # because the parent may have changed.
|
90
84
|
end
|
91
85
|
end
|
92
86
|
end
|
data/lib/closure_tree/support.rb
CHANGED
@@ -13,9 +13,7 @@ module ClosureTree
|
|
13
13
|
:name_column => 'name',
|
14
14
|
:with_advisory_lock => true
|
15
15
|
}.merge(options)
|
16
|
-
|
17
16
|
raise IllegalArgumentException, "name_column can't be 'path'" if options[:name_column] == 'path'
|
18
|
-
|
19
17
|
end
|
20
18
|
|
21
19
|
def connection
|
@@ -101,24 +99,24 @@ module ClosureTree
|
|
101
99
|
connection.quote(field)
|
102
100
|
end
|
103
101
|
|
102
|
+
def order_option?
|
103
|
+
!options[:order].nil?
|
104
|
+
end
|
105
|
+
|
104
106
|
def order_option
|
105
|
-
options[:order]
|
107
|
+
options[:order].to_s
|
106
108
|
end
|
107
109
|
|
108
110
|
def with_order_option(options)
|
109
|
-
order_option ? options.merge(:order => order_option) : options
|
111
|
+
order_option? ? options.merge(:order => order_option) : options
|
110
112
|
end
|
111
113
|
|
112
114
|
def scope_with_order(scope, additional_order_by = nil)
|
113
|
-
|
114
|
-
scope.order(*([additional_order_by, order_option].compact))
|
115
|
-
else
|
116
|
-
scope
|
117
|
-
end
|
115
|
+
order_option? ? scope.order(*([additional_order_by, order_option].compact)) : scope
|
118
116
|
end
|
119
117
|
|
120
118
|
def with_order_option(options)
|
121
|
-
if order_option
|
119
|
+
if order_option?
|
122
120
|
options[:order] = [options[:order], order_option].compact.join(",")
|
123
121
|
end
|
124
122
|
options
|
@@ -126,14 +124,13 @@ module ClosureTree
|
|
126
124
|
|
127
125
|
def order_is_numeric?
|
128
126
|
# The table might not exist yet (in the case of ActiveRecord::Observer use, see issue 32)
|
129
|
-
return false if order_option
|
127
|
+
return false if !order_option? || !model_class.table_exists?
|
130
128
|
c = model_class.columns_hash[order_option]
|
131
129
|
c && c.type == :integer
|
132
130
|
end
|
133
131
|
|
134
132
|
def order_column
|
135
|
-
|
136
|
-
o.split(' ', 2).first if o
|
133
|
+
order_option.split(' ', 2).first if order_option?
|
137
134
|
end
|
138
135
|
|
139
136
|
def require_order_column
|
data/lib/closure_tree/version.rb
CHANGED
data/spec/label_spec.rb
CHANGED
@@ -230,7 +230,7 @@ describe Label do
|
|
230
230
|
end
|
231
231
|
|
232
232
|
it "when inserted before" do
|
233
|
-
@b.append_sibling(@a
|
233
|
+
@b.append_sibling(@a)
|
234
234
|
# Have to reload because the sort_order will have changed out from under the references:
|
235
235
|
@b.reload.sort_order.should be < @a.reload.sort_order
|
236
236
|
@a.reload.sort_order.should be < @c.reload.sort_order
|
@@ -245,15 +245,19 @@ describe Label do
|
|
245
245
|
|
246
246
|
a.append_sibling(b)
|
247
247
|
root.reload.children.collect(&:name).should == %w(a b)
|
248
|
+
root.reload.children.collect(&:sort_order).should == [0, 1]
|
248
249
|
|
249
250
|
a.prepend_sibling(b)
|
250
251
|
root.reload.children.collect(&:name).should == %w(b a)
|
252
|
+
root.reload.children.collect(&:sort_order).should == [0, 1]
|
251
253
|
|
252
254
|
a.append_sibling(c)
|
253
255
|
root.reload.children.collect(&:name).should == %w(b a c)
|
256
|
+
root.reload.children.collect(&:sort_order).should == [0, 1, 2]
|
254
257
|
|
255
258
|
b.append_sibling(c)
|
256
259
|
root.reload.children.collect(&:name).should == %w(b c a)
|
260
|
+
root.reload.children.collect(&:sort_order).should == [0, 1, 2]
|
257
261
|
end
|
258
262
|
|
259
263
|
context "Deterministic siblings sort with custom integer column" do
|
@@ -280,9 +284,9 @@ describe Label do
|
|
280
284
|
end
|
281
285
|
|
282
286
|
it "should prepend a node as a sibling of another node (!update_all)" do
|
283
|
-
labels(:c16).prepend_sibling(labels(:c17)
|
287
|
+
labels(:c16).prepend_sibling(labels(:c17))
|
284
288
|
labels(:c16).self_and_siblings.to_a.should == [labels(:c17), labels(:c16), labels(:c18), labels(:c19)]
|
285
|
-
labels(:c19).reload.prepend_sibling(labels(:c16).reload
|
289
|
+
labels(:c19).reload.prepend_sibling(labels(:c16).reload)
|
286
290
|
labels(:c16).self_and_siblings.to_a.should == [labels(:c17), labels(:c18), labels(:c16), labels(:c19)]
|
287
291
|
labels(:c16).siblings_before.to_a.should == [labels(:c17), labels(:c18)]
|
288
292
|
labels(:c16).siblings_after.to_a.should == [labels(:c19)]
|
@@ -316,7 +320,7 @@ describe Label do
|
|
316
320
|
|
317
321
|
it "should move a node before another node" do
|
318
322
|
labels(:c2).ancestry_path.should == %w{a1 b2 c2}
|
319
|
-
labels(:b2).prepend_sibling(labels(:c2)
|
323
|
+
labels(:b2).prepend_sibling(labels(:c2))
|
320
324
|
labels(:c2).ancestry_path.should == %w{a1 c2}
|
321
325
|
labels(:c2).self_and_siblings.to_a.should == [labels(:b1), labels(:c2), labels(:b2)]
|
322
326
|
end
|
@@ -343,10 +347,10 @@ describe Label do
|
|
343
347
|
|
344
348
|
it "should move a node after another node" do
|
345
349
|
labels(:c2).ancestry_path.should == %w{a1 b2 c2}
|
346
|
-
labels(:b2).append_sibling(labels(:c2)
|
350
|
+
labels(:b2).append_sibling(labels(:c2))
|
347
351
|
labels(:c2).ancestry_path.should == %w{a1 c2}
|
348
352
|
labels(:c2).self_and_siblings.to_a.should == [labels(:b1), labels(:b2), labels(:c2)]
|
349
|
-
labels(:c2).append_sibling(labels(:e2)
|
353
|
+
labels(:c2).append_sibling(labels(:e2))
|
350
354
|
labels(:e2).self_and_siblings.to_a.should == [labels(:b1), labels(:b2), labels(:c2), labels(:e2)]
|
351
355
|
labels(:a1).self_and_descendants.collect(&:name).should == %w(a1 b1 b2 c2 e2 d2 c1-six c1-seven c1-eight c1-nine)
|
352
356
|
labels(:a1).leaves.collect(&:name).should == %w(b2 e2 d2 c1-six c1-seven c1-eight c1-nine)
|
data/spec/support/models.rb
CHANGED
@@ -43,8 +43,8 @@ class Contract < ActiveRecord::Base
|
|
43
43
|
end
|
44
44
|
|
45
45
|
class Label < ActiveRecord::Base
|
46
|
-
attr_accessible :name #
|
47
|
-
acts_as_tree :order =>
|
46
|
+
attr_accessible :name # <- make sure order doesn't matter
|
47
|
+
acts_as_tree :order => :sort_order, # <- LOOK IT IS A SYMBOL OMG
|
48
48
|
:parent_column_name => "mother_id",
|
49
49
|
:dependent => :destroy
|
50
50
|
|
data/spec/user_spec.rb
CHANGED
@@ -116,7 +116,7 @@ describe "empty db" do
|
|
116
116
|
end
|
117
117
|
|
118
118
|
it "supports siblings" do
|
119
|
-
User._ct.order_option
|
119
|
+
User._ct.order_option?.should be_false
|
120
120
|
a = User.create(:email => "a")
|
121
121
|
b1 = a.children.create(:email => "b1")
|
122
122
|
b2 = a.children.create(:email => "b2")
|
@@ -127,7 +127,7 @@ describe "empty db" do
|
|
127
127
|
|
128
128
|
context "when a user is not yet saved" do
|
129
129
|
it "supports siblings" do
|
130
|
-
User._ct.order_option
|
130
|
+
User._ct.order_option?.should be_false
|
131
131
|
a = User.create(:email => "a")
|
132
132
|
b1 = a.children.new(:email => "b1")
|
133
133
|
b2 = a.children.create(:email => "b2")
|
metadata
CHANGED
@@ -1,205 +1,190 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: closure_tree
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 4
|
8
|
-
- 0
|
9
|
-
- 0
|
10
|
-
version: 4.0.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 4.0.1
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Matthew McEachen
|
14
8
|
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
hash: 7
|
28
|
-
segments:
|
29
|
-
- 3
|
30
|
-
- 0
|
31
|
-
- 0
|
11
|
+
date: 2013-05-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
32
19
|
version: 3.0.0
|
33
20
|
type: :runtime
|
34
|
-
name: activerecord
|
35
|
-
version_requirements: *id001
|
36
21
|
prerelease: false
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: with_advisory_lock
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
48
33
|
version: 0.0.6
|
49
34
|
type: :runtime
|
50
|
-
name: with_advisory_lock
|
51
|
-
version_requirements: *id002
|
52
35
|
prerelease: false
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
hash: 3
|
60
|
-
segments:
|
61
|
-
- 0
|
62
|
-
version: "0"
|
63
|
-
type: :development
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.6
|
41
|
+
- !ruby/object:Gem::Dependency
|
64
42
|
name: rake
|
65
|
-
|
66
|
-
|
67
|
-
- !
|
68
|
-
|
69
|
-
|
70
|
-
requirements:
|
71
|
-
- - ">="
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
hash: 3
|
74
|
-
segments:
|
75
|
-
- 0
|
76
|
-
version: "0"
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
77
48
|
type: :development
|
78
|
-
name: yard
|
79
|
-
version_requirements: *id004
|
80
49
|
prerelease: false
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
91
62
|
type: :development
|
92
|
-
name: rspec
|
93
|
-
version_requirements: *id005
|
94
63
|
prerelease: false
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
105
76
|
type: :development
|
106
|
-
name: rails
|
107
|
-
version_requirements: *id006
|
108
77
|
prerelease: false
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
119
90
|
type: :development
|
120
|
-
name: rspec-rails
|
121
|
-
version_requirements: *id007
|
122
91
|
prerelease: false
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
133
104
|
type: :development
|
134
|
-
name: mysql2
|
135
|
-
version_requirements: *id008
|
136
105
|
prerelease: false
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: mysql2
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
147
118
|
type: :development
|
148
|
-
name: pg
|
149
|
-
version_requirements: *id009
|
150
119
|
prerelease: false
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pg
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
161
132
|
type: :development
|
162
|
-
name: sqlite3
|
163
|
-
version_requirements: *id010
|
164
133
|
prerelease: false
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sqlite3
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
175
146
|
type: :development
|
176
|
-
name: uuidtools
|
177
|
-
version_requirements: *id011
|
178
147
|
prerelease: false
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ! '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: uuidtools
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ! '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
189
160
|
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ! '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
190
168
|
name: strong_parameters
|
191
|
-
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
192
175
|
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ! '>='
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
193
181
|
description: Easily and efficiently make your ActiveRecord model support hierarchies
|
194
|
-
email:
|
182
|
+
email:
|
195
183
|
- matthew-github@mceachen.org
|
196
184
|
executables: []
|
197
|
-
|
198
185
|
extensions: []
|
199
|
-
|
200
186
|
extra_rdoc_files: []
|
201
|
-
|
202
|
-
files:
|
187
|
+
files:
|
203
188
|
- lib/closure_tree/acts_as_tree.rb
|
204
189
|
- lib/closure_tree/deterministic_ordering.rb
|
205
190
|
- lib/closure_tree/model.rb
|
@@ -225,41 +210,30 @@ files:
|
|
225
210
|
- spec/support/models.rb
|
226
211
|
- spec/tag_spec.rb
|
227
212
|
- spec/user_spec.rb
|
228
|
-
has_rdoc: true
|
229
213
|
homepage: http://matthew.mceachen.us/closure_tree
|
230
214
|
licenses: []
|
231
|
-
|
215
|
+
metadata: {}
|
232
216
|
post_install_message:
|
233
217
|
rdoc_options: []
|
234
|
-
|
235
|
-
require_paths:
|
218
|
+
require_paths:
|
236
219
|
- lib
|
237
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
none: false
|
248
|
-
requirements:
|
249
|
-
- - ">="
|
250
|
-
- !ruby/object:Gem::Version
|
251
|
-
hash: 3
|
252
|
-
segments:
|
253
|
-
- 0
|
254
|
-
version: "0"
|
220
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - ! '>='
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: '0'
|
225
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ! '>='
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
255
230
|
requirements: []
|
256
|
-
|
257
231
|
rubyforge_project:
|
258
|
-
rubygems_version:
|
232
|
+
rubygems_version: 2.0.3
|
259
233
|
signing_key:
|
260
|
-
specification_version:
|
234
|
+
specification_version: 4
|
261
235
|
summary: Easily and efficiently make your ActiveRecord model support hierarchies
|
262
|
-
test_files:
|
236
|
+
test_files:
|
263
237
|
- spec/cuisine_type_spec.rb
|
264
238
|
- spec/db/database.yml
|
265
239
|
- spec/db/schema.rb
|
@@ -274,3 +248,4 @@ test_files:
|
|
274
248
|
- spec/support/models.rb
|
275
249
|
- spec/tag_spec.rb
|
276
250
|
- spec/user_spec.rb
|
251
|
+
has_rdoc:
|