simple_nested_set 0.0.24 → 0.0.25

Sign up to get free protection for your applications and to get access to all the features.
@@ -37,12 +37,20 @@ module SimpleNestedSet
37
37
  where(:parent_id => parent_id).order(:lft)
38
38
  end
39
39
 
40
- def with_ancestors(lft, rgt)
41
- where(arel_table[:lft].lt(lft).and(arel_table[:rgt].gt(rgt))).order(:lft)
40
+ def with_ancestors(lft, rgt, opts = {})
41
+ if opts.fetch(:include_self, false)
42
+ where(arel_table[:lft].lteq(lft).and(arel_table[:rgt].gteq(rgt))).order(:lft)
43
+ else
44
+ where(arel_table[:lft].lt(lft).and(arel_table[:rgt].gt(rgt))).order(:lft)
45
+ end
42
46
  end
43
47
 
44
- def with_descendants(lft, rgt)
45
- where(arel_table[:lft].gt(lft).and(arel_table[:rgt].lt(rgt))).order(:lft)
48
+ def with_descendants(lft, rgt, opts = {})
49
+ if opts.fetch(:include_self, false)
50
+ where(arel_table[:lft].gteq(lft).and(arel_table[:rgt].lteq(rgt))).order(:lft)
51
+ else
52
+ where(arel_table[:lft].gt(lft).and(arel_table[:rgt].lt(rgt))).order(:lft)
53
+ end
46
54
  end
47
55
 
48
56
  def with_left_sibling(lft)
@@ -57,5 +65,18 @@ module SimpleNestedSet
57
65
  # where("#{arel_table[:lft].to_sql} = #{arel_table[:rgt].to_sql} - 1").order(:lft)
58
66
  where("#{arel_table.name}.lft = #{arel_table.name}.rgt - 1").order(:lft)
59
67
  end
68
+
69
+ def nested_set_transaction(sort_order = :id)
70
+ begin
71
+ nested_set_class.move_after_save = false
72
+ self.transaction do
73
+ yield self
74
+ # nested_set_class.new(self).rebuild_by_parents!
75
+ Rebuild::FromParents.new.run(self, sort_order)
76
+ end
77
+ ensure
78
+ nested_set_class.move_after_save = true
79
+ end
80
+ end
60
81
  end
61
82
  end
@@ -63,13 +63,13 @@ module SimpleNestedSet
63
63
  end
64
64
 
65
65
  # Returns an array of all parents
66
- def ancestors
67
- nested_set.with_ancestors(lft, rgt)
66
+ def ancestors(opts = {})
67
+ nested_set.with_ancestors(lft, rgt, opts)
68
68
  end
69
69
 
70
70
  # Returns the array of all parents and self
71
71
  def self_and_ancestors
72
- ancestors + [self]
72
+ ancestors(:include_self => true)
73
73
  end
74
74
 
75
75
  # Returns true if this is a descendent of the given node
@@ -83,13 +83,13 @@ module SimpleNestedSet
83
83
  end
84
84
 
85
85
  # Returns a set of all of its children and nested children.
86
- def descendants
87
- rgt - lft == 1 ? [] : nested_set.with_descendants(lft, rgt)
86
+ def descendants(opts = {})
87
+ nested_set.with_descendants(lft, rgt, opts)
88
88
  end
89
89
 
90
90
  # Returns a set of itself and all of its nested children.
91
91
  def self_and_descendants
92
- [self] + descendants
92
+ descendants(:include_self => true)
93
93
  end
94
94
 
95
95
  # Returns the number of descendants
@@ -2,12 +2,13 @@ module SimpleNestedSet
2
2
  class NestedSet < ActiveRecord::Relation
3
3
  include SqlAbstraction
4
4
 
5
- class_inheritable_accessor :node_class, :scope_names
5
+ class_inheritable_accessor :node_class, :scope_names, :move_after_save
6
6
 
7
7
  class << self
8
8
  def build_class(model, scopes)
9
9
  model.const_get(:NestedSet) rescue model.const_set(:NestedSet, Class.new(NestedSet)).tap do |node_class|
10
10
  node_class.node_class = model
11
+ node_class.move_after_save = true
11
12
  node_class.scope_names = Array(scopes).map { |s| s.to_s =~ /_id$/ ? s.to_sym : :"#{s}_id" }
12
13
  end
13
14
  end
@@ -41,8 +42,15 @@ module SimpleNestedSet
41
42
  def save!
42
43
  attributes = node.instance_variable_get(:@_nested_set_attributes)
