jnicklas-eb_nested_set 0.3.2 → 0.3.5
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.
- data/README.md +33 -1
- data/Rakefile +6 -1
- data/lib/eb_nested_set.rb +193 -72
- metadata +2 -2
data/README.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
A nested set is a datastruture in a database, sort of like a tree, but unlike a tree it allows you to find all descendants of a node with a single query. Loading a deeply nested structure with nested sets is therefore a lot more efficient than using a tree. So what's the disadvantage? Nested sets are a lot harder to maintain, since inserting and moving records requires management and it is easy to corrupt the dataset. Enter: EvenBetterNestedSet. Amount of micromanaging you need to do: 0. EvenBetterNestedSet does it all for you.
|
|
4
4
|
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Stable:
|
|
8
|
+
|
|
9
|
+
[sudo] gem install eb_nested_set
|
|
10
|
+
|
|
11
|
+
Edge:
|
|
12
|
+
|
|
13
|
+
[sudo] gem install jnicklas-eb_nested_set --source http://gems.github.com
|
|
14
|
+
|
|
15
|
+
From source:
|
|
16
|
+
|
|
17
|
+
git clone git://github.com/jnicklas/even_better_nested_set.git
|
|
18
|
+
cd even_better_nested_set
|
|
19
|
+
rake install
|
|
20
|
+
|
|
21
|
+
If you're running Rails, just add it to your environment.rb file
|
|
22
|
+
|
|
23
|
+
config.gem 'eb_nested_set'
|
|
24
|
+
|
|
25
|
+
You can also install it as a Rails plugin.
|
|
26
|
+
|
|
27
|
+
script/plugin install git://github.com/jnicklas/even_better_nested_set.git
|
|
28
|
+
|
|
5
29
|
## Declaring nested sets
|
|
6
30
|
|
|
7
31
|
This is how you declare a nested set:
|
|
@@ -38,4 +62,12 @@ EvenBetterNestedSet will not automatically cache children for you, because it as
|
|
|
38
62
|
|
|
39
63
|
or more conveniently:
|
|
40
64
|
|
|
41
|
-
d = Directory.find_with_nested_set(42)
|
|
65
|
+
d = Directory.find_with_nested_set(42)
|
|
66
|
+
|
|
67
|
+
## I18n
|
|
68
|
+
|
|
69
|
+
Add these keys to your translation file:
|
|
70
|
+
|
|
71
|
+
even_better_nested_set:
|
|
72
|
+
parent_not_in_scope: "nay, thy parent not be in scope {{scope_name}}"
|
|
73
|
+
illegal_nesting: "arr tis be illegal nesting"
|
data/Rakefile
CHANGED
|
@@ -3,9 +3,10 @@ require 'rake/gempackagetask'
|
|
|
3
3
|
require 'rubygems/specification'
|
|
4
4
|
require 'date'
|
|
5
5
|
require 'spec/rake/spectask'
|
|
6
|
+
require 'yard'
|
|
6
7
|
|
|
7
8
|
GEM = "eb_nested_set"
|
|
8
|
-
GEM_VERSION = "0.3.
|
|
9
|
+
GEM_VERSION = "0.3.5"
|
|
9
10
|
AUTHOR = "Jonas Nicklas"
|
|
10
11
|
EMAIL = "jonas.nicklas@gmail.com"
|
|
11
12
|
HOMEPAGE = "http://github.com/jnicklas/even_better_nested_set/tree/master"
|
|
@@ -27,6 +28,10 @@ spec = Gem::Specification.new do |s|
|
|
|
27
28
|
s.files = %w(LICENSE README.md Rakefile init.rb) + Dir.glob("{lib,spec}/**/*")
|
|
28
29
|
end
|
|
29
30
|
|
|
31
|
+
YARD::Rake::YardocTask.new do |t|
|
|
32
|
+
t.files = ["README.md", "LICENSE", "TODO", 'lib/**/*.rb']
|
|
33
|
+
end
|
|
34
|
+
|
|
30
35
|
Rake::GemPackageTask.new(spec) do |pkg|
|
|
31
36
|
pkg.gem_spec = spec
|
|
32
37
|
end
|
data/lib/eb_nested_set.rb
CHANGED
|
@@ -1,13 +1,57 @@
|
|
|
1
1
|
module EvenBetterNestedSet
|
|
2
2
|
|
|
3
|
-
def self.included(base)
|
|
4
|
-
super
|
|
5
|
-
base.extend ClassMethods
|
|
6
|
-
end
|
|
7
|
-
|
|
8
3
|
class NestedSetError < StandardError; end
|
|
9
4
|
class IllegalAssignmentError < NestedSetError; end
|
|
10
|
-
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Declare this model as a nested set. Automatically adds all methods in +NestedSet+ to the model, as
|
|
8
|
+
# well as parent and children associations.
|
|
9
|
+
#
|
|
10
|
+
# == Options
|
|
11
|
+
# left [Symbol]:: the name of the column that contains the left boundary [Defaults to +left+]
|
|
12
|
+
# right [Symbol]:: the name of the column that contains the right boundary [Defaults to +right+]
|
|
13
|
+
# scope [Symbol]:: the name of an association to scope this nested set to
|
|
14
|
+
#
|
|
15
|
+
# @param [Hash] options a set of options
|
|
16
|
+
#
|
|
17
|
+
def acts_as_nested_set(options={})
|
|
18
|
+
options = { :left => :left, :right => :right }.merge!(options)
|
|
19
|
+
options[:scope] = "#{options[:scope]}_id" if options[:scope]
|
|
20
|
+
|
|
21
|
+
include NestedSet
|
|
22
|
+
|
|
23
|
+
self.nested_set_options = options
|
|
24
|
+
|
|
25
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
|
26
|
+
def #{options[:left]}=(left)
|
|
27
|
+
raise EvenBetterNestedSet::IllegalAssignmentError, "#{options[:left]} is an internal attribute used by EvenBetterNestedSet, do not assign it directly as is may corrupt the data in your database"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def #{options[:right]}=(right)
|
|
31
|
+
raise EvenBetterNestedSet::IllegalAssignmentError, "#{options[:right]} is an internal attribute used by EvenBetterNestedSet, do not assign it directly as is may corrupt the data in your database"
|
|
32
|
+
end
|
|
33
|
+
RUBY
|
|
34
|
+
|
|
35
|
+
named_scope :roots, :conditions => { :parent_id => nil }, :order => "#{nested_set_column(:left)} asc"
|
|
36
|
+
has_many :children, :class_name => self.name, :foreign_key => :parent_id, :order => "#{nested_set_column(:left)} asc"
|
|
37
|
+
belongs_to :parent, :class_name => self.name, :foreign_key => :parent_id
|
|
38
|
+
|
|
39
|
+
named_scope :descendants, lambda { |node|
|
|
40
|
+
left, right = find_boundaries(node.id)
|
|
41
|
+
{ :conditions => ["#{nested_set_column(:left)} > ? and #{nested_set_column(:right)} < ?", left, right],
|
|
42
|
+
:order => "#{nested_set_column(:left)} asc" }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
before_create :append_node
|
|
46
|
+
before_update :move_node
|
|
47
|
+
before_destroy :reload
|
|
48
|
+
after_destroy :remove_node
|
|
49
|
+
validate_on_update :illegal_nesting
|
|
50
|
+
validate :validate_parent_is_within_scope
|
|
51
|
+
|
|
52
|
+
delegate :nested_set_column, :to => "self.class"
|
|
53
|
+
end
|
|
54
|
+
|
|
11
55
|
module NestedSet
|
|
12
56
|
|
|
13
57
|
def self.included(base)
|
|
@@ -19,10 +63,20 @@ module EvenBetterNestedSet
|
|
|
19
63
|
|
|
20
64
|
attr_accessor :nested_set_options
|
|
21
65
|
|
|
66
|
+
##
|
|
67
|
+
# Finds the last root, used internally to find the point to insert new roots
|
|
68
|
+
#
|
|
69
|
+
# @return [ActiveRecord::Base] the last root node
|
|
70
|
+
#
|
|
22
71
|
def find_last_root
|
|
23
72
|
find(:first, :order => "#{nested_set_column(:right)} DESC", :conditions => { :parent_id => nil })
|
|
24
73
|
end
|
|
25
74
|
|
|
75
|
+
##
|
|
76
|
+
# Finds the left and right boundaries of a node given an id.
|
|
77
|
+
#
|
|
78
|
+
# @return [Array[Integer]] left and right boundaries
|
|
79
|
+
#
|
|
26
80
|
def find_boundaries(id)
|
|
27
81
|
query = "SELECT #{nested_set_column(:left)}, #{nested_set_column(:right)}" +
|
|
28
82
|
"FROM #{quote_db_property(table_name)}" +
|
|
@@ -30,10 +84,21 @@ module EvenBetterNestedSet
|
|
|
30
84
|
connection.select_rows(query).first
|
|
31
85
|
end
|
|
32
86
|
|
|
87
|
+
##
|
|
88
|
+
# Returns all nodes with children cached to a nested set
|
|
89
|
+
#
|
|
90
|
+
# @return [Array[ActiveRecord::Base]] an array of root nodes with cached children
|
|
91
|
+
#
|
|
33
92
|
def nested_set
|
|
34
93
|
sort_nodes_to_nested_set(find(:all, :order => "#{nested_set_column(:left)} ASC"))
|
|
35
94
|
end
|
|
36
95
|
|
|
96
|
+
##
|
|
97
|
+
# Finds all nodes matching the criteria provided, and caches their descendants
|
|
98
|
+
#
|
|
99
|
+
# @param [Object] *args same parameters as ordinary find calls
|
|
100
|
+
# @return [Array[ActiveRecord::Base], ActiveRecord::Base] the found nodes
|
|
101
|
+
#
|
|
37
102
|
def find_with_nested_set(*args)
|
|
38
103
|
result = find(*args)
|
|
39
104
|
if result.respond_to?(:cache_nested_set)
|
|
@@ -46,6 +111,12 @@ module EvenBetterNestedSet
|
|
|
46
111
|
result
|
|
47
112
|
end
|
|
48
113
|
|
|
114
|
+
##
|
|
115
|
+
# Given a flat list of nodes, sorts them to a tree, caching descendants in the process
|
|
116
|
+
#
|
|
117
|
+
# @param [Array[ActiveRecord::Base]] nodes an array of nodes
|
|
118
|
+
# @return [Array[ActiveRecord::Base]] an array of nodes with children cached
|
|
119
|
+
#
|
|
49
120
|
def sort_nodes_to_nested_set(nodes)
|
|
50
121
|
roots = []
|
|
51
122
|
hashmap = {}
|
|
@@ -69,11 +140,18 @@ module EvenBetterNestedSet
|
|
|
69
140
|
return roots
|
|
70
141
|
end
|
|
71
142
|
|
|
143
|
+
##
|
|
144
|
+
# Returns the properly quoted column name given the generic term
|
|
145
|
+
#
|
|
146
|
+
# @param [Symbol] name the name of the column to find
|
|
147
|
+
# @return [String]
|
|
72
148
|
def nested_set_column(name)
|
|
73
149
|
quote_db_property(nested_set_options[name])
|
|
74
150
|
end
|
|
75
151
|
|
|
152
|
+
##
|
|
76
153
|
# Recalculates the left and right values for the entire tree
|
|
154
|
+
#
|
|
77
155
|
def recalculate_nested_set
|
|
78
156
|
transaction do
|
|
79
157
|
left = 1
|
|
@@ -83,29 +161,59 @@ module EvenBetterNestedSet
|
|
|
83
161
|
end
|
|
84
162
|
end
|
|
85
163
|
|
|
164
|
+
##
|
|
165
|
+
# Properly quotes a column name
|
|
166
|
+
#
|
|
167
|
+
# @param [String] property
|
|
168
|
+
# @return [String] quoted property
|
|
169
|
+
#
|
|
86
170
|
def quote_db_property(property)
|
|
87
171
|
"`#{property}`".gsub('.','`.`')
|
|
88
172
|
end
|
|
89
173
|
|
|
90
174
|
end
|
|
91
175
|
|
|
176
|
+
##
|
|
177
|
+
# Checks if this root is a root node
|
|
178
|
+
#
|
|
179
|
+
# @return [Boolean] whether this node is a root node or not
|
|
180
|
+
#
|
|
92
181
|
def root?
|
|
93
182
|
not parent_id?
|
|
94
183
|
end
|
|
95
184
|
|
|
185
|
+
##
|
|
186
|
+
# Checks if this node is a descendant of node
|
|
187
|
+
#
|
|
188
|
+
# @param [ActiveRecord::Base] node the node to check agains
|
|
189
|
+
# @return [Boolean] whether this node is a descendant
|
|
190
|
+
#
|
|
96
191
|
def descendant_of?(node)
|
|
97
192
|
node.left < self.left && self.right < node.right
|
|
98
193
|
end
|
|
99
194
|
|
|
100
|
-
|
|
101
|
-
|
|
195
|
+
##
|
|
196
|
+
# Finds the root node that this node descends from
|
|
197
|
+
#
|
|
198
|
+
# @param [Boolean] force_reload forces the root node to be reloaded
|
|
199
|
+
# @return [ActiveRecord::Base] node the root node this descends from
|
|
200
|
+
#
|
|
201
|
+
def root(force_reload=nil)
|
|
202
|
+
@root = nil if force_reload
|
|
203
|
+
@root ||= transaction do
|
|
102
204
|
reload_boundaries
|
|
103
|
-
|
|
205
|
+
base_class.roots.find(:first, :conditions => ["#{nested_set_column(:left)} <= ? AND #{nested_set_column(:right)} >= ?", left, right])
|
|
104
206
|
end
|
|
105
207
|
end
|
|
106
208
|
|
|
107
209
|
alias_method :patriarch, :root
|
|
108
210
|
|
|
211
|
+
##
|
|
212
|
+
# Returns a list of ancestors this node belongs to
|
|
213
|
+
#
|
|
214
|
+
# @param [Boolean] force_reload forces the list to be reloaded
|
|
215
|
+
# @return [Array[ActiveRecord::Base]] a list of nodes that this node descends from
|
|
216
|
+
#
|
|
109
217
|
def ancestors(force_reload=false)
|
|
110
218
|
@ancestors = nil if force_reload
|
|
111
219
|
@ancestors ||= base_class.find(
|
|
@@ -114,26 +222,55 @@ module EvenBetterNestedSet
|
|
|
114
222
|
)
|
|
115
223
|
end
|
|
116
224
|
|
|
225
|
+
##
|
|
226
|
+
# Returns a list of the node itself and all of its ancestors
|
|
227
|
+
#
|
|
228
|
+
# @param [Boolean] force_reload forces the list to be reloaded
|
|
229
|
+
# @return [Array[ActiveRecord::Base]] a list of nodes that this node descends from
|
|
230
|
+
#
|
|
117
231
|
def lineage(force_reload=false)
|
|
118
232
|
[self, *ancestors(force_reload)]
|
|
119
233
|
end
|
|
120
234
|
|
|
235
|
+
##
|
|
236
|
+
# Returns all nodes that descend from the same root node as this node
|
|
237
|
+
#
|
|
238
|
+
# @return [Array[ActiveRecord::Base]]
|
|
239
|
+
#
|
|
121
240
|
def kin
|
|
122
241
|
patriarch.family
|
|
123
242
|
end
|
|
124
243
|
|
|
244
|
+
##
|
|
245
|
+
# Returns all nodes that descend from this node
|
|
246
|
+
#
|
|
247
|
+
# @return [Array[ActiveRecord::Base]]
|
|
248
|
+
#
|
|
125
249
|
def descendants
|
|
126
250
|
base_class.descendants(self)
|
|
127
251
|
end
|
|
128
252
|
|
|
253
|
+
##
|
|
254
|
+
# Caches the children of this node
|
|
255
|
+
#
|
|
129
256
|
def cache_nested_set
|
|
130
257
|
@cached_children || base_class.sort_nodes_to_nested_set(family)
|
|
131
258
|
end
|
|
132
259
|
|
|
260
|
+
##
|
|
261
|
+
# Returns the node and all nodes that descend from it.
|
|
262
|
+
#
|
|
263
|
+
# @return [Array[ActiveRecord::Base]]
|
|
264
|
+
#
|
|
133
265
|
def family
|
|
134
266
|
[self, *descendants]
|
|
135
267
|
end
|
|
136
268
|
|
|
269
|
+
##
|
|
270
|
+
# Returns the ids of the node and all nodes that descend from it.
|
|
271
|
+
#
|
|
272
|
+
# @return [Array[Integer]]
|
|
273
|
+
#
|
|
137
274
|
def family_ids(force_reload=false)
|
|
138
275
|
return @family_ids unless @family_ids.nil? or force_reload
|
|
139
276
|
|
|
@@ -146,14 +283,29 @@ module EvenBetterNestedSet
|
|
|
146
283
|
end
|
|
147
284
|
end
|
|
148
285
|
|
|
286
|
+
##
|
|
287
|
+
# Returns all nodes that share the same parent as this node.
|
|
288
|
+
#
|
|
289
|
+
# @return [Array[ActiveRecord::Base]]
|
|
290
|
+
#
|
|
149
291
|
def generation
|
|
150
292
|
root? ? base_class.roots : parent.children
|
|
151
293
|
end
|
|
152
294
|
|
|
295
|
+
##
|
|
296
|
+
# Returns all nodes that are siblings of this node
|
|
297
|
+
#
|
|
298
|
+
# @return [Array[ActiveRecord::Base]]
|
|
299
|
+
#
|
|
153
300
|
def siblings
|
|
154
301
|
generation - [self]
|
|
155
302
|
end
|
|
156
303
|
|
|
304
|
+
##
|
|
305
|
+
# Returns how deeply this node is nested, that is how many ancestors it has.
|
|
306
|
+
#
|
|
307
|
+
# @return [Integer] the number of ancestors of this node.
|
|
308
|
+
#
|
|
157
309
|
def level
|
|
158
310
|
if root?
|
|
159
311
|
0
|
|
@@ -164,36 +316,46 @@ module EvenBetterNestedSet
|
|
|
164
316
|
end
|
|
165
317
|
end
|
|
166
318
|
|
|
319
|
+
##
|
|
320
|
+
# @return [Range] the left to the right boundary of this node
|
|
321
|
+
#
|
|
167
322
|
def bounds
|
|
168
323
|
left..right
|
|
169
324
|
end
|
|
170
325
|
|
|
171
|
-
|
|
172
|
-
|
|
326
|
+
##
|
|
327
|
+
# @return [Integer] the left boundary of this node
|
|
328
|
+
#
|
|
329
|
+
def left
|
|
330
|
+
read_attribute(self.class.nested_set_options[:left])
|
|
173
331
|
end
|
|
174
332
|
|
|
175
|
-
|
|
176
|
-
|
|
333
|
+
##
|
|
334
|
+
# @return [Integer] the right boundary of this node
|
|
335
|
+
#
|
|
336
|
+
def right
|
|
337
|
+
read_attribute(self.class.nested_set_options[:right])
|
|
177
338
|
end
|
|
178
339
|
|
|
340
|
+
##
|
|
341
|
+
# Caches the node as this node's parent.
|
|
342
|
+
#
|
|
179
343
|
def cache_parent(parent) #:nodoc:
|
|
180
344
|
self.parent = parent
|
|
181
345
|
end
|
|
182
346
|
|
|
347
|
+
##
|
|
348
|
+
# Caches the nodes as this node's children.
|
|
349
|
+
#
|
|
183
350
|
def cache_children(*nodes) #:nodoc:
|
|
184
351
|
@cached_children ||= []
|
|
185
|
-
@cached_children.push(*nodes)
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def left
|
|
189
|
-
read_attribute(self.class.nested_set_options[:left])
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
def right
|
|
193
|
-
read_attribute(self.class.nested_set_options[:right])
|
|
352
|
+
children.target = @cached_children.push(*nodes)
|
|
194
353
|
end
|
|
195
|
-
|
|
196
|
-
|
|
354
|
+
|
|
355
|
+
##
|
|
356
|
+
# Rebuild this node's childrens boundaries
|
|
357
|
+
#
|
|
358
|
+
def recalculate_nested_set(left) #:nodoc:
|
|
197
359
|
child_left = left + 1
|
|
198
360
|
children.each do |child|
|
|
199
361
|
child_left = child.recalculate_nested_set(child_left)
|
|
@@ -208,7 +370,7 @@ module EvenBetterNestedSet
|
|
|
208
370
|
|
|
209
371
|
def illegal_nesting
|
|
210
372
|
if parent_id? and family_ids.include?(parent_id)
|
|
211
|
-
errors.add(:parent_id, 'cannot move node to its own descendant')
|
|
373
|
+
errors.add(:parent_id, I18n.t('even_better_nested_set.illegal_nesting', :default => 'cannot move node to its own descendant'))
|
|
212
374
|
end
|
|
213
375
|
end
|
|
214
376
|
|
|
@@ -293,57 +455,16 @@ module EvenBetterNestedSet
|
|
|
293
455
|
if self.class.nested_set_options[:scope] && parent_id
|
|
294
456
|
parent.reload # Make sure we are testing the record corresponding to the parent_id
|
|
295
457
|
if self.send(self.class.nested_set_options[:scope]) != parent.send(self.class.nested_set_options[:scope])
|
|
296
|
-
|
|
458
|
+
message = I18n.t('even_better_nested_set.parent_not_in_scope',
|
|
459
|
+
:default => "cannot be a record with a different {{scope_name}} to this record",
|
|
460
|
+
:scope_name => self.class.nested_set_options[:scope]
|
|
461
|
+
)
|
|
462
|
+
errors.add(:parent_id, message)
|
|
297
463
|
end
|
|
298
464
|
end
|
|
299
465
|
end
|
|
300
466
|
end
|
|
301
467
|
|
|
302
|
-
module ClassMethods
|
|
303
|
-
|
|
304
|
-
def acts_as_nested_set(options = {})
|
|
305
|
-
options = { :left => :left, :right => :right }.merge!(options)
|
|
306
|
-
options[:scope] = "#{options[:scope]}_id" if options[:scope]
|
|
307
|
-
|
|
308
|
-
include NestedSet
|
|
309
|
-
|
|
310
|
-
self.nested_set_options = options
|
|
311
|
-
|
|
312
|
-
class_eval <<-RUBY, __FILE__, __LINE__+1
|
|
313
|
-
def #{options[:left]}=(left)
|
|
314
|
-
raise EvenBetterNestedSet::IllegalAssignmentError, "#{options[:left]} is an internal attribute used by EvenBetterNestedSet, do not assign it directly as is may corrupt the data in your database"
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
def #{options[:right]}=(right)
|
|
318
|
-
raise EvenBetterNestedSet::IllegalAssignmentError, "#{options[:right]} is an internal attribute used by EvenBetterNestedSet, do not assign it directly as is may corrupt the data in your database"
|
|
319
|
-
end
|
|
320
|
-
RUBY
|
|
321
|
-
|
|
322
|
-
named_scope :roots, :conditions => { :parent_id => nil }, :order => "#{nested_set_column(:left)} asc"
|
|
323
|
-
|
|
324
|
-
has_many :uncached_children, :class_name => self.name, :foreign_key => :parent_id, :order => "#{nested_set_column(:left)} asc"
|
|
325
|
-
protected :uncached_children, :uncached_children=
|
|
326
|
-
|
|
327
|
-
belongs_to :parent, :class_name => self.name, :foreign_key => :parent_id
|
|
328
|
-
|
|
329
|
-
named_scope :descendants, lambda { |node|
|
|
330
|
-
left, right = find_boundaries(node.id)
|
|
331
|
-
{ :conditions => ["#{nested_set_column(:left)} > ? and #{nested_set_column(:right)} < ?", left, right],
|
|
332
|
-
:order => "#{nested_set_column(:left)} asc" }
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
before_create :append_node
|
|
336
|
-
before_update :move_node
|
|
337
|
-
before_destroy :reload
|
|
338
|
-
after_destroy :remove_node
|
|
339
|
-
validate_on_update :illegal_nesting
|
|
340
|
-
validate :validate_parent_is_within_scope
|
|
341
|
-
|
|
342
|
-
delegate :nested_set_column, :to => "self.class"
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
end
|
|
346
|
-
|
|
347
468
|
end
|
|
348
469
|
|
|
349
|
-
ActiveRecord::Base.
|
|
470
|
+
ActiveRecord::Base.extend EvenBetterNestedSet if defined?(ActiveRecord)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jnicklas-eb_nested_set
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jonas Nicklas
|
|
@@ -9,7 +9,7 @@ autorequire: eb_nested_set
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-02-
|
|
12
|
+
date: 2009-02-16 00:00:00 -08:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|