crewmate/crewmate

View on GitHub
app/models/page.rb

Summary

Maintainability
B
5 hrs
Test Coverage
# -*- encoding : utf-8 -*-
class Page < RoleRecord
  include Immortal
  has_many :notes, :dependent => :destroy
  has_many :dividers, :dependent => :destroy
  has_many :uploads, :dependent => :destroy

  has_many :slots, :class_name => 'PageSlot', :order => 'position ASC', :dependent => :delete_all

  has_permalink :name, :scope => :project_id

  attr_accessible :name, :description, :note_attributes
  attr_accessor :suppress_activity

  validates_length_of :name, :minimum => 1

  default_scope :order => 'position ASC, created_at DESC, id DESC'

  after_create :log_create
  after_update :log_update

  def build_note(note = {})
    self.notes.build(note) do |note|
      note.project_id = self.project_id
      note.page_id = self.id
    end
  end

  def build_divider(divider = {})
    self.dividers.build(divider) do |divider|
      divider.project_id = self.project_id
      divider.page_id = self.id
    end
  end

  def new_note(note = {})
    self.notes.new(note) do |note|
      note.project_id = self.project_id
      note.page_id = self.id
    end
  end

  def new_slot(insert_id, insert_before, widget)
     PageSlot.transaction do
       # Calculate correct position
       insert_pos = nil

       # Assuming we have an insert_id...
       if !insert_id.nil? and insert_id != 0
         old_slot = PageSlot.find(insert_id) rescue nil
         insert_pos = (insert_before ? old_slot.position : old_slot.position+1) unless old_slot.nil?
       end

       # Fallback
       if insert_pos.nil?
         if self.slots.empty?
           insert_pos = 0
         else
           insert_pos = insert_before ? self.slots[0].position :
                                        self.slots[self.slots.length-1].position+1
         end
       end

       # Bump up all other slots
       self.slots.each do |slot|
         if slot.position >= insert_pos
           slot.position += 1
           slot.save
         end
       end

       # Make the new slot, damnit!
       slot = PageSlot.new(:page => self, :position => insert_pos, :rel_object => widget)
       slot.save

       slot
     end
  end

  def divided_slots
    groups = []
    divider = nil
    items = []
    slots.each do |slot|
      if slot.rel_object_type == 'Divider'
        if divider or items.length > 0
          groups << [divider, items]
          items = []
        end
        divider = slot
      else
        items << slot
      end
    end

    # Final group
    if divider or items.length > 0
      groups << [divider, items]
    end

    groups
  end

  def log_create
    project.log_activity(self,'create')
  end

  def log_update
    project.log_activity(self, 'edit') unless @suppress_activity
  end

  def to_s
    name
  end

  def to_param
    permalink || id.to_s
  end

  def user
    @user ||= user_id ? User.with_deleted.find_by_id(user_id) : nil
  end

  def refs_objects
    notes+dividers+uploads
  end

  def to_xml(options = {})
    options[:indent] ||= 2
    xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
    xml.instruct! unless options[:skip_instruct]
    xml.page :id => id do
      xml.tag! 'project-id',      project_id
      xml.tag! 'user-id',         user_id
      xml.tag! 'name',            name
      xml.tag! 'description',     description
      xml.tag! 'created-at',      created_at.to_s(:db)
      xml.tag! 'updated-at',      updated_at.to_s(:db)
      xml.tag! 'watchers',        Array(watchers_ids).join(',')
      if Array(options[:include]).include? :slots
        slots.to_xml(options.merge({ :skip_instruct => true, :root => 'slots' }))
      end
      if Array(options[:include]).include? :objects
        notes.to_xml(options.merge({ :skip_instruct => true, :root => 'notes' }))
        dividers.to_xml(options.merge({ :skip_instruct => true, :root => 'dividers' }))
        uploads.to_xml(options.merge({ :skip_instruct => true, :root => 'uploads' }))
      end
    end
  end

  def to_api_hash(options = {})
    base = {
      :id => id,
      :project_id => project_id,
      :user_id => user_id,
      :name => name,
      :description => description,
      :created_at => created_at.to_s(:api_time),
      :updated_at => updated_at.to_s(:api_time),
      :watchers => Array.wrap(watchers_ids)
    }

    base[:type] = self.class.to_s if options[:emit_type]

    if Array(options[:include]).include? :slots
      base[:slots] = slots.map{|s| s.to_api_hash(options)}
    end

    if Array(options[:include]).include? :objects
      base[:objects] = refs_objects.map{|o| o.to_api_hash(:emit_type => true)}
    end

    base
  end

  define_index do
    where Page.undeleted_clause_sql

    indexes name, :sortable => true
    indexes description
    indexes notes.name, :as => :note_name
    indexes notes.body, :as => :note_body
    indexes dividers.name, :as => :divider_name
    indexes uploads(:asset_file_name), :as => :upload_name
    has project_id, created_at, updated_at
  end
end