SysMO-DB/seek

View on GitHub
app/models/project_folder.rb

Summary

Maintainability
A
3 hrs
Test Coverage
class ProjectFolder < ActiveRecord::Base
  before_destroy :deletable?
  before_destroy :unsort_assets_and_remove_children

  belongs_to :project
  belongs_to :parent,:class_name=>"ProjectFolder",:foreign_key=>:parent_id
  has_many :children,:class_name=>"ProjectFolder",:foreign_key=>:parent_id, :order=>:title, :after_add=>:update_child
  has_many :project_folder_assets, :dependent=>:destroy



  scope :root_folders, lambda { |project| {
    :conditions=>{:project_id=>project.id,:parent_id=>nil},:order=>"LOWER(title)"
    }
  }

  validates_presence_of :project,:title

  def update_child child
    child.project = project
    child.parent = self
  end

  def assets
    project_folder_assets.collect{|pfa| pfa.asset}
  end

  #assets that are authorized to be shown for the current user
  def authorized_assets
    assets.select{|a| a.can_view?}
  end

  #what is displayed in the tree
  def label
    "#{title} (#{authorized_assets.count})"
  end

  def self.new_items_folder project
    ProjectFolder.where(:project_id=>project.id,:incoming=>true).first
  end

  #constucts the default project folders for a given project from a yaml file, by default using Rails.root/config/default_data/default_project_folders.yml
  def self.initialize_default_folders project, yaml_path=File.join(Rails.root,"config","default_data","default_project_folders.yml")
    raise Exception.new("This #{I18n.t('project')} already has folders defined") unless ProjectFolder.root_folders(project).empty?

    yaml = YAML.load(ERB.new(File.read(yaml_path)).result)
    folders={}

    #create individual folder items
    yaml.keys.each do |key|
      desc = yaml[key]
      new_folder=ProjectFolder.create :title=>desc["title"],
                                      :editable=>(desc["editable"].nil? ? true : desc["editable"]),
                                      :incoming=>(desc["incoming"].nil? ? false : desc["incoming"]),
                                      :deletable=>(desc["deletable"].nil? ? true : desc["deletable"]),
                                      :project=>project
      folders[key]=new_folder
    end

    #now assign children
    yaml.keys.each do |key|
      desc=yaml[key]
      if desc.has_key?("children")
        parent = folders[key]
        desc["children"].split(",").each do |child|
          folder = folders[child.strip]
          unless folder.nil?
            parent.children << folder
          else
            Rails.logger.error("Default #{I18n.t('project')} folder for key #{child} not found")
          end
        end
        parent.save!
      end
    end

    ProjectFolder.root_folders project
  end

  #adds a child with the given title, and makes sure the project is set correctly
  def add_child title
    child = ProjectFolder.new(:title=>title)
    children << child
    child
  end

  def add_assets assets
    assets = Array(assets)
    assets.each do |asset|
      pfa = ProjectFolderAsset.new :asset=>asset,:project_folder=>self
      pfa.save!
    end
  end

  #moves assets to this folder, from the source folder (source folder needed incase the asset belongs to more than 1 folder)
  def move_assets assets,source_folder
    assets=Array(assets)
    if (project_id == source_folder.project_id)
      assets.each do |asset|
        link = ProjectFolderAsset.where(:asset_id=>asset.id,:asset_type=>asset.class.name,:project_folder_id=>source_folder.id).first
        link.project_folder=self
        link.save!
      end
    end
  end

  #temporary method to destroy folders for a project, useful whilst developing
  def self.nuke project
    folders = ProjectFolder.all(:conditions=>{:project_id=>project.id})
    folder_assets = ProjectFolderAsset.all.select{|pfa| pfa.project_folder.nil? || pfa.project_folder.try(:project_id)==project.id}
    folder_assets.each {|a| a.destroy}
    folders.each {|f| f.deletable=true ; f.destroy}

  end

  def unsort_assets_and_remove_children
    new_items_folder=ProjectFolder.new_items_folder(project)
    if (new_items_folder && !self.incoming?)
      disable_authorization_checks do
        new_items_folder.add_assets(assets)
      end
    end
    children.destroy_all
  end

end