acts_as_many_trees 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/acts_as_many_trees/base.rb +19 -10
- data/lib/acts_as_many_trees/hierarchy_table.rb +142 -41
- data/lib/acts_as_many_trees/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 633c463bad4d37f9c467cba4852ebcbdc10cb87b
|
4
|
+
data.tar.gz: e18295cde70abd5712d5bf316584ced556d321a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2319dc68f438895276c0d6072df2ec3cd56c79376958e3f338c97590a960a2241a6c455ae52b18c742eeed84a63a3fdf15115c2ff342dc0e1226f94e296c1aef
|
7
|
+
data.tar.gz: b3dd7f7a3720dcf927927d51d071a425017fc4276559cb5fb6a1f764e01fcbad7bc42305260e8545dcbd8e4575df890542624f47de3146436de03f587505d3b4
|
@@ -61,12 +61,19 @@ module ActsAsManyTrees
|
|
61
61
|
}
|
62
62
|
|
63
63
|
scope :roots , ->(tree_name=self.default_tree_name){
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
h1 = hierarchy_class.arel_table
|
65
|
+
h2 = hierarchy_class.arel_table.alias
|
66
|
+
on1 = Arel::Nodes::On.new(Arel::Nodes::Equality.new(arel_table[:id],h1[:descendant_id])
|
67
|
+
.and(h1[:hierarchy_scope].eq(tree_name))
|
68
|
+
.and(h1[:generation].eq(0))
|
67
69
|
)
|
68
|
-
|
69
|
-
|
70
|
+
on2 = Arel::Nodes::On.new(Arel::Nodes::Equality.new(h1[:ancestor_id],h2[:descendant_id])
|
71
|
+
.and(Arel::Nodes::Equality.new(h1[:hierarchy_scope],h2[:hierarchy_scope]))
|
72
|
+
.and(h2[:generation].not_eq(0))
|
73
|
+
)
|
74
|
+
inner_join = Arel::Nodes::InnerJoin.new(h1,on1)
|
75
|
+
outer_join = Arel::Nodes::OuterJoin.new(h2,on2)
|
76
|
+
joins(inner_join).joins(outer_join).merge(where(Arel::Nodes::Equality.new(h2[:ancestor_id],nil)))
|
70
77
|
}
|
71
78
|
scope :not_this,->(this_id) { where.not(id: this_id)}
|
72
79
|
end
|
@@ -81,22 +88,24 @@ module ActsAsManyTrees
|
|
81
88
|
new_parent=inpt_parent[:new_parent]
|
82
89
|
after_node=inpt_parent[:after_node]
|
83
90
|
before_node=inpt_parent[:before_node]
|
84
|
-
tree_name=inpt_parent[:tree_name] ||
|
91
|
+
tree_name = inpt_parent[:tree_name] || (new_parent ? new_parent.default_tree_name : self.default_tree_name)
|
92
|
+
existing_tree_name = inpt_parent[:existing_tree_name] || self.default_tree_name
|
85
93
|
else
|
86
94
|
new_parent=inpt_parent
|
87
95
|
after_node=inpt_parent.children.last unless inpt_parent.nil?
|
88
96
|
before_node=inpt_parent.next_sibling unless inpt_parent.nil?
|
89
97
|
tree_name = inpt_parent ? inpt_parent.default_tree_name : self.default_tree_name
|
98
|
+
existing_tree_name = self.default_tree_name
|
90
99
|
end
|
91
|
-
hierarchy_class.set_parent_of(self,new_parent,tree_name,after_node,before_node)
|
100
|
+
hierarchy_class.set_parent_of(item:self,new_parent:new_parent,hierarchy_scope:tree_name,existing_scope:existing_tree_name,after_node:after_node,before_node:before_node)
|
92
101
|
end
|
93
102
|
|
94
|
-
def set_parent(new_parent
|
95
|
-
hierarchy_class.set_parent_of(self,new_parent,tree_name)
|
103
|
+
def set_parent(new_parent:,tree_name:self.default_tree_name,existing_tree:self.default_tree_name,clone_sub_tree:false)
|
104
|
+
hierarchy_class.set_parent_of(item:self,new_parent:new_parent,hierarchy_scope:tree_name,existing_scope:existing_tree,clone_sub_tree:clone_sub_tree)
|
96
105
|
end
|
97
106
|
|
98
107
|
def add_child(new_child,tree_name=self.default_tree_name)
|
99
|
-
hierarchy_class.set_parent_of(new_child,self,tree_name)
|
108
|
+
hierarchy_class.set_parent_of(item:new_child,new_parent:self,hierarchy_scope:tree_name)
|
100
109
|
end
|
101
110
|
|
102
111
|
def parent(tree_name=self.default_tree_name)
|
@@ -63,7 +63,7 @@ module ActsAsManyTrees
|
|
63
63
|
scope :roots,->do
|
64
64
|
t1 = arel_table
|
65
65
|
t2 = arel_table.alias
|
66
|
-
t1.project(Arel::star).join(t2,Arel::Nodes::OuterJoin)
|
66
|
+
j=t1.project(Arel::star).join(t2,Arel::Nodes::OuterJoin)
|
67
67
|
.on(t1[:ancestor_id]
|
68
68
|
.eq(t2[:descendant_id])
|
69
69
|
.and(t1[:hierarchy_scope].eq(t2[:hierarchy_scope])
|
@@ -71,6 +71,7 @@ module ActsAsManyTrees
|
|
71
71
|
)
|
72
72
|
.where(t2[:ancestor_id].eq(nil)
|
73
73
|
)
|
74
|
+
joins(j)
|
74
75
|
end
|
75
76
|
scope :self_and_siblings, ->(item,hierarchy_scope='')do
|
76
77
|
joins(:siblings)
|
@@ -79,7 +80,7 @@ module ActsAsManyTrees
|
|
79
80
|
joins(:siblings).where(:position,lt(rec.position))
|
80
81
|
end
|
81
82
|
|
82
|
-
def self.set_parent_of(item
|
83
|
+
def self.set_parent_of(item:,new_parent:,hierarchy_scope:'',existing_scope:'',clone_sub_tree:false,after_node:nil,before_node:nil)
|
83
84
|
if new_parent
|
84
85
|
wrk_parent = self.find_by(descendant_id:new_parent.id,ancestor_id:new_parent.id,generation: 0,hierarchy_scope: hierarchy_scope)
|
85
86
|
unless wrk_parent
|
@@ -87,6 +88,9 @@ module ActsAsManyTrees
|
|
87
88
|
wrk_parent=self.create(descendant_id:new_parent.id,ancestor_id:new_parent.id,generation: 0,hierarchy_scope: hierarchy_scope,position: position)
|
88
89
|
end
|
89
90
|
end
|
91
|
+
# puts 'ppppppppppp'
|
92
|
+
# debug_tree('')
|
93
|
+
# puts 'pppppppp'
|
90
94
|
if item
|
91
95
|
after_position = after_this(wrk_parent,after_node,hierarchy_scope)
|
92
96
|
before_position = before_this(before_node,hierarchy_scope)
|
@@ -100,14 +104,44 @@ module ActsAsManyTrees
|
|
100
104
|
temp_name = SecureRandom.hex
|
101
105
|
# BEWARE this works when added default trees and adding default trees to a new scope but it won't work when moving
|
102
106
|
# items within a named tree or when adding items from one named scope to another
|
103
|
-
|
104
|
-
|
105
|
-
|
107
|
+
# puts "hierarchy_scope #{hierarchy_scope} existing_scope #{existing_scope}"
|
108
|
+
if (hierarchy_scope != existing_scope)
|
109
|
+
# debug_tree(existing_scope)
|
110
|
+
# debug_tree(hierarchy_scope)
|
111
|
+
# debug_tree(temp_name)
|
112
|
+
if clone_sub_tree
|
113
|
+
clone_sub_tree(item:wrk_item,temp_name:temp_name,existing_name:existing_scope)
|
114
|
+
else
|
115
|
+
clone_item_only(item:wrk_item,new_parent:wrk_parent,hierarchy_scope:temp_name)
|
116
|
+
end
|
117
|
+
add_all_ancestors(wrk_item,wrk_parent,temp_name)
|
118
|
+
# debug_tree(temp_name)
|
119
|
+
else
|
120
|
+
# debug_tree
|
121
|
+
# debug_tree(temp_name)
|
122
|
+
# # add_all_ancestors(wrk_item,wrk_parent,temp_name)
|
123
|
+
# puts wrk_item.attributes
|
124
|
+
# puts wrk_parent.attributes
|
125
|
+
create_tree(wrk_item:wrk_item,wrk_parent:wrk_parent,temp_name:temp_name)
|
126
|
+
# debug_tree(temp_name)
|
127
|
+
# delete_item_ancestors(wrk_item)
|
128
|
+
#where({descendant_id: wrk_item.descendant_id,hierarchy_scope: hierarchy_scope }).delete_all
|
129
|
+
# delete_ancestors(wrk_item,wrk_item.hierarchy_scope)
|
130
|
+
delete_ancestors_of_item_children(wrk_item,hierarchy_scope)
|
131
|
+
end
|
106
132
|
reset_descendant_position(wrk_item,before_position,temp_name)
|
107
133
|
rename_tree(temp_name,hierarchy_scope)
|
134
|
+
# debug_tree('')
|
135
|
+
# puts "***************\n\n"
|
108
136
|
end
|
109
137
|
end
|
110
138
|
|
139
|
+
def self.debug_tree(hierarchy_scope='')
|
140
|
+
puts '======================'
|
141
|
+
self.where(hierarchy_scope:hierarchy_scope).order([:ancestor_id,:generation]).each{|r| puts r.attributes}
|
142
|
+
puts '**********************'
|
143
|
+
end
|
144
|
+
|
111
145
|
private
|
112
146
|
# the new position is after the maximum of the after_node, the parent, the current maximum of all
|
113
147
|
def self.after_this(wrk_parent,after_node,hierarchy_scope)
|
@@ -131,51 +165,110 @@ module ActsAsManyTrees
|
|
131
165
|
position
|
132
166
|
end
|
133
167
|
|
134
|
-
def self.
|
135
|
-
|
136
|
-
|
137
|
-
|
168
|
+
def self.clone_item_only(item:,new_parent:,hierarchy_scope:)
|
169
|
+
sql=<<-SQL
|
170
|
+
insert into #{table_name}(ancestor_id,descendant_id,generation,hierarchy_scope,position)
|
171
|
+
select b.ancestor_id,a.descendant_id,b.generation+1,'#{hierarchy_scope}',a.position
|
172
|
+
from #{table_name} a,#{table_name} b
|
173
|
+
where b.descendant_id = #{new_parent.descendant_id}
|
174
|
+
and a.descendant_id = #{item.descendant_id}
|
175
|
+
and a.hierarchy_scope = '#{item.hierarchy_scope}'
|
176
|
+
and a.hierarchy_scope = b.hierarchy_scope
|
177
|
+
and a.generation = 0
|
178
|
+
SQL
|
179
|
+
connection.execute(sql)
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.clone_sub_tree(item:,temp_name:,existing_name:'')
|
183
|
+
sql=<<-SQL
|
184
|
+
insert into #{table_name}(ancestor_id,descendant_id,generation,hierarchy_scope,position)
|
185
|
+
WITH RECURSIVE sub_trees(ancestor_id,descendant_id,generation,hierarchy_scope,position) AS
|
186
|
+
(select ancestor_id,descendant_id,generation,'#{temp_name}',position from #{table_name}
|
187
|
+
where descendant_id = #{item.descendant_id}
|
188
|
+
and hierarchy_scope = '#{existing_name}'
|
189
|
+
UNION
|
190
|
+
select s.ancestor_id,s.descendant_id,
|
191
|
+
s.generation,'#{temp_name}',s.position
|
192
|
+
from #{table_name} s, sub_trees st
|
193
|
+
where s.ancestor_id = st.descendant_id
|
194
|
+
and s.hierarchy_scope = '#{existing_name}'
|
195
|
+
)
|
196
|
+
select * from sub_trees;
|
197
|
+
SQL
|
198
|
+
connection.execute(sql)
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.add_all_ancestors(item,parent,temp_name)
|
202
|
+
sql=<<-SQL
|
138
203
|
insert into #{table_name}(ancestor_id,descendant_id,generation,hierarchy_scope,position)
|
139
204
|
select a.ancestor_id,b.descendant_id,a.generation+b.generation+1,'#{temp_name}',b.position
|
140
205
|
from #{table_name} a, #{table_name} b
|
141
|
-
where a.descendant_id=#{
|
142
|
-
and b.ancestor_id=#{
|
143
|
-
and
|
144
|
-
and a.hierarchy_scope = '#{
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
and
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
206
|
+
where a.descendant_id=#{parent.descendant_id}
|
207
|
+
and b.ancestor_id=#{item.descendant_id}
|
208
|
+
and b.hierarchy_scope = '#{temp_name}'
|
209
|
+
and a.hierarchy_scope = '#{parent.hierarchy_scope}'
|
210
|
+
SQL
|
211
|
+
connection.execute(sql)
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.create_tree(wrk_item:,wrk_parent:,temp_name:)
|
215
|
+
if wrk_parent
|
216
|
+
# if existing_name != wrk_item.hierarchy_scope
|
217
|
+
# puts 'new hierarchy'
|
218
|
+
# sql=<<-SQL
|
219
|
+
# insert into #{table_name}(ancestor_id,descendant_id,generation,hierarchy_scope,position)
|
220
|
+
# select a.ancestor_id,b.descendant_id,a.generation+b.generation+1,'#{temp_name}',b.position
|
221
|
+
# from #{table_name} a, #{table_name} b
|
222
|
+
# where a.descendant_id=#{wrk_parent.descendant_id}
|
223
|
+
# and b.ancestor_id=#{wrk_item.ancestor_id}
|
224
|
+
# and a.hierarchy_scope = b.hierarchy_scope
|
225
|
+
# and a.hierarchy_scope = '#{wrk_item.hierarchy_scope}'
|
226
|
+
# union
|
227
|
+
# select c.ancestor_id,c.descendant_id,c.generation,'#{temp_name}',c.position
|
228
|
+
# from #{table_name} c
|
229
|
+
# where c.ancestor_id = #{wrk_item.descendant_id}
|
230
|
+
# and c.hierarchy_scope = '#{wrk_item.hierarchy_scope}'
|
231
|
+
# union
|
232
|
+
# select c.ancestor_id,c.descendant_id,c.generation,'#{temp_name}',c.position
|
233
|
+
# from #{table_name} c
|
234
|
+
# where c.ancestor_id = #{wrk_item.descendant_id}
|
235
|
+
# and c.ancestor_id <> c.descendant_id
|
236
|
+
# and c.hierarchy_scope = '#{existing_name}'
|
237
|
+
# union
|
238
|
+
# select #{wrk_parent.descendant_id},c.descendant_id,#{wrk_parent.generation}+c.generation+1,'#{temp_name}',c.position
|
239
|
+
# from #{table_name} c
|
240
|
+
# where c.ancestor_id = #{wrk_item.descendant_id}
|
241
|
+
# and c.ancestor_id <> c.descendant_id
|
242
|
+
# and c.hierarchy_scope = '#{existing_name}'
|
243
|
+
# /* add existing descendants of descendants in the new tree */
|
244
|
+
# union
|
245
|
+
# select c.ancestor_id,c.descendant_id,c.generation,'#{temp_name}',c.position
|
246
|
+
# from #{table_name} c, #{table_name} d
|
247
|
+
# where c.ancestor_id = d.descendant_id
|
248
|
+
# and d.ancestor_id =#{wrk_item.descendant_id}
|
249
|
+
# and d.hierarchy_scope = c.hierarchy_scope
|
250
|
+
# and c.ancestor_id != c.descendant_id
|
251
|
+
# and c.hierarchy_scope = '#{existing_name}'
|
252
|
+
# SQL
|
253
|
+
# else
|
254
|
+
sql=<<-SQL
|
165
255
|
insert into #{table_name}(ancestor_id,descendant_id,generation,hierarchy_scope,position)
|
256
|
+
/* add self and descendants to the new parent */
|
166
257
|
select a.ancestor_id,b.descendant_id,a.generation+b.generation+1,'#{temp_name}',b.position
|
167
258
|
from #{table_name} a, #{table_name} b
|
168
259
|
where a.descendant_id=#{wrk_parent.descendant_id}
|
169
260
|
and b.ancestor_id=#{wrk_item.ancestor_id}
|
170
261
|
and a.hierarchy_scope = b.hierarchy_scope
|
171
262
|
and a.hierarchy_scope = '#{wrk_item.hierarchy_scope}'
|
263
|
+
|
264
|
+
/* add existing descendants in the new tree */
|
172
265
|
union
|
173
266
|
select c.ancestor_id,c.descendant_id,c.generation,'#{temp_name}',c.position
|
174
267
|
from #{table_name} c
|
175
268
|
where c.ancestor_id = #{wrk_item.descendant_id}
|
176
269
|
and c.hierarchy_scope = '#{wrk_item.hierarchy_scope}'
|
177
|
-
|
178
|
-
|
270
|
+
|
271
|
+
SQL
|
179
272
|
else
|
180
273
|
sql=<<-SQL
|
181
274
|
insert into #{table_name}(ancestor_id,descendant_id,generation,hierarchy_scope,position)
|
@@ -203,25 +296,33 @@ module ActsAsManyTrees
|
|
203
296
|
|
204
297
|
def self.rename_tree(old_name,new_name)
|
205
298
|
sql=<<-SQL
|
206
|
-
update #{table_name}
|
299
|
+
update #{table_name} h1
|
207
300
|
set hierarchy_scope='#{new_name}'
|
208
301
|
where hierarchy_scope='#{old_name}'
|
302
|
+
and not exists(select h2.ancestor_id from #{table_name} h2
|
303
|
+
where h1.ancestor_id = h2.ancestor_id
|
304
|
+
and h1.descendant_id = h2.descendant_id
|
305
|
+
and h2.hierarchy_scope = '#{new_name}'
|
306
|
+
)
|
209
307
|
SQL
|
210
308
|
connection.execute(sql)
|
211
309
|
end
|
212
310
|
|
213
|
-
def self.delete_ancestors(item,hierarchy_scope)
|
214
|
-
|
311
|
+
def self.delete_ancestors(item,hierarchy_scope='')
|
312
|
+
puts "#{item.id}"
|
313
|
+
self.delete(descendant_id: item.id,hierarchy_scope: hierarchy_scope )
|
215
314
|
end
|
216
315
|
|
217
316
|
def self.delete_ancestors_of_item_children(item,hierarchy_scope)
|
218
317
|
sql = <<-SQL
|
219
|
-
delete from #{table_name} as p using #{table_name} as p1
|
318
|
+
delete from #{table_name} as p using #{table_name} as p1, #{table_name} as p2
|
220
319
|
where p.descendant_id = p1.descendant_id
|
221
|
-
and
|
320
|
+
and p.ancestor_id = p2.ancestor_id
|
321
|
+
and p2.descendant_id = #{item.descendant_id}
|
322
|
+
and p1.ancestor_id = p2.descendant_id
|
323
|
+
and p2.hierarchy_scope = p1.hierarchy_scope
|
222
324
|
and p.hierarchy_scope = p1.hierarchy_scope
|
223
325
|
and p1.hierarchy_scope = '#{hierarchy_scope}'
|
224
|
-
and p.generation > 0
|
225
326
|
SQL
|
226
327
|
connection.execute(sql)
|
227
328
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_many_trees
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Small
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|