discogs-wrapper 1.0.0

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.markdown +81 -0
  2. data/Rakefile +27 -0
  3. data/discogs.gemspec +19 -0
  4. data/lib/discogs.rb +20 -0
  5. data/lib/wrapper/resource.rb +79 -0
  6. data/lib/wrapper/resource_mappings.rb +84 -0
  7. data/lib/wrapper/resources/artist.rb +37 -0
  8. data/lib/wrapper/resources/artist_release.rb +17 -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 +61 -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 +105 -0
  21. data/spec/resource_spec.rb +27 -0
  22. data/spec/resources/artist_release_spec.rb +59 -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 +36 -0
  36. data/spec/wrapper_methods/get_artist_spec.rb +109 -0
  37. data/spec/wrapper_methods/get_label_spec.rb +89 -0
  38. data/spec/wrapper_methods/get_release_spec.rb +123 -0
  39. data/spec/wrapper_methods/search_spec.rb +330 -0
  40. data/spec/wrapper_spec.rb +162 -0
  41. metadata +126 -0
data/README.markdown ADDED
@@ -0,0 +1,81 @@
1
+ Discogs::Wrapper
2
+ ================
3
+
4
+ ABOUT
5
+ -----
6
+ A 100% Ruby wrapper of the 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
+ The master branch aims to give full support for version 2.0 of the API. If you need support for everything in version 1.0, see the api-v1 branch.
11
+
12
+ Specifically:
13
+
14
+ * Artists
15
+ * Releases
16
+ * Labels
17
+ * Searching (all of the above)
18
+
19
+ Please, [see the Wiki](http://github.com/buntine/discogs/wiki) for helpful documentation.
20
+
21
+ The Discogs API is [documented here](http://www.discogs.com/help/api).
22
+
23
+ INSTALLATION
24
+ ------------
25
+ You can install the library via Rubygems:
26
+
27
+ $ gem sources -a http://gems.github.com
28
+ $ sudo gem install buntine-discogs
29
+
30
+ USAGE
31
+ -----
32
+ To use this library, you must supply a valid User-agent value. For example:
33
+
34
+ require 'discogs'
35
+ wrapper = Discogs::Wrapper.new("Mozilla/5.0 (X11; Linux i686; rv:6.0.2) Gecko/20100101 Firefox/6.0.2")
36
+
37
+ I suggest passing on your users User-agent.
38
+
39
+ Accessing information is easy:
40
+
41
+ artist = wrapper.get_artist("Master's Hammer")
42
+ release = wrapper.get_release("611973") # Supply an ID.
43
+ label = wrapper.get_label("Monitor Records")
44
+ search_results = wrapper.search("Necrovore")
45
+
46
+ artist.name # => "Master's Hammer"
47
+ artist.releases[0].title # => "Finished"
48
+ artist.releases[1].year # => "1989"
49
+ artist.releases[4].extraartists # => [ "Arakain", "Debustrol" ]
50
+
51
+ release.title # => "Ritual"
52
+ release.labels[0].name # => "Osmose Productions"
53
+ release.formats[0].descriptions[0] # => "LP"
54
+ release.styles # => [ "Black Metal", "Death Metal" ]
55
+ release.tracklist[1].title # => "Pad modly"
56
+
57
+ label.images[0].width # => "220"
58
+ label.releases.length # => 22
59
+ label.releases[3].artist # => "Root"
60
+ label.releases[7].catno # => "MON007"
61
+
62
+ search.total_results # => 124
63
+ search.total_pages # => 7
64
+ search.current_page # => 1
65
+
66
+ # Exact results
67
+ search.exact[0].type # => "artist"
68
+ search.exact[0].title # => "Necrovore"
69
+ search.exact(:label)[0].title # => "Necrovores Records"
70
+ search.closest(:artist) # => <Discogs::Search::Result:0x324ad3e2>
71
+
72
+ # All results
73
+ search.results[3].title # => "Necrovore - Demo '87"
74
+ search.results[3].summary # => "First and only demo tape"
75
+ search.results(:release)[0] # => <Discogs::Search::Result:0x343de34a>
76
+
77
+
78
+ LICENSE
79
+ -------
80
+
81
+ <a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/3.0/80x15.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Discogs::Wrapper</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://github.com/buntine/discogs" property="cc:attributionName" rel="cc:attributionURL">Andrew Buntine</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="http://www.discogs.com/help/api" rel="dct:source">www.discogs.com</a>.
data/Rakefile ADDED
@@ -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
data/discogs.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+
3
+ s.name = "discogs-wrapper"
4
+ s.version = "1.0.0"
5
+ s.date = "2011-09-27"
6
+ s.summary = "Discogs::Wrapper is a full wrapper for the http://www.discogs.com API V2"
7
+ s.homepage = "http://www.github.com/buntine/discogs"
8
+ s.email = "info@andrewbuntine.com"
9
+ s.authors = ["Andrew Buntine", "Ed Hickey"]
10
+
11
+ s.description = "Discogs::Wrapper is a full wrapper for the http://www.discogs.com API V2"
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.markdown", "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
data/lib/discogs.rb ADDED
@@ -0,0 +1,20 @@
1
+
2
+ ## Discogs::Wrapper
3
+ ## by Andrew Buntine, 2009
4
+ ##
5
+ ## This library provides full access to the Discogs.com API v1.0
6
+ ##
7
+ ## Please file all bug reports at http://www.github.com/buntine/discogs, or
8
+ ## email me at info@andrewbuntine.com.
9
+ ##
10
+ ## Enjoy!
11
+
12
+ # Application namespace.
13
+ module Discogs; end
14
+
15
+ # Custom exceptions.
16
+ class Discogs::UnknownResource < Exception; end
17
+ class Discogs::InternalServerError < Exception; end
18
+
19
+ # Loading sequence.
20
+ require File.dirname(__FILE__) + "/wrapper/wrapper"
@@ -0,0 +1,79 @@
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
+ # Create an instance of the named resource and build it.
38
+ if !singular.nil?
39
+ nested_object = singular.send(:new, element.to_s)
40
+ self.send(setter, nested_object.build!)
41
+
42
+ # Setup an array and build each child.
43
+ elsif !plural.nil?
44
+ set_accessors_from_attributes(element)
45
+
46
+ self.send(setter, [])
47
+ element.each_element do |sub_element|
48
+ nested_object = plural.send(:new, sub_element.to_s)
49
+ self.send(name) << nested_object.build!
50
+ end
51
+
52
+ elsif self.respond_to? setter
53
+ self.send(setter, element.text)
54
+ end
55
+ end
56
+
57
+ self
58
+ end
59
+
60
+ def build_with_resp!
61
+ build!(false)
62
+ end
63
+
64
+ private
65
+
66
+ # Sets accessors on _self_ from the attributes of the given element.
67
+ def set_accessors_from_attributes(element)
68
+ element.attributes.each_attribute do |attribute|
69
+ setter = (attribute.expanded_name + "=").to_sym
70
+
71
+ if self.respond_to? setter
72
+ self.send(setter, attribute.value)
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ Dir[File.join(File.dirname(__FILE__), "resources", "*.rb")].each { |file| require file }
@@ -0,0 +1,84 @@
1
+ # Abstracts the resource-mapping class methods.
2
+ #
3
+ # Each "resource" in the wrapper maps to one or more elements
4
+ # in the API response. This way they can be recursively built
5
+ # without having to manually specify it in each class.
6
+
7
+ module Discogs::ResourceMappings
8
+
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ # Helper method to map resource to element in API response.
16
+ def map_to(*elements)
17
+ self.class_eval <<-EOF
18
+ def self.element_names
19
+ #{elements.inspect}
20
+ end
21
+ EOF
22
+ end
23
+
24
+ # Helper method to map pluralised resource to element in API response.
25
+ def map_to_plural(*elements)
26
+ self.class_eval <<-EOF
27
+ def self.plural_element_names
28
+ #{elements.inspect}
29
+ end
30
+ EOF
31
+ end
32
+
33
+ # Used by root classes (Discogs::Artist, etc) that should be built internally.
34
+ def no_mapping
35
+ self.class_eval <<-EOF
36
+ def self.element_names; []; end
37
+ def self.plural_element_names; []; end
38
+ EOF
39
+ end
40
+
41
+ # Element defaults to prevent excess boilerplate code.
42
+ def element_names
43
+ [ self.to_s.split("::")[-1].downcase.to_sym ]
44
+ end
45
+ def plural_element_names
46
+ [ (self.element_names[0].to_s + "s").to_sym ]
47
+ end
48
+
49
+ end
50
+
51
+ private
52
+
53
+ def find_resource_for_name(name, type=:singular)
54
+ method = if type == :singular
55
+ :element_names
56
+ else
57
+ :plural_element_names
58
+ end
59
+
60
+ find_resource do |klass|
61
+ klass.constants.find do |const|
62
+ if klass.const_get(const).respond_to? method
63
+ klass.const_get(const).send(method).any? { |element| element.eql?(name) }
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # Look in _namespace_ for a matching resource class.
70
+ # First looks in the children of _self_ namespace, and then looks more
71
+ # generally. Returns nil if nothing is found.
72
+ def find_resource(namespace=self.class, &matcher)
73
+ match = matcher.call(namespace)
74
+
75
+ if match
76
+ match = namespace.const_get(match)
77
+ elsif namespace == self.class
78
+ match = find_resource(Discogs, &matcher)
79
+ end
80
+
81
+ return match
82
+ end
83
+
84
+ end
@@ -0,0 +1,37 @@
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
+ def main_releases
17
+ filter_releases("Main")
18
+ end
19
+
20
+ def bootlegs
21
+ filter_releases("UnofficialRelease")
22
+ end
23
+
24
+ def appearances
25
+ filter_releases("Appearance")
26
+ end
27
+
28
+ private
29
+
30
+ # Simple helper for filtering a particular type of release.
31
+ def filter_releases(type)
32
+ self.releases.find_all do |release|
33
+ release.type == type
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,17 @@
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
+ :artist,
12
+ :format,
13
+ :year,
14
+ :label,
15
+ :trackinfo
16
+
17
+ 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