buntine-discogs 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. data/README +61 -0
  2. data/Rakefile +27 -0
  3. data/discogs.gemspec +19 -0
  4. data/lib/discogs.rb +10 -0
  5. data/lib/wrapper/resource.rb +75 -0
  6. data/lib/wrapper/resource_mappings.rb +80 -0
  7. data/lib/wrapper/resources/artist.rb +16 -0
  8. data/lib/wrapper/resources/artist_release.rb +16 -0
  9. data/lib/wrapper/resources/format.rb +11 -0
  10. data/lib/wrapper/resources/generic_list.rb +29 -0
  11. data/lib/wrapper/resources/image.rb +11 -0
  12. data/lib/wrapper/resources/label.rb +16 -0
  13. data/lib/wrapper/resources/label_release.rb +17 -0
  14. data/lib/wrapper/resources/release.rb +22 -0
  15. data/lib/wrapper/resources/release_artist.rb +18 -0
  16. data/lib/wrapper/resources/release_label.rb +10 -0
  17. data/lib/wrapper/resources/search.rb +17 -0
  18. data/lib/wrapper/resources/search_result.rb +16 -0
  19. data/lib/wrapper/resources/track.rb +15 -0
  20. data/lib/wrapper/wrapper.rb +88 -0
  21. data/spec/resource_spec.rb +27 -0
  22. data/spec/resources/artist_release_spec.rb +55 -0
  23. data/spec/resources/artist_spec.rb +15 -0
  24. data/spec/resources/format_spec.rb +41 -0
  25. data/spec/resources/generic_list_spec.rb +66 -0
  26. data/spec/resources/image_spec.rb +43 -0
  27. data/spec/resources/label_release_spec.rb +55 -0
  28. data/spec/resources/label_spec.rb +15 -0
  29. data/spec/resources/release_artist_spec.rb +43 -0
  30. data/spec/resources/release_label_spec.rb +31 -0
  31. data/spec/resources/release_spec.rb +15 -0
  32. data/spec/resources/search_result_spec.rb +47 -0
  33. data/spec/resources/search_spec.rb +15 -0
  34. data/spec/resources/track_spec.rb +56 -0
  35. data/spec/spec_helper.rb +35 -0
  36. data/spec/wrapper_methods/get_artist_spec.rb +95 -0
  37. data/spec/wrapper_methods/get_label_spec.rb +91 -0
  38. data/spec/wrapper_methods/get_release_spec.rb +125 -0
  39. data/spec/wrapper_methods/search_spec.rb +99 -0
  40. data/spec/wrapper_spec.rb +100 -0
  41. metadata +93 -0