43
44
  node.instance_variable_set(:@_nested_set_attributes, nil)
44
- move_by_attributes(attributes) unless attributes.blank?
45
- denormalize!
45
+
46
+ if self.class.move_after_save
47
+ move_by_attributes(attributes) unless attributes.blank?
48
+ denormalize!
49
+ elsif attributes
50
+ attributes.each do |key, value|
51
+ node.update_attribute(key, value)
52
+ end
53
+ end
46
54
  end
47
55
 
48
56
  # FIXME we don't always want to call this on after_save, do we? it's only relevant when
@@ -121,6 +129,10 @@ module SimpleNestedSet
121
129
  Rebuild::FromPaths.new.run(self)
122
130
  end
123
131
 
132
+ def rebuild_from_parents!(sort_order = nil)
133
+ Rebuild::FromParents.new.run(self, sort_order)
134
+ end
135
+
124
136
  def denormalize_level_query
125
137
  aliaz = arel_table.as(:l)
126
138
  query = aliaz.project(aliaz[:id].count).
@@ -0,0 +1,56 @@
1
+ module SimpleNestedSet
2
+ module Rebuild
3
+ class FromParents
4
+ attr_writer :num
5
+
6
+ def num
7
+ @num ||= 0
8
+ end
9
+
10
+ def run(nested_set, sort_order = nil)
11
+ order_columns = ([:parent_id] + Array[sort_order]).compact
12
+
13
+ nodes = if nested_set.respond_to?(:except)
14
+ nested_set.except(:order).order(order_columns)
15
+ else
16
+ nested_set.reorder(order_columns)
17
+ end.to_a
18
+
19
+ renumber(nodes.dup)
20
+ nodes.each(&:save)
21
+ end
22
+
23
+ def renumber(nodes)
24
+ until nodes.empty?
25
+ node = nodes.shift
26
+ node.lft = self.num += 1
27
+ num = renumber(extract_children(node, nodes))
28
+ node.rgt = self.num += 1
29
+ end
30
+ num
31
+ end
32
+
33
+ def extract_children(node, nodes)
34
+ children = nodes.select { |child| child?(node, child) }
35
+ nodes.replace(nodes - children)
36
+ children
37
+ end
38
+
39
+ def child?(node, child)
40
+ if child.root?
41
+ false
42
+ elsif direct_child?(node, child)
43
+ true
44
+ else
45
+ # recurse to find indirect children,
46
+ # i.e. the child is one of the grandchildren of the node
47
+ child?(node, child.parent)
48
+ end
49
+ end
50
+
51
+ def direct_child? node, child
52
+ child.parent_id == node.id
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,3 +1,3 @@
1
1
  module SimpleNestedSet
2
- VERSION = "0.0.24"
2
+ VERSION = "0.0.25"
3
3
  end
@@ -21,6 +21,7 @@ module SimpleNestedSet
21
21
 
22
22
  module Rebuild
23
23
  autoload :FromPaths, 'simple_nested_set/rebuild/from_paths'
24
+ autoload :FromParents, 'simple_nested_set/rebuild/from_parents'
24
25
  end
25
26
  end
26
27
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_nested_set
3
3
  version: !ruby/object:Gem::Version
4
- hash: 47
4
+ hash: 45
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 24
10
- version: 0.0.24
9
+ - 25
10
+ version: 0.0.25
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sven Fuchs
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-21 00:00:00 +01:00
18
+ date: 2010-11-29 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -82,12 +82,14 @@ dependencies:
82
82
  requirement: &id005 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
- - - ">="
85
+ - - "="
86
86
  - !ruby/object:Gem::Version
87
- hash: 3
87
+ hash: 15
88
88
  segments:
89
89
  - 0
90
- version: "0"
90
+ - 5
91
+ - 2
92
+ version: 0.5.2
91
93
  type: :development
92
94
  version_requirements: *id005
93
95
  - !ruby/object:Gem::Dependency
@@ -122,6 +124,7 @@ files:
122
124
  - lib/simple_nested_set/move/to_target.rb
123
125
  - lib/simple_nested_set/nested_set.rb
124
126
  - lib/simple_nested_set/patches/arel_table_initialization.rb
127
+ - lib/simple_nested_set/rebuild/from_parents.rb
125
128
  - lib/simple_nested_set/rebuild/from_paths.rb
126
129
  - lib/simple_nested_set/sql_abstraction.rb
127
130
  - lib/simple_nested_set/version.rb