freesound-ruby 0.0.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.
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "freesound/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "freesound-ruby"
7
+ s.version = Freesound::VERSION
8
+ s.authors = ["Alex Genco"]
9
+ s.email = ["alexgenco@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Freesound.org API wrapper in Ruby.}
12
+ s.description = %q{Freesound.org API wrapper in Ruby.}
13
+
14
+ s.rubyforge_project = "freesound-ruby"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
18
+ #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency("rspec")
22
+ s.add_development_dependency("bundler", "~> 1.0.0")
23
+ s.add_development_dependency("webmock")
24
+ s.add_runtime_dependency("crack")
25
+ end
@@ -0,0 +1,50 @@
1
+ class Hash
2
+ def symbolize_keys
3
+ Hash[ map { |k, v| [k.to_sym, v] } ]
4
+ end
5
+
6
+ # converting xml into a hash sometimes gives you things like:
7
+ # { 'element' => ['just_one_value'] }
8
+ # this method converts this to the more useful
9
+ # { 'element' => 'just_one_value' }
10
+ def flatten_single_element_array_values
11
+ Hash[ map do |k, v|
12
+ [k, (v.is_a?(Array) && v.size == 1) ? v[0] : v]
13
+ end ]
14
+ end
15
+
16
+ # convert to a uri string
17
+ def to_uri
18
+ map { |k, v| "#{k}=#{v}" }.join("&")
19
+ end
20
+
21
+ def numberize_values
22
+ Hash[ map { |k, v| [k, ( (v.numberizeable? rescue false) ? v.numberize : v )] } ]
23
+ end
24
+
25
+ def underscore_keys
26
+ Hash[ map { |k, v| [(k.underscore rescue k), v] } ]
27
+ end
28
+ end
29
+
30
+ class String
31
+ def numberize
32
+ if numberizeable?
33
+ float? ? to_f : to_i
34
+ end
35
+ end
36
+
37
+ def numberizeable?
38
+ !scan(/^\-?\d*\.?\d*$/).empty?
39
+ end
40
+
41
+ def underscore
42
+ gsub(/\W/, '_')
43
+ end
44
+
45
+ private
46
+
47
+ def float?
48
+ scan(/\./).size == 1
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'crack'
4
+ require 'core_ext'
5
+
6
+ YAML::ENGINE.yamler = 'syck'
7
+
8
+ module Freesound
9
+ def self.root_dir
10
+ File.expand_path('..', File.dirname(__FILE__))
11
+ end
12
+
13
+ class InvalidConfigurationParameterError < ArgumentError; end
14
+
15
+ module Configuration
16
+ DEFAULTS = {
17
+ :api_key => ENV['FREESOUND_KEY'],
18
+ :base_url => 'http://www.freesound.org/api',
19
+ :sounds_url => 'http://www.freesound.org/api/sounds'
20
+ }
21
+
22
+ DEFAULTS.each_key do |key|
23
+ eval <<-EOS
24
+ def self.#{key}
25
+ @@#{key} ||= DEFAULTS[:#{key}]
26
+ end
27
+
28
+ def self.#{key}=(val)
29
+ @@#{key} = val
30
+ end
31
+ EOS
32
+ end
33
+
34
+ def self.method_missing(name, *args)
35
+ raise(InvalidConfigurationParameterError, "#{name} is not a recognized configuration parameter")
36
+ end
37
+ end # module Configuration
38
+
39
+ def self.configure(params={})
40
+ params.each do |key, value|
41
+ Configuration.send("#{key}=", value)
42
+ end
43
+
44
+ yield Configuration if block_given?
45
+ end
46
+
47
+ def self.config
48
+ Configuration
49
+ end
50
+ end # module Freesound
51
+
52
+ require 'freesound/version'
53
+ require 'freesound/client'
54
+ require 'freesound/request'
55
+ require 'freesound/uri_compiler'
56
+ require 'freesound/response'
57
+ require 'freesound/response_parser'
58
+ require 'freesound/sound'
@@ -0,0 +1,27 @@
1
+ module Freesound
2
+ class InvalidApiKeyError < ArgumentError; end
3
+
4
+ class Client
5
+ attr_reader :api_key, :requests, :responses
6
+
7
+ def initialize(api_key, options={})
8
+ @api_key = api_key
9
+ @requests = []
10
+ @responses = []
11
+ end
12
+
13
+ def get_sound(id)
14
+ request = Request.new(:sound_id => id)
15
+ response = request.get!
16
+ @requests << request
17
+ @responses << response
18
+ response.sounds.first
19
+ end
20
+
21
+ def search_sounds(query, options={})
22
+ request = Request.new(:search => {:q => query})
23
+ response = request.get!
24
+ response.sounds
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module Freesound
2
+ class InvalidRequestFormatError < ArgumentError; end
3
+
4
+ class Request
5
+ attr_reader :uri, :params, :response, :format
6
+
7
+ def initialize(params={})
8
+ self.format = params[:format] || :json
9
+ @params = params
10
+ @response = nil
11
+ end
12
+
13
+ def format=(format)
14
+ raise(InvalidRequestFormatError, "#{format} is not a valid request format") unless [:json, :xml, :yaml, :yml].include?(format.to_sym)
15
+ @format = format.to_sym
16
+ end
17
+
18
+ def uri
19
+ @uri ||= URICompiler.new(@params.dup.merge({:format => @format})).uri
20
+ end
21
+
22
+ def get!
23
+ response_body = Net::HTTP.get_response(self.uri).body
24
+ @response ||= Response.new(response_body, @format)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module Freesound
2
+ class Response
3
+ attr_reader :content, :parser
4
+
5
+ def initialize(raw, format=:json)
6
+ @content = raw
7
+ @format = format
8
+ @parser = ResponseParser.new(format)
9
+ end
10
+
11
+ def data
12
+ @data ||= @parser.parse(@content)
13
+ end
14
+
15
+ def num_results
16
+ self.data[:num_results] || 1
17
+ end
18
+
19
+ def sounds
20
+ @sounds ||= if num_results == 1
21
+ [ Sound.new(*self.data.values) ]
22
+ else
23
+ self.data[:sounds].map { |data| Sound.new(data) }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,43 @@
1
+ module Freesound
2
+ class ResponseParser
3
+ attr_reader :format
4
+
5
+ def initialize(format)
6
+ @format = format
7
+ end
8
+
9
+ def parse(raw)
10
+ case @format
11
+ when :xml
12
+ parse_xml(raw)
13
+ when :yaml, :yml
14
+ parse_yaml(raw)
15
+ else
16
+ parse_json(raw)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def parse_json(raw)
23
+ ::Crack::JSON.parse(raw).underscore_keys.symbolize_keys
24
+ end
25
+
26
+ # xml gets parsed slightly differently than json and yaml.
27
+ # the result needs to convert single element arrays to strings,
28
+ # convert strings like "2" to their corresponding number object i.e. 2
29
+ # and remove the nesting of the :tags key under "resource"
30
+ def parse_xml(raw)
31
+ result = ::Crack::XML.parse(raw)["response"].underscore_keys
32
+ .symbolize_keys
33
+ .flatten_single_element_array_values
34
+ .numberize_values
35
+ result[:tags] = result[:tags]["resource"]
36
+ result
37
+ end
38
+
39
+ def parse_yaml(raw)
40
+ ::YAML::load(raw).underscore_keys.symbolize_keys
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ module Freesound
2
+ Sound = Struct.new(
3
+ :similarity, :num_ratings, :duration, :samplerate, :preview_hq_ogg,
4
+ :id, :preview_lq_ogg, :bitdepth, :num_comments, :filesize,
5
+ :preview_hq_mp3, :type, :analysis_stats, :description, :tags,
6
+ :serve, :spectral_m, :spectral_l, :user, :bitrate, :num_downloads,
7
+ :analysis_frames, :channels, :license, :created, :url, :ref,:avg_rating,
8
+ :preview_lq_mp3, :original_filename, :waveform_l, :waveform_m, :pack
9
+ )
10
+ end
@@ -0,0 +1,32 @@
1
+ module Freesound
2
+ class Freesound::URICompiler
3
+ attr_reader :uri
4
+
5
+ def initialize(params)
6
+ search_params = params.delete(:search)
7
+ sound_id = params.delete(:sound_id)
8
+ format = params.delete(:format)
9
+ @uri = URI.parse(compile_uri_string(search_params, sound_id, format))
10
+ end
11
+
12
+ def compile_uri_string(search_params, sound_id, format)
13
+ format_string = format ? "&format=#{format}" : ""
14
+
15
+ if search_params
16
+ search_uri(search_params, format_string)
17
+ elsif sound_id
18
+ sound_id_uri(sound_id, format_string)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def search_uri(search_params, format_string)
25
+ "#{Freesound.config.sounds_url}/search/?api_key=#{Freesound.config.api_key}#{format_string}&#{search_params.to_uri}"
26
+ end
27
+
28
+ def sound_id_uri(id, format_string)
29
+ "#{Freesound.config.sounds_url}/#{id}/?api_key=#{Freesound.config.api_key}#{format_string}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ module Freesound
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Hash do
4
+ describe '#symbolize_keys' do
5
+ it 'symbolizes keys' do
6
+ {"one" => 1, "two" => 2}.symbolize_keys.should == {:one => 1, :two => 2}
7
+ end
8
+ end
9
+
10
+ describe '#flatten_single_element_array_values' do
11
+ it 'converts values that are single element arrays into just the first element of that array' do
12
+ {"one" => [1], "two_and_three" => [2, 3], "four" => 4}
13
+ .flatten_single_element_array_values.should == {"one" => 1, "two_and_three" => [2, 3], "four" => 4}
14
+ end
15
+ end
16
+
17
+ describe '#to_uri' do
18
+ it 'converts hash to a uri string' do
19
+ {"one" => 1, :api_key => "1234"}.to_uri.should == "one=1&api_key=1234"
20
+ end
21
+ end
22
+
23
+ describe '#numberize_values' do
24
+ it 'turns all numerical string values to ints or floats' do
25
+ {:one => "1", :one_point_two => "1.2", :negative_three => "-3", :something => "anything"}.numberize_values.should ==
26
+ {:one => 1, :one_point_two => 1.2, :negative_three => -3, :something => "anything"}
27
+ end
28
+ end
29
+
30
+ describe '#underscore_keys' do
31
+ it 'underscores keys' do
32
+ {"one-two" => 12}.underscore_keys.should == {"one_two" => 12}
33
+ end
34
+ end
35
+ end
36
+
37
+ describe String do
38
+ describe '#numberize' do
39
+ it 'converts to an integer' do
40
+ '123'.numberize.should == 123
41
+ end
42
+
43
+ it 'converts to a float' do
44
+ '123.456'.numberize.should == 123.456
45
+ end
46
+
47
+ it 'returns nil for non-numerical strings' do
48
+ 'abc123'.numberize.should be_nil
49
+ end
50
+ end
51
+
52
+ describe '#numberizeable?' do
53
+ it 'returns true' do
54
+ %w{ 123 -2 1.23 -1.56 .900 23. 023 }.each { |str| str.should be_numberizeable }
55
+ end
56
+
57
+ it 'returns false' do
58
+ %w{ 1.2.3 12a3 alex 1-23 --345 ..45 98..}.each { |str| str.should_not be_numberizeable }
59
+ end
60
+ end
61
+
62
+ describe '#underscore' do
63
+ it 'underscores -s' do
64
+ 'one-two'.underscore.should == 'one_two'
65
+ end
66
+
67
+ it 'underscores whitespace' do
68
+ 'one two'.underscore.should == 'one_two'
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Client do
4
+ it 'has an api key' do
5
+ Client.new('123abc').api_key.should == '123abc'
6
+ end
7
+
8
+ context 'with valid api key' do
9
+ subject { Client.new(Freesound.config.api_key) }
10
+
11
+ before do
12
+ json = File.read("#{Freesound.root_dir}/data/sample.json")
13
+ path = "http://www.freesound.org/api/sounds/10/?api_key=#{Freesound.config.api_key}&format=json"
14
+
15
+ stub_request(:get, path).to_return(:body => json)
16
+ end
17
+
18
+ describe '#get_sound' do
19
+ it 'returns a Sound' do
20
+ subject.get_sound(10).should be_a(Sound)
21
+ end
22
+
23
+ it 'returns a Response corresponding to the given id' do
24
+ subject.get_sound(10).id.should == 10
25
+ end
26
+
27
+ it 'adds to @requests' do
28
+ expect { subject.get_sound(10) }.to change(subject.requests, :size).by(1)
29
+ end
30
+
31
+ it 'adds to @responses' do
32
+ expect { subject.get_sound(10) }.to change(subject.responses, :size).by(1)
33
+ end
34
+ end
35
+
36
+ describe '#search_sounds' do
37
+ before do
38
+ json = File.read("#{Freesound.root_dir}/data/sample_query.json")
39
+ path = "http://www.freesound.org/api/sounds/search/?api_key=#{Freesound.config.api_key}&format=json&q=badass"
40
+ stub_request(:get, path).to_return(:body => json)
41
+ end
42
+
43
+ it 'returns a response' do
44
+ subject.search_sounds("badass").should be_a(Array)
45
+ subject.search_sounds("badass").first.should be_a(Sound)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Request do
4
+ subject { Request.new({:sound_id => 10}) }
5
+
6
+ it 'initializes with a params hash' do
7
+ subject.params.should == {:sound_id => 10}
8
+ end
9
+
10
+ it 'fails with invalid format' do
11
+ expect { Request.new({:format => :pdf}) }.to raise_error(InvalidRequestFormatError)
12
+ end
13
+
14
+ describe '#get!' do
15
+ before do
16
+ json = File.read("#{Freesound.root_dir}/data/sample.json")
17
+ path = "http://www.freesound.org/api/sounds/10/?api_key=#{Freesound.config.api_key}&format=json"
18
+
19
+ stub_request(:get, path).to_return(:body => json)
20
+ end
21
+
22
+ it 'returns a Response' do
23
+ subject.get!.should be_a(Response)
24
+ end
25
+ end
26
+ end