simple_nested_set 0.0.24 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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