athenaeum 1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ Copyright (c) 2007, LAIKA Inc. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are
5
+ met:
6
+
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of the LAIKA, Inc nor the names of its contributors
15
+ may be used to endorse or promote products derived from this software
16
+ without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,19 @@
1
+ = Athenaeum
2
+
3
+ Athenaeum is a small web application meant to read and display the items
4
+ checked out from your Delicious Library.
5
+
6
+ == Dependencies
7
+
8
+ * Delicious Library - http://www.delicious-monster.com
9
+ * RubyCocoa - http://rubycocoa.sf.net
10
+ * hpricot - http://code.whytheluckystiff.net/hpricot
11
+ * mongrel - http://mongrel.rubyforge.org
12
+
13
+ == Authors
14
+
15
+ * Ben Bleything - <mailto:bbleything@laika.com>
16
+
17
+ == License and Copyright
18
+
19
+ Athenaeum is copyright (c) 2007, LAIKA Inc. It is distributed under the terms of the BSD license.
@@ -0,0 +1,128 @@
1
+ ##############################################################
2
+ # Copyright 2007, LAIKA, Inc. #
3
+ # #
4
+ # Based heavily on Ben Bleything's Rakefile for plist, which #
5
+ # is in turn based on Geoffrey Grosenbach's Rakefile for #
6
+ # gruff. #
7
+ # #
8
+ # Includes whitespace-fixing task based on code from Typo. #
9
+ # #
10
+ # Authors: #
11
+ # * Ben Bleything <bbleything@laika.com> #
12
+ ##############################################################
13
+
14
+ require 'fileutils'
15
+ require 'rubygems'
16
+ require 'rake'
17
+ require 'rake/rdoctask'
18
+ require 'rake/packagetask'
19
+ require 'rake/gempackagetask'
20
+ require 'rake/contrib/rubyforgepublisher'
21
+
22
+ $:.unshift(File.dirname(__FILE__) + "/lib")
23
+ require 'athenaeum'
24
+
25
+ PKG_NAME = Athenaeum::NAME.downcase
26
+ PKG_VERSION = Athenaeum::VERSION
27
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
28
+
29
+ RELEASE_NAME = "REL #{PKG_VERSION}"
30
+
31
+ RUBYFORGE_PROJECT = "athenaeum"
32
+ RUBYFORGE_USER = ENV['RUBYFORGE_USER']
33
+
34
+ TEXT_FILES = %w( Rakefile README LICENSE )
35
+ LIB_FILES = Dir.glob('lib/**/*').delete_if { |item| item.include?( "\.svn" ) }
36
+ RELEASE_FILES = TEXT_FILES + LIB_FILES
37
+
38
+ task :default => [ :clean ]
39
+
40
+ desc "Clean pkg, coverage, and rdoc; remove .bak files"
41
+ task :clean => [ :clobber_rdoc, :clobber_package ] do
42
+ puts cmd = "find . -type f -name *.bak -delete"
43
+ `#{cmd}`
44
+ end
45
+
46
+ desc "Strip trailing whitespace and fix newlines for all release files"
47
+ task :fix_whitespace => [ :clean ] do
48
+ RELEASE_FILES.each do |filename|
49
+ next if File.directory? filename
50
+
51
+ File.open(filename) do |file|
52
+ newfile = ''
53
+ needs_love = false
54
+
55
+ file.readlines.each_with_index do |line, lineno|
56
+ if line =~ /[ \t]+$/
57
+ needs_love = true
58
+ puts "#{filename}: trailing whitespace on line #{lineno}"
59
+ line.gsub!(/[ \t]*$/, '')
60
+ end
61
+
62
+ if line.chomp == line
63
+ needs_love = true
64
+ puts "#{filename}: no newline on line #{lineno}"
65
+ line << "\n"
66
+ end
67
+
68
+ newfile << line
69
+ end
70
+
71
+ if needs_love
72
+ tempname = "#{filename}.new"
73
+
74
+ File.open(tempname, 'w').write(newfile)
75
+ File.chmod(File.stat(filename).mode, tempname)
76
+
77
+ FileUtils.ln filename, "#{filename}.bak"
78
+ FileUtils.ln tempname, filename, :force => true
79
+ File.unlink(tempname)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+
86
+ desc "Copy documentation to rubyforge"
87
+ task :update_rdoc => [ :rdoc ] do
88
+ Rake::SshDirPublisher.new("#{RUBYFORGE_USER}@rubyforge.org", "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}", "rdoc").upload
89
+ end
90
+
91
+
92
+ ### Genereate the RDoc documentation
93
+ Rake::RDocTask.new { |rdoc|
94
+ rdoc.rdoc_dir = 'rdoc'
95
+ rdoc.title = "#{Athenaeum::NAME} - #{Athenaeum::DESCRIPTION}"
96
+ rdoc.options << '-SNmREADME'
97
+
98
+ rdoc.rdoc_files.include TEXT_FILES
99
+ rdoc.rdoc_files.include LIB_FILES
100
+ rdoc.rdoc_files.include Dir.glob('docs/**').delete_if {|f| f.include? 'jamis' }
101
+ }
102
+
103
+
104
+ ### Create compressed packages
105
+ spec = Gem::Specification.new do |s|
106
+ s.name = PKG_NAME
107
+ s.version = PKG_VERSION
108
+
109
+ s.summary = "#{Athenaeum::NAME} - #{Athenaeum::DESCRIPTION}"
110
+ s.description = Athenaeum::LONG_DESC
111
+
112
+ s.authors = "LAIKA, Inc."
113
+ s.homepage = "http://opensource.laika.com"
114
+ s.rubyforge_project = RUBYFORGE_PROJECT
115
+
116
+ s.has_rdoc = true
117
+
118
+ s.files = RELEASE_FILES
119
+ s.executables = 'athenaeum'
120
+
121
+ s.autorequire = 'athenaeum'
122
+ end
123
+
124
+ Rake::GemPackageTask.new(spec) do |p|
125
+ p.gem_spec = spec
126
+ p.need_tar = true
127
+ p.need_zip = true
128
+ end
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Athenaeum is a small web application meant to read and display the items
8
+ # checked out from your Delicious Library.
9
+ #
10
+ # == Authors
11
+ #
12
+ # * Ben Bleything <bbleything@laika.com>
13
+ #
14
+ # == Copyright
15
+ #
16
+ # Copyright (c) 2007 LAIKA, Inc
17
+ #
18
+ # == Version
19
+ #
20
+ # $Id: athenaeum 288 2007-08-01 22:35:03Z bbleything $
21
+
22
+ require 'athenaeum'
23
+
24
+ ########################################################################
25
+ ### S E T U P
26
+ ########################################################################
27
+
28
+ # fetch the DL data from the running user's home directory
29
+ @xml = File.read( "/Users/#{`whoami`.strip}/Library/Application\ Support/Delicious\ Library/Library\ Media\ Data.xml" )
30
+ @doc = Hpricot.XML( @xml )
31
+
32
+ ########################################################################
33
+ ### B U I L D L I B R A R Y
34
+ ########################################################################
35
+
36
+ # this query will get us all the top-level books, movies, music, and games
37
+ #from the item container. This prevents us from accidentally grabbing the
38
+ # recommendations and related items.
39
+ @doc.at( "/library/items" ).search( "/book | /movie | /music | /game" ) do |item|
40
+ Athenaeum::Item.create( item )
41
+ end
42
+
43
+ # fetches all the borrowers from the xml, creating Athenaeum::Borrower objects
44
+ # for each. This must happen *after* the Items are found, because
45
+ # Athenaeum::Borrower uses Athenaeum::Item's registry to build its internal
46
+ # registry.
47
+ @doc.search( "/library/borrowers/borrower" ).each do |b|
48
+ Athenaeum::Borrower.new( b )
49
+ end
50
+
51
+ ########################################################################
52
+ ### O U T P U T ! ! ! 1
53
+ ########################################################################
54
+
55
+ Athenaeum::Item.types.sort_by {|k| k.type_name}.each do |type|
56
+ items = Athenaeum::Item.find_by_type( type )
57
+ next if items.empty?
58
+
59
+ type_name = type.type_name
60
+ type_name << 's' unless type_name == 'Music'
61
+
62
+ # +-----+
63
+ # | foo |
64
+ # +-----+----------------------------------------------------------------------+
65
+ puts "+-" + ( '-' * type_name.length ) + "-+"
66
+ puts "| #{type_name} |"
67
+ puts "+-" + ( '-' * type_name.length ) + "-+" + ( '-' * (79 - type_name.length - 6) ) + "+"
68
+ puts
69
+
70
+ # get the items of this type, sorted by title
71
+ items.sort_by {|item| item.title }.each do |item|
72
+ puts "- #{item.title} by #{item.creator}"
73
+
74
+ if loan = Athenaeum::Loan.find_by_item_uuid( item.uuid )
75
+ due_date = loan.due_date.strftime( '%B %d, %Y' )
76
+ puts " - loaned to #{loan.borrower.name} (#{loan.borrower.email}), due on #{due_date}"
77
+ end
78
+ end
79
+
80
+ puts # blank line for clarity
81
+ end
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Athenaeum is a small web application meant to read and display the items
8
+ # checked out from your Delicious Library.
9
+ #
10
+ # == Authors
11
+ #
12
+ # * Ben Bleything <bbleything@laika.com>
13
+ #
14
+ # == Copyright
15
+ #
16
+ # Copyright (c) 2007 LAIKA, Inc
17
+ #
18
+ # == Version
19
+ #
20
+ # $Id: athenaeum.rb 292 2007-08-02 21:56:18Z bbleything $
21
+
22
+ ### standard library
23
+ require 'date'
24
+
25
+ ### rubygems
26
+ require 'rubygems'
27
+ require 'hpricot'
28
+
29
+ ### rubycocoa
30
+ require 'osx/cocoa'
31
+
32
+ module Athenaeum
33
+ NAME = "Athenaeum"
34
+ DESCRIPTION = "A small webapp to display the contents of your Delicious Library"
35
+ LONG_DESC = "Athenaeum is a collection of libraries to read and display the contents of your Delicious Library. It includes the ability to display what items are checked out, to whom, and when they are due."
36
+ VERSION = "1.0"
37
+ end
38
+
39
+ ### athenaeum
40
+ require 'athenaeum/borrower'
41
+ require 'athenaeum/item'
42
+ require 'athenaeum/loan'
43
+
44
+ require 'athenaeum/itemtypes/book'
45
+ require 'athenaeum/itemtypes/game'
46
+ require 'athenaeum/itemtypes/movie'
47
+ require 'athenaeum/itemtypes/music'
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum::Borrower
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Represents a person who has borrowed an item.
8
+ #
9
+ # Accepts a <borrower> record (as an Hpricot::Elem) and creates an object that
10
+ # represents that data.
11
+ #
12
+ # == Authors
13
+ #
14
+ # * Ben Bleything <bbleything@laika.com>
15
+ #
16
+ # == Copyright
17
+ #
18
+ # Copyright (c) 2007 LAIKA, Inc
19
+ #
20
+ # == Version
21
+ #
22
+ # $Id: borrower.rb 287 2007-08-01 22:15:57Z bbleything $
23
+
24
+ class Athenaeum::Borrower
25
+ # load the AddressBook framework from RubyCocoa
26
+ OSX.require_framework 'AddressBook'
27
+
28
+ attr_reader :email, :id, :name
29
+
30
+ # takes an Hpricot::Elem representing a borrower.
31
+ def initialize( info )
32
+ raise "Must provide an Hpricot::Elem object" unless
33
+ info.is_a? Hpricot::Elem
34
+
35
+ @id = info[ :id ]
36
+
37
+ if ab_record = fetch_ab_record( @id )
38
+ @name, @email = extract_data( ab_record )
39
+ else
40
+ @name = @email = 'Unknown'
41
+ end
42
+
43
+ info.search( "/loan" ).each {|loan| Athenaeum::Loan.new( self, loan ) }
44
+ end
45
+
46
+ # return an HTML representation of this borrower
47
+ def to_html
48
+ inner = if email !~ /unknown email address/
49
+ "<a href='mailto:#{self.email}'>#{self.name}</a>"
50
+ else
51
+ self.name
52
+ end
53
+
54
+ return "<span class='borrower'>#{inner}</span>"
55
+ end
56
+
57
+ ########################################################################
58
+ private
59
+ ########################################################################
60
+
61
+ # given a uuid, finds the record in the Address Book
62
+ def fetch_ab_record( id )
63
+ return OSX::ABAddressBook.sharedAddressBook.recordForUniqueId( id )
64
+ end
65
+
66
+ # fetches name and email from Address Book
67
+ def extract_data( ab_record )
68
+ return extract_name( ab_record ), extract_email( ab_record )
69
+ end
70
+
71
+ # fetches name from Address Book
72
+ def extract_name( ab_record )
73
+ first = ab_record.valueForProperty( 'First' )
74
+ last = ab_record.valueForProperty( 'Last' )
75
+
76
+ return "#{first} #{last}"
77
+ end
78
+
79
+ # fetches primary email from Address Book
80
+ def extract_email( ab_record )
81
+ if emails = ab_record.valueForProperty( 'Email' )
82
+ # emails is a multivalue list, so we need to find the primary
83
+ # identifier and then...
84
+ primary_id = emails.primaryIdentifier
85
+ # ... fetch the value associated with the primary id
86
+ return emails.valueAtIndex( emails.indexForIdentifier( primary_id ) ).to_s
87
+ else
88
+ return 'unknown email address'
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum::Item
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Represents an item from your collection. This is the semi-abstract
8
+ # superclass from which the actual object types descend.
9
+ #
10
+ # == Authors
11
+ #
12
+ # * Ben Bleything <bbleything@laika.com>
13
+ #
14
+ # == Copyright
15
+ #
16
+ # Copyright (c) 2007 LAIKA, Inc
17
+ #
18
+ # == Version
19
+ #
20
+ # $Id: item.rb 290 2007-08-02 18:26:29Z bbleything $
21
+
22
+ class Athenaeum::Item
23
+ ########################################################################
24
+ ### I N I T I A L I Z E R S
25
+ ########################################################################
26
+
27
+ # the initializer is not used directly, rather it is inherited by the
28
+ # subclasses and used in them.
29
+ def initialize( item )
30
+ item.attributes.keys.each do |name|
31
+ # add getter
32
+ (class << self ; self ; end).instance_eval {
33
+ attr_reader name.to_s.intern
34
+ }
35
+
36
+ # set ivar. Use raw_attributes because that's the only way to
37
+ # get the un-unescaped content.
38
+ instance_variable_set "@#{name}", item.raw_attributes[ name ]
39
+ end
40
+
41
+ @@registry ||= []
42
+ @@registry << self
43
+ end
44
+
45
+ # this is the initializer that actually gets used. Pass the appropriate
46
+ # kind of Hpricot::Elem object (representing an item in the xml) and it
47
+ # will give you the appropriate type of item back.
48
+ def self::create( item )
49
+ raise "Must provide an Hpricot::Elem object" unless
50
+ item.is_a? Hpricot::Elem
51
+
52
+ Athenaeum.const_get( item.etag.name.capitalize ).new( item )
53
+ end
54
+
55
+ ########################################################################
56
+ ### M A G I C H O O K S
57
+ ########################################################################
58
+
59
+ # keep a registry of subclasses, for self::types, below
60
+ def self::inherited( klass )
61
+ @@subclasses ||= []
62
+ @@subclasses << klass
63
+ end
64
+
65
+ ########################################################################
66
+ ### I N T R O S P E C T I O N
67
+ ########################################################################
68
+
69
+ # simple getter for the item registry
70
+ def self::registry
71
+ @@registry ||= []
72
+ return @@registry
73
+ end
74
+
75
+ # the name of this particular type... book, music, game, movie, etc
76
+ def self::type_name
77
+ self.to_s.split( /::/ ).last
78
+ end
79
+
80
+ # simple getter for the subclass registry
81
+ def self::types
82
+ @@subclasses || []
83
+ end
84
+
85
+ ########################################################################
86
+ ### F I N D E R S
87
+ ########################################################################
88
+
89
+ # searches through the registry, finding all items of a given subclass
90
+ def self::find_by_type( type )
91
+ return @@registry.select {|item| item.is_a? type }
92
+ end
93
+
94
+ # searches through the registry, returning the item with the uuid
95
+ # specified
96
+ def self::find_by_uuid( uuid )
97
+ return @@registry.detect {|item| item.uuid == uuid }
98
+ end
99
+
100
+ ########################################################################
101
+ ### I N S T A N C E M E T H O D S
102
+ ########################################################################
103
+
104
+ # returns a decent HTML representation of the item
105
+ def to_html
106
+ return "<span class='title'>#{self.title}</span> <span class='creator'>by #{self.creator}</span>"
107
+ end
108
+
109
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum::Book
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Represents a book from your collection.
8
+ #
9
+ # == Authors
10
+ #
11
+ # * Ben Bleything <bbleything@laika.com>
12
+ #
13
+ # == Copyright
14
+ #
15
+ # Copyright (c) 2007 LAIKA, Inc
16
+ #
17
+ # == Version
18
+ #
19
+ # $Id: book.rb 285 2007-08-01 21:38:27Z bbleything $
20
+
21
+ class Athenaeum::Book < Athenaeum::Item
22
+ # alias author to creator
23
+ def creator
24
+ creator = self.author rescue nil
25
+ return creator || 'Unknown Author'
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum::Game
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Represents a video game from your collection.
8
+ #
9
+ # == Authors
10
+ #
11
+ # * Ben Bleything <bbleything@laika.com>
12
+ #
13
+ # == Copyright
14
+ #
15
+ # Copyright (c) 2007 LAIKA, Inc
16
+ #
17
+ # == Version
18
+ #
19
+ # $Id: game.rb 284 2007-08-01 18:01:14Z bbleything $
20
+
21
+ class Athenaeum::Game < Athenaeum::Item
22
+ # alias publisher to creator
23
+ def creator
24
+ self.publisher
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum::Movie
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Represents a movie from your collection.
8
+ #
9
+ # == Authors
10
+ #
11
+ # * Ben Bleything <bbleything@laika.com>
12
+ #
13
+ # == Copyright
14
+ #
15
+ # Copyright (c) 2007 LAIKA, Inc
16
+ #
17
+ # == Version
18
+ #
19
+ # $Id: movie.rb 285 2007-08-01 21:38:27Z bbleything $
20
+
21
+ class Athenaeum::Movie < Athenaeum::Item
22
+ # alias director (or, failing that, publisher) to creator
23
+ def creator
24
+ creator = self.director rescue nil
25
+ return creator || 'Unknown Director'
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum::Music
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Represents an audio recording from your collection.
8
+ #
9
+ # == Authors
10
+ #
11
+ # * Ben Bleything <bbleything@laika.com>
12
+ #
13
+ # == Copyright
14
+ #
15
+ # Copyright (c) 2007 LAIKA, Inc
16
+ #
17
+ # == Version
18
+ #
19
+ # $Id: music.rb 285 2007-08-01 21:38:27Z bbleything $
20
+
21
+ class Athenaeum::Music < Athenaeum::Item
22
+ # alias artist to creator
23
+ def creator
24
+ creator = self.artist rescue nil
25
+ return creator || 'Unknown Artist'
26
+ end
27
+ end
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Athenaeum::Loan
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # Encapsulates the relationship between a borrower and an item. Any instance
8
+ # of this class represented an item that has been loaned out to a particular
9
+ # person.
10
+ #
11
+ # == Authors
12
+ #
13
+ # * Ben Bleything <bbleything@laika.com>
14
+ #
15
+ # == Copyright
16
+ #
17
+ # Copyright (c) 2007 LAIKA, Inc
18
+ #
19
+ # == Version
20
+ #
21
+ # $Id: loan.rb 289 2007-08-01 23:17:06Z bbleything $
22
+
23
+ class Athenaeum::Loan
24
+ attr_reader :borrower, :item, :due_date
25
+
26
+ # take a borrower and a loan tag, and create an object to encapsulate
27
+ # them. Searches the Item registry for the item.
28
+ def initialize( borrower, loan )
29
+ raise "Must provide an Athenaeum::Borrower object" unless
30
+ borrower.is_a? Athenaeum::Borrower
31
+
32
+ raise "Must provide an Hpricot::Elem object" unless
33
+ loan.is_a? Hpricot::Elem
34
+
35
+ @item = Athenaeum::Item.find_by_uuid( loan[ :mediaID ] )
36
+ @borrower = borrower
37
+ @due_date = Date.strptime( loan[ :dueDate ], '%d-%m-%Y' )
38
+
39
+ @@registry ||= []
40
+ @@registry << self
41
+ end
42
+
43
+ ########################################################################
44
+ ### I N T R O S P E C T I O N
45
+ ########################################################################
46
+
47
+ # simple getter for the loan registry
48
+ def self::registry
49
+ @@registry ||= []
50
+ return @@registry
51
+ end
52
+
53
+ ########################################################################
54
+ ### F I N D E R S
55
+ ########################################################################
56
+
57
+ # searches the Loan registry and returns the loan for the item with the
58
+ # given uuid, if any.
59
+ def self::find_by_item_uuid( uuid )
60
+ @@registry ||= []
61
+ return @@registry.detect {|loan| loan.item.uuid == uuid }
62
+ end
63
+
64
+ # searches the Loan registry and returns all loans that belong to the
65
+ # specified borrower.
66
+ def self::find_by_borrower_id( id )
67
+ @@registry ||= []
68
+ return @@registry.select {|loan| loan.borrower.id == id }
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: athenaeum
5
+ version: !ruby/object:Gem::Version
6
+ version: "1.0"
7
+ date: 2007-09-10 00:00:00 -07:00
8
+ summary: Athenaeum - A small webapp to display the contents of your Delicious Library
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage: http://opensource.laika.com
13
+ rubyforge_project: athenaeum
14
+ description: Athenaeum is a collection of libraries to read and display the contents of your Delicious Library. It includes the ability to display what items are checked out, to whom, and when they are due.
15
+ autorequire: athenaeum
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - LAIKA, Inc.
31
+ files:
32
+ - Rakefile
33
+ - README
34
+ - LICENSE
35
+ - lib/athenaeum
36
+ - lib/athenaeum/borrower.rb
37
+ - lib/athenaeum/item.rb
38
+ - lib/athenaeum/itemtypes
39
+ - lib/athenaeum/itemtypes/book.rb
40
+ - lib/athenaeum/itemtypes/game.rb
41
+ - lib/athenaeum/itemtypes/movie.rb
42
+ - lib/athenaeum/itemtypes/music.rb
43
+ - lib/athenaeum/loan.rb
44
+ - lib/athenaeum.rb
45
+ test_files: []
46
+
47
+ rdoc_options: []
48
+
49
+ extra_rdoc_files: []
50
+
51
+ executables:
52
+ - athenaeum
53
+ extensions: []
54
+
55
+ requirements: []
56
+
57
+ dependencies: []
58
+