Skip to content

Instantly share code, notes, and snippets.

@localshred
Created October 29, 2009 04:05
Show Gist options
  • Save localshred/221136 to your computer and use it in GitHub Desktop.
Save localshred/221136 to your computer and use it in GitHub Desktop.
<div id="files-<%= group.folder_name %>" class="files">
<% if group.has_files? -%>
<ul>
<% group.files.each do |file| -%>
<li><%= link_to_audio_file(file) %></li>
<% end -%>
</ul>
<% else -%>
<p class="emphasis">No files available.</p>
<% end -%>
</div>
<div id="group-<%= group.folder_name %>" class="group">
<% if group.has_files? -%>
<p><a href="javascript: void(0);" title="Show group files" id="group-link-<%= group.folder_name %>" class="group-link"><%= group.display_name %></a></p>
<% else -%>
<p><%= group.display_name %></p>
<% end -%>
<%= render_file_tree(group.groups) if group.has_groups? %>
</div>
require 'digest/md5'
module AudioLib
# Currently only checks for mp3 and m4a files
def self.is_audio_file?(file_name)
File.file?(file_name) && File.basename(file_name) =~ AudioLib.file_format[:regexp]
end
def self.file_format
{
:regexp => /^[-a-z0-9 ]+\.(mp3|m4a)$/i,
:glob => "*.m[p4][34a]"
}
end
class AudioFile
attr_accessor :full_path, :name, :hash_name
def self.find(options={})
# Determine the group or path to search
if options.include? :group
path = options[:group].full_path
elsif options.include? :path
path = options[:path]
else
raise ArgumentError, "You must specify the :group or :path to search."
end
# Determine the name glob to use
if options.include? :name
name_glob = options[:name]
else
name_glob = AudioLib.file_format[:glob]
end
if options.include? :recursive
path = File.join(path, "**")
end
file_glob = File.join(path, name_glob)
print "file glob #{file_glob}"
# Walk the file tree
files = Dir[file_glob].map do |file|
unless file.nil? || !AudioLib.is_audio_file?(file)
AudioLib::AudioFile.new(file)
end
end
files.uniq!
files.delete nil
if options.include? :name
unless files.nil? || files.empty?
files[0]
else
nil
end
else
files
end
end
# Initializes a new file based on a full_path name.
# The file folder must be a valid file and match a specific named format
def initialize(file_path)
raise ArgumentError, "File name or path is invalid" unless AudioLib.is_audio_file?(file_path)
@full_path = File.expand_path file_path
@name = File.basename file_path
end
def size
File.size @full_path
end
end
end
module AudioLib
# Ensures the folder name format is sort-name (e.g. 001-ultimate)
def self.is_group?(group_name)
File.directory?(group_name) && File.basename(group_name) =~ AudioLib.group_format[:regexp]
end
def self.group_format
{
:regexp => /^\d+-[a-z]+$/i,
:glob => "[0-9][0-9][0-9]-*"
}
end
# Recursively build a group/file tree
def self.build_tree(starting_group=nil)
raise ArgumentError, "Starting group needs to be an AudioLib::AudioGroup object" unless starting_group.nil? || starting_group.is_a?(AudioLib::AudioGroup)
starting_group = AudioLib::AudioGroup.find if starting_group.nil?
if starting_group.nil?
[]
else
# Start the tree recursion
build_groups(starting_group)
end
end
class AudioGroup
attr_accessor :full_path, :folder_name, :name, :sort, :groups, :files
# Use this find method to search for one or more groups in a given location on the FS
# Options include:
# - :parent (optional) - the folder in which to search. This should always come from RAILS_ROOT. Defaults to APP_CONFIG['audio_products_location']
# - :name (optional) - the Dir#glob name to search for. Defauls to group_format[:glob]
def self.find(options={})
# Determine the folder to search
if options.include? :parent
group_folder = options[:parent]
else
group_folder = File.join(RAILS_ROOT, APP_CONFIG['audio_products_location'])
end
# Determine the name glob to use
if options.include? :name
name_glob = options[:name]
else
name_glob = AudioLib.group_format[:glob]
end
group_glob = File.join(group_folder, name_glob)
# Walk the file tree
groups = Dir[group_glob].map do |group|
unless group.nil? || !AudioLib.is_group?(group)
AudioLib::AudioGroup.new(group)
end
end
groups.uniq!
groups.delete nil
if options.include? :name
unless groups.nil? || groups.empty?
groups[0]
else
nil
end
else
groups
end
end
# Initializes a new group based on a full_path folder name.
# The group folder must be a valid directory and match a specific named format
def initialize(folder_name)
raise ArgumentError, "Group name or path is invalid" unless AudioLib.is_group?(folder_name)
info = File.basename(folder_name).split('-') # folder format is sort-name (e.g. 001-ultimate)
@full_path = File.expand_path(folder_name)
@folder_name = folder_name
@name = info[1]
@sort = info[0]
@groups = nil # Lazy load sub groups
@files = nil # Lazy load files
end
def groups
@groups ||= find_groups
end
def files
@files ||= find_files
end
def display_name
@name.capitalize
end
def folder_name
"#{@sort}-#{@name}"
end
# Enables sub_group searching by key
def [](key)
if (key.to_s =~ /^[\d.]+$/) >= 0
groups[key.to_i]
else
groups.select{|group| key.to_s.strip.downcase == group.name.downcase}
end
end
def first
groups.first
end
def last
groups.last
end
def has_groups?
groups.size > 0
end
def has_files?
files.size > 0
end
private
def find_groups
AudioLib::AudioGroup.find(:parent => @full_path) || []
end
def find_files
AudioLib::AudioFile.find(:group => self) || []
end
end
private
def self.build_groups(groups)
groups.each do |sub_group|
sub_group.files
build_groups(sub_group.groups) if sub_group.has_groups?
end
end
end
<div id="library-contents" class="cf">
<div id="library-banner">&nbsp;</div>
<% unless @file_tree.nil? || @file_tree.empty? -%>
<div id="group-panel">
<%= render_file_tree(@file_tree) %>
</div>
<div id="file-panel">
<div id="files-description" class="files">
...
</div>
<%= render_file_tree(@file_tree, "files") %>
</div>
<% else -%>
<p class="error">Could not load the audio library. Please try again later.</p>
<% end -%>
</div>
class LibraryController > ApplicationController
...
def index
@file_tree = AudioLib.build_tree
end
...
end
def render_file_tree(group_tree, which_render="group")
if group_tree.is_a? AudioLib::AudioGroup
which_render == "group" ? render_group(group_tree) : (render_files(group_tree) if group_tree.has_files?)
elsif group_tree.is_a? Array
out = ""
group_tree.each do |group|
if which_render == "group"
out += render_group(group)
else
out += render_files(group) if group.has_files?
out += render_file_tree(group.groups, "files") if group.has_groups?
end
end
out
end
end
def render_group(group)
render :partial => "group", :locals => { :group => group }
end
def render_files(group)
render :partial => "file", :locals => { :group => group }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment