discogs-wrapper 1.0.0

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.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