buntine-discogs 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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