# -*- encoding : utf-8 -*- class MenuItem < ActiveRecord::Base belongs_to :menu_content, :polymorphic => true belongs_to :menu validates :name, :presence => true validates :slug, :presence => true attr_accessor :skip_before_update, :skip_permalink accepts_nested_attributes_for :menu_content acts_as_tree def url if menu_content self.permalink else "/404.html" end end before_validation do self.slug = self.slug.to_slug end before_save do #self.set_permalink end def generate_permalink r = "" node, ancestors = self, [] ancestors << node = MenuItem.find(node.parent_id) while node.parent_id? ancestors.reverse.each do |ancestor| r += ancestor.slug.to_s r+= "/" end r+= self.slug.to_s end def set_permalink if !skip_permalink self.permalink = self.generate_permalink self.skip_permalink = true self.skip_before_update = true self.save # self.children.each do |child| # child.save # end end end def validate self.parent_id = nil if self.parent_id == 0 errors.add(:parent_id, 'doit être différent de la page actuelle') if parent_id == id and id != nil if self.id errors.add(:parent_id, 'attention la page parente à pour page parente celle-ci = boucle') if self.parent_id and self.id == MenuItem.find(self.parent_id).parent_id end conditions = ["menu_id = ? and parent_id "+(self.parent_id ? "=" : "IS")+" ? and slug = ? "+("and id != ?" if self.id).to_s, self.menu_id,self.parent_id ,self.slug] conditions << self.id if self.id if MenuItem.where(conditions).first errors.add(:slug, 'est déjà utilisé') end end before_create do if !position top = MenuItem.find(:first, :conditions =>{ :parent_id => self.parent_id, :menu_id => self.menu_id}, :order => "position DESC") if top self.position = top.position.to_i + 1 else self.position = 1 end end if position MenuItem.find(:all, :conditions => ["menu_id = ? and position >= ? and parent_id "+(self.parent_id ? "=" : "IS")+" ?",self.menu_id,self.position,self.parent_id]).each do |portlet| portlet.position = portlet.position + 1 portlet.skip_before_update = true portlet.save! end end end before_update do if !skip_before_update if self.parent_id_changed? MenuItem.find(:all, :conditions => ["menu_id = ? and position > ? and parent_id "+(self.changes['parent_id'][0] ? "=" : "IS")+" ?",self.menu_id,self.position,self.changes['parent_id'][0]]).each do |portlet| portlet.position = portlet.position - 1 portlet.skip_before_update = true portlet.save! end self.position = 1 MenuItem.find(:all, :conditions => ["menu_id = ? and parent_id "+(self.parent_id ? "=" : "IS")+" ?",self.menu_id,self.parent_id]).each do |portlet| portlet.position = portlet.position + 1 portlet.skip_before_update = true portlet.save! end elsif self.position_changed? top = MenuItem.find(:first, :conditions =>{ :parent_id => self.parent_id, :menu_id => self.menu_id}, :order => "position DESC") if self.changes['position'][1] > self.changes['position'][0] self.position = self.position - 1 self.changes['position'][1] = self.changes['position'][1] - 1 MenuItem.find(:all, :conditions => ["menu_id = ? and position > ? and position <= ? and parent_id "+(self.parent_id ? "=" : "IS")+" ?",self.menu_id,self.changes['position'][0],self.changes['position'][1],self.parent_id]).each do |portlet| portlet.position = portlet.position - 1 portlet.skip_before_update = true portlet.save! end #si la position est plus petite que l'ancienne. elsif self.changes['position'][1] < self.changes['position'][0] MenuItem.find(:all, :conditions => ["menu_id = ? and position >= ? and position < ? and parent_id "+(self.parent_id ? "=" : "IS")+" ?",self.menu_id,self.changes['position'][1],self.changes['position'][0],self.parent_id]).each do |portlet| portlet.position = portlet.position + 1 portlet.skip_before_update = true portlet.save! end end end end end before_destroy do MenuItem.find(:all, :conditions => ["menu_id = ? and position > ? and parent_id "+(self.parent_id ? "=" : "IS")+" ?",self.menu_id,self.position,self.parent_id]).each do |portlet| portlet.position = portlet.position - 1 portlet.skip_before_update = true portlet.save! end end end