Module: ActiveRecord::Acts::MaterializedPath::InstanceMethods

Defined in:
lib/acts_as_materialized_path.rb

Instance Method Summary collapse

Instance Method Details

#ancestors(include_self = false) ⇒ Object

returns an array of parents to root



336
337
338
339
340
341
342
# File 'lib/acts_as_materialized_path.rb', line 336

def ancestors(include_self = false)
  self.class.find(:all,
                  :conditions =>
                  [ mp_between,
                    the_path(!include_self) ],
                  :order => mp_asc )
end

#childrenObject

returns an array of children (empty if this is a leaf)



323
324
325
# File 'lib/acts_as_materialized_path.rb', line 323

def children
  self.class.siblings(the_path)
end

#depthObject

returns the depth of this node in the tree (0 based)



345
346
347
# File 'lib/acts_as_materialized_path.rb', line 345

def depth
  the_path.count(mp_delimiter)-1
end

#descendants(include_self = false) ⇒ Object

TODO



350
351
352
353
354
355
356
# File 'lib/acts_as_materialized_path.rb', line 350

def descendants(include_self = false)
  self.class.find(:all,
                  :conditions =>
                  [ mp_like,
                    "#{the_path}%" ],
                  :order => mp_asc )
end

#destroyObject

Raises:



202
203
204
205
206
207
208
209
210
211
# File 'lib/acts_as_materialized_path.rb', line 202

def destroy
  raise DestroyNotLeaf unless children.length == 0
  #or
#           self.class.transaction do
#             children.each do |child|
#               child.destroy
#             end
#           end
  super
end

#handle_new_record_codeObject



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/acts_as_materialized_path.rb', line 263

def handle_new_record_code
  self.class.transaction do
    basepath = ''
    if mp_parent_id_for_save.to_i > 0
      relation = mp_parent_id_for_save
      sibling = false
    elsif mp_sibling_id_for_save.to_i > 0
      relation = mp_sibling_id_for_save
      sibling = true
    end
    basepath =
      self.class.find(relation).the_path(sibling) if relation

    nextval = nextvalue(basepath)
    set_path(basepath+self.class.num2path_string(nextval)+mp_delimiter)
  end
end

#is_leaf?Boolean

Returns:

  • (Boolean)


186
187
188
# File 'lib/acts_as_materialized_path.rb', line 186

def is_leaf?
  !left_most_child
end

#left_most_childObject



178
179
180
181
182
183
184
# File 'lib/acts_as_materialized_path.rb', line 178

def left_most_child
  self.class.find(:first,
                  :conditions =>
                  ["#{mp_like}",
                   the_path + '_' * mp_places + mp_delimiter],
                  :order => mp_asc)
end

#nextvalue(path) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/acts_as_materialized_path.rb', line 219

def nextvalue(path)
  last = self.class.find(:first,
                         :select => mp_column,
                         :conditions =>
                         [mp_like, path +
                          '_' * mp_places +
                          mp_delimiter],
                         :order => mp_desc,
                         :lock => true)

  if last
    last_path = last.the_path
    if i = last_path.index(mp_regexp)
      leaf = last_path[i, mp_places]
    else
      leaf = last_path
    end
    nextval = leaf.to_i(mp_base).next
  else
    nextval = 0
  end

  return nextval
end

#parentObject



328
329
330
331
332
333
# File 'lib/acts_as_materialized_path.rb', line 328

def parent
  self.class.find(:first,
                  :conditions =>
                  [ mp_eq,
                    the_path(true) ])
end

#right_siblingObject



191
192
193
194
195
196
197
198
199
# File 'lib/acts_as_materialized_path.rb', line 191

def right_sibling
  self.class.find(:first,
                  :conditions =>
                  ["#{mp_gt} and #{mp_lt} and length(#{mp_column}) = ?",
                   the_path,
                   the_path(true)+'~',
                   the_path.length],
                  :order => mp_asc)
end

#saveObject



245
246
247
248
249
250
251
252
# File 'lib/acts_as_materialized_path.rb', line 245

def save
  if new_record? && !the_path
    handle_new_record_code
    super
  else
    super
  end
end

#save!Object



254
255
256
257
258
259
260
261
# File 'lib/acts_as_materialized_path.rb', line 254

def save!
  if new_record? && !the_path
    handle_new_record_code
    super
  else
    super
  end
end

#save_as_child_of(parent) ⇒ Object



299
300
301
# File 'lib/acts_as_materialized_path.rb', line 299

def save_as_child_of(parent)
  save_as_relation(parent, false)
end

#save_as_relation(parent_or_sibling, sibling) ⇒ Object



283
284
285
286
287
288
289
290
291
# File 'lib/acts_as_materialized_path.rb', line 283

def save_as_relation(parent_or_sibling, sibling)
  raise PathUpdateDisallowed unless new_record? && !the_path
  self.class.transaction do
    basepath = parent_or_sibling.the_path(sibling)
    nextval = nextvalue(basepath)
    set_path(basepath+self.class.num2path_string(nextval)+mp_delimiter)
    save
  end
end

#save_as_sibling_of(sibling) ⇒ Object



294
295
296
# File 'lib/acts_as_materialized_path.rb', line 294

def save_as_sibling_of(sibling)
  save_as_relation(sibling, true)
end

#set_path(path) ⇒ Object



214
215
216
# File 'lib/acts_as_materialized_path.rb', line 214

def set_path(path)
  write_attribute(mp_column.to_sym, path)
end

#siblings(include_self = false) ⇒ Object



316
317
318
319
320
# File 'lib/acts_as_materialized_path.rb', line 316

def siblings(include_self = false)
  res = self.class.siblings(the_path(true))
  res.delete_if{|mp| mp.the_path == the_path} unless include_self
  return res
end

#the_path(truncate = false) ⇒ Object



304
305
306
307
308
309
310
311
312
313
# File 'lib/acts_as_materialized_path.rb', line 304

def the_path(truncate = false)
  materialized_path = self.send(mp_column)
  if truncate
    rex = Regexp.new('[[:alnum:]]{' + mp_places.to_s + '}' +
                     '\\' + mp_delimiter)
    offset = materialized_path.rindex(rex)
  end
  materialized_path = materialized_path[0, offset] if offset
  return materialized_path
end