data/README ADDED
@@ -0,0 +1,61 @@
1
+ Discogs::Wrapper
2
+ --------------------------
3
+
4
+ ABOUT
5
+
6
+ A 100% Ruby wrapper of the http://www.discogs.com API. No dependencies, no extra gems. :)
7
+
8
+ Discogs::Wrapper abstracts all the nasty boilerplate code needed to interact with the Discogs API. It gives you direct access to the information you need.
9
+
10
+ Full support for everything in version 1.0 of the API:
11
+
12
+ - Artists
13
+ - Releases
14
+ - Labels
15
+ - Searching
16
+
17
+ The API is documented here: http://www.discogs.com/help/api
18
+
19
+ INSTALLATION
20
+
21
+ You can install the library via Rubygems:
22
+
23
+ $ gem sources -a http://gems.github.com
24
+ $ sudo gem install buntine-discogs
25
+
26
+
27
+ USAGE
28
+
29
+ To use this library, you must supply a valid Discogs API key.
30
+
31
+ wrapper = Discogs::Wrapper.new("my_api_key")
32
+
33
+
34
+ Accessing information is easy:
35
+
36
+ artist = wrapper.get_artist("Master's Hammer")
37
+ release = wrapper.get_release("611973") # Supply an ID.
38
+ label = wrapper.get_label("Monitor Records")
39
+ search_results = wrapper.search("Necrovore")
40
+
41
+ artist.name # => Master's Hammer
42
+ artist.releases[0].title # => Finished
43
+ artist.releases[1].year # => 1989
44
+ artist.releases[4].extraartists # => [ "Arakain", "Debustrol" ]
45
+
46
+ release.title # => "Ritual"
47
+ release.labels[0].name # => "Osmose Productions"
48
+ release.formats[0].descriptions[0] # => "LP"
49
+ release.styles # => [ "Black Metal", "Death Metal" ]
50
+ release.tracklist[1].title # => "Pad modly"
51
+
52
+ label.images[0].width # => "220"
53
+ label.releases.length # => 22
54
+ label.releases[3].artist # => "Root"
55
+ label.releases[7].catno # => "MON007"
56
+
57
+ search.total_results # => "124"
58
+ search.exactresults[0].type # => "artist"
59
+ search.exactresults[0].title # => "Necrovore"
60
+ search.searchresults[3].title # => "Necrovore - Demo '87"
61
+ search.searchresults[3].summary # => "First and only demo tape"
@@ -0,0 +1,27 @@
1
+ require 'rake'
2
+ require 'spec'
3
+ require 'spec/rake/spectask'
4
+ require 'rake/gempackagetask'
5
+
6
+ task :default => :spec
7
+
8
+ desc "Run all specs in spec directory"
9
+ Spec::Rake::SpecTask.new(:spec) do |t|
10
+ t.spec_opts = ["--colour", "--format progress", "--loadby mtime", "--reverse"]
11
+ t.spec_files = FileList[ 'spec/**/*_spec.rb' ]
12
+ end
13
+
14
+ desc "Run all specs and generate RCov report"
15
+ Spec::Rake::SpecTask.new('cov') do |t|
16
+ t.spec_files = FileList['spec/**/*.rb']
17
+ t.spec_opts = ["--colour"]
18
+ t.rcov = true
19
+ t.rcov_opts = ['-T --no-html --exclude', 'spec\/,gems\/']
20
+ end
21
+
22
+ spec = eval(File.read("discogs.gemspec"))
23
+
24
+ Rake::GemPackageTask.new(spec) do |pkg|
25
+ # pkg.need_zip = true
26
+ # pkg.need_tar = true
27
+ end
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+
3
+ s.name = "discogs"
4
+ s.version = "0.3.1"
5
+ s.date = "2009-07-04"
6
+ s.summary = "Discogs::Wrapper is a full wrapper for the http://www.discogs.com API"
7
+ s.homepage = "http://www.github.com/buntine/discogs"
8
+ s.email = "info@andrewbuntine.com"
9
+ s.authors = ["Andrew Buntine"]
10
+
11
+ s.description = "Discogs::Wrapper is a full wrapper for the http://www.discogs.com API"
12
+
13
+ s.files = ["lib/wrapper", "lib/wrapper/resource_mappings.rb", "lib/wrapper/wrapper.rb", "lib/wrapper/resource.rb", "lib/wrapper/resources", "lib/wrapper/resources/format.rb", "lib/wrapper/resources/search.rb", "lib/wrapper/resources/label_release.rb", "lib/wrapper/resources/artist.rb", "lib/wrapper/resources/release_artist.rb", "lib/wrapper/resources/artist_release.rb", "lib/wrapper/resources/release_label.rb", "lib/wrapper/resources/generic_list.rb", "lib/wrapper/resources/search_result.rb", "lib/wrapper/resources/label.rb", "lib/wrapper/resources/image.rb", "lib/wrapper/resources/track.rb", "lib/wrapper/resources/release.rb", "lib/discogs.rb", "Rakefile", "README", "discogs.gemspec"]
14
+
15
+ s.test_files = ["spec/wrapper_methods/get_release_spec.rb", "spec/wrapper_methods/search_spec.rb", "spec/wrapper_methods/get_artist_spec.rb", "spec/wrapper_methods/get_label_spec.rb", "spec/resource_spec.rb", "spec/resources/label_spec.rb", "spec/resources/generic_list_spec.rb", "spec/resources/artist_release_spec.rb", "spec/resources/artist_spec.rb", "spec/resources/release_artist_spec.rb", "spec/resources/search_spec.rb", "spec/resources/label_release_spec.rb", "spec/resources/release_label_spec.rb", "spec/resources/release_spec.rb", "spec/resources/search_result_spec.rb", "spec/resources/image_spec.rb", "spec/resources/track_spec.rb", "spec/resources/format_spec.rb", "spec/wrapper_spec.rb", "spec/spec_helper.rb"]
16
+
17
+ s.platform = Gem::Platform::RUBY
18
+
19
+ end
@@ -0,0 +1,10 @@
1
+
2
+ # Application namespace.
3
+ module Discogs; end
4
+
5
+ # Custom exceptions.
6
+ class Discogs::InvalidAPIKey < Exception; end
7
+ class Discogs::UnknownResource < Exception; end
8
+
9
+ # Loading sequence.
10
+ require File.dirname(__FILE__) + "/wrapper/wrapper"
@@ -0,0 +1,75 @@
1
+ # Represents a generic resource in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/resource_mappings"
4
+
5
+ class Discogs::Resource
6
+
7
+ include Discogs::ResourceMappings
8
+
9
+ def initialize(content)
10
+ @content = content
11
+ end
12
+
13
+ def original_content
14
+ @content
15
+ end
16
+
17
+ # Builds the resource with it's content.
18
+ def build!(remove_resp=true)
19
+ document = REXML::Document.new(@content, :ignore_whitespace_nodes => :all)
20
+ root_node = document.root
21
+
22
+ # Ignore the <resp> element if necessary.
23
+ if remove_resp and document.root.expanded_name == "resp"
24
+ root_node = root_node[0]
25
+ end
26
+
27
+ set_accessors_from_attributes(root_node)
28
+
29
+ # Traverse node children.
30
+ root_node.each_element do |element|
31
+ name = element.expanded_name.to_sym
32
+ setter = (name.to_s + "=").to_sym
33
+
34
+ singular = find_resource_for_name(name, :singular)
35
+ plural = singular ? nil : find_resource_for_name(name, :plural)
36
+
37
+ if !singular.nil?
38
+ nested_object = singular.send(:new, element.to_s)
39
+ self.send(setter, nested_object.build!)
40
+ elsif !plural.nil?
41
+ set_accessors_from_attributes(element)
42
+
43
+ self.send(setter, [])
44
+ element.each_element do |sub_element|
45
+ nested_object = plural.send(:new, sub_element.to_s)
46
+ self.send(name) << nested_object.build!
47
+ end
48
+ elsif self.respond_to? setter
49
+ self.send(setter, element.text)
50
+ end
51
+ end
52
+
53
+ self
54
+ end
55
+
56
+ def build_with_resp!
57
+ build!(false)
58
+ end
59
+
60
+ private
61
+
62
+ # Sets accessors on _self_ from the attributes of the given element.
63
+ def set_accessors_from_attributes(element)
64
+ element.attributes.each_attribute do |attribute|
65
+ setter = (attribute.expanded_name + "=").to_sym
66
+
67
+ if self.respond_to? setter
68
+ self.send(setter, attribute.value)
69
+ end
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ Dir[File.join(File.dirname(__FILE__), "resources", "*.rb")].each { |file| require file }
@@ -0,0 +1,80 @@
1
+ # Abstracts the resource-mapping class methods.
2
+
3
+ module Discogs::ResourceMappings
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ # Helper method to map resource to element in API response.
12
+ def map_to(*elements)
13
+ self.class_eval <<-EOF
14
+ def self.element_names
15
+ #{elements.inspect}
16
+ end
17
+ EOF
18
+ end
19
+
20
+ # Helper method to map pluralised resource to element in API response.
21
+ def map_to_plural(*elements)
22
+ self.class_eval <<-EOF
23
+ def self.plural_element_names
24
+ #{elements.inspect}
25
+ end
26
+ EOF
27
+ end
28
+
29
+ # Used by root classes (Discogs::Artist, etc) that should be built internally.
30
+ def no_mapping
31
+ self.class_eval <<-EOF
32
+ def self.element_names; []; end
33
+ def self.plural_element_names; []; end
34
+ EOF
35
+ end
36
+
37
+ # Element defaults to prevent excess boilerplate code.
38
+ def element_names
39
+ [ self.to_s.split("::")[-1].downcase.to_sym ]
40
+ end
41
+ def plural_element_names
42
+ [ (self.element_names[0].to_s + "s").to_sym ]
43
+ end
44
+
45
+ end
46
+
47
+ private
48
+
49
+ def find_resource_for_name(name, type=:singular)
50
+ method = if type == :singular
51
+ :element_names
52
+ else
53
+ :plural_element_names
54
+ end
55
+
56
+ find_resource do |klass|
57
+ klass.constants.find do |const|
58
+ if klass.const_get(const).respond_to? method
59
+ klass.const_get(const).send(method).any? { |element| element.eql?(name) }
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ # Look in _namespace_ for a matching resource class.
66
+ # First looks in the children of _self_ namespace, and then looks more
67
+ # generally. Returns nil if nothing is found.
68
+ def find_resource(namespace=self.class, &matcher)
69
+ match = matcher.call(namespace)
70
+
71
+ if match
72
+ match = namespace.const_get(match)
73
+ elsif namespace == self.class
74
+ match = find_resource(Discogs, &matcher)
75
+ end
76
+
77
+ return match
78
+ end
79
+
80
+ end
@@ -0,0 +1,16 @@
1
+ # Represents an artist in the Discogs API.
2
+
3
+ class Discogs::Artist < Discogs::Resource
4
+
5
+ no_mapping
6
+
7
+ attr_accessor :name,
8
+ :realname,
9
+ :images,
10
+ :urls,
11
+ :namevariations,
12
+ :aliases,
13
+ :members,
14
+ :releases
15
+
16
+ end
@@ -0,0 +1,16 @@
1
+ # Represents an artist's release in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/artist"
4
+
5
+ class Discogs::Artist::Release < Discogs::Resource
6
+
7
+ attr_accessor :id,
8
+ :status,
9
+ :type,
10
+ :title,
11
+ :format,
12
+ :year,
13
+ :label,
14
+ :trackinfo
15
+
16
+ end
@@ -0,0 +1,11 @@
1
+ # Represents a release format in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/release"
4
+
5
+ class Discogs::Release::Format < Discogs::Resource
6
+
7
+ attr_accessor :name,
8
+ :qty,
9
+ :descriptions
10
+
11
+ end
@@ -0,0 +1,29 @@
1
+ # Represents a generic list of items in the Discogs API.
2
+
3
+ class Discogs::GenericList < Discogs::Resource
4
+
5
+ map_to :descriptions, :genres, :aliases, :namevariations, :styles, :urls, :members, :sublabels
6
+
7
+ map_to_plural :lists
8
+
9
+ # Overload build method to provide custom process for
10
+ # converting contents into something useful.
11
+ def build!
12
+ @items = []
13
+ document = REXML::Document.new(@content)
14
+
15
+ document.root.each_element do |element|
16
+ @items << element.text
17
+ end
18
+
19
+ @items
20
+ end
21
+
22
+ # Provides post-build access to the list.
23
+ def [](index)
24
+ if @items.is_a?(Array)
25
+ @items[index]
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,11 @@
1
+ # Represents an image in the Discogs API.
2
+
3
+ class Discogs::Image < Discogs::Resource
4
+
5
+ attr_accessor :uri,
6
+ :uri150,
7
+ :width,
8
+ :height,
9
+ :type
10
+
11
+ end
@@ -0,0 +1,16 @@
1
+ # Represents a label in the Discogs API.
2
+
3
+ class Discogs::Label < Discogs::Resource
4
+
5
+ no_mapping
6
+
7
+ attr_accessor :name,
8
+ :contactinfo,
9
+ :profile,
10
+ :parentlabel,
11
+ :images,
12
+ :urls,
13
+ :sublabels,
14
+ :releases
15
+
16
+ end
@@ -0,0 +1,17 @@
1
+ # Represents a labels release in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/label"
4
+
5
+ class Discogs::Label::Release < Discogs::Resource
6
+
7
+ attr_accessor :id,
8
+ :status,
9
+ :type,
10
+ :catno,
11
+ :artist,
12
+ :title,
13
+ :format,
14
+ :year,
15
+ :trackinfo
16
+
17
+ end
@@ -0,0 +1,22 @@
1
+ # Represents a release in the Discogs API.
2
+
3
+ class Discogs::Release < Discogs::Resource
4
+
5
+ no_mapping
6
+
7
+ attr_accessor :id,
8
+ :status,
9
+ :title,
10
+ :country,
11
+ :released,
12
+ :notes,
13
+ :images,
14
+ :artists,
15
+ :extraartists,
16
+ :labels,
17
+ :formats,
18
+ :styles,
19
+ :genres,
20
+ :tracklist
21
+
22
+ end
@@ -0,0 +1,18 @@
1
+ # Represents an release's artist in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/track"
4
+
5
+ class Discogs::Release::Artist < Discogs::Resource
6
+
7
+ map_to_plural :artists, :extraartists
8
+
9
+ attr_accessor :name,
10
+ :role,
11
+ :join,
12
+ :anv,
13
+ :tracks
14
+
15
+ end
16
+
17
+ # Define other classes that also replicate this structure.
18
+ class Discogs::Release::Track::Artist < Discogs::Release::Artist; end