engine/app/models/extensions/page/tree.rb
2010-06-03 17:32:40 +02:00

97 lines
2.9 KiB
Ruby

module Models
module Extensions
module Page
module Tree
extend ActiveSupport::Concern
included do
include Mongoid::Acts::Tree
## fields ##
field :position, :type => Integer
## behaviours ##
acts_as_tree :order => ['position', 'asc']
## callbacks ##
before_validate :reset_parent
before_save { |p| p.parent_id = nil if p.parent_id.blank? }
before_save :change_parent
before_create { |p| p.send(:fix_position, false) }
before_create :add_to_list_bottom
before_destroy :remove_from_list
# Fixme (Didier L.): Instances methods are defined before the include itself
alias :ancestors :hacked_ancestors
alias :fix_position :hacked_fix_position
end
module InstanceMethods
def sort_children!(ids)
ids.each_with_index do |id, position|
child = self.children.detect { |p| p._id == id }
child.position = position
child.save
end
end
def parent=(owner) # missing in acts_as_tree
@_parent = owner
self.fix_position(false)
self.instance_variable_set :@_will_move, true
end
def hacked_ancestors
return [] if root?
self.class.find(self.path.clone << nil) # bug in mongoid (it does not handle array with one element)
end
protected
def change_parent
if self.parent_id_changed?
self.fix_position(false)
self.add_to_list_bottom
self.instance_variable_set :@_will_move, true
end
end
def hacked_fix_position(perform_save = true)
if parent.nil?
self[parent_id_field] = nil
self[path_field] = []
self[depth_field] = 0
else
self[parent_id_field] = parent._id
self[path_field] = parent[path_field] + [parent._id]
self[depth_field] = parent[depth_field] + 1
self.save if perform_save
end
end
def reset_parent
if self.parent_id_changed?
@_parent = nil
end
end
def add_to_list_bottom
self.position = (::Page.where(:_id.ne => self._id).and(:parent_id => self.parent_id).max(:position) || 0) + 1
end
def remove_from_list
return if (self.site rescue nil).nil?
::Page.where(:parent_id => self.parent_id).and(:position.gt => self.position).each do |p|
p.position -= 1
p.save
end
end
end
end
end
end
end