nestling 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -17,3 +17,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
17
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
18
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  THE SOFTWARE.
20
+
data/README.md CHANGED
@@ -75,9 +75,14 @@ Additional information passed by EchoNest for collections (such as `results`,
75
75
  too:
76
76
 
77
77
  blogs.each do |blog|
78
- # Some smart code
78
+ puts blog.name
79
79
  end
80
80
 
81
+ Nestling will also convert timestamps to Ruby DateTime objects for you:
82
+
83
+ nestling.artist("Radiohead").blogs[0].date_found
84
+ # => #<DateTime: 2011-09-09T20:49:16+00:00 (53045590339/21600,0/1,2299161)>
85
+
81
86
  ## WHAT'S MISSING AT THE MOMENT?
82
87
 
83
88
  - Catalog API Methods
data/Rakefile CHANGED
@@ -6,3 +6,4 @@ Rake::TestTask.new do |t|
6
6
  end
7
7
 
8
8
  task :default => :test
9
+
@@ -5,7 +5,6 @@ module Nestling
5
5
  METHOD_PREFIX = "artist/"
6
6
 
7
7
  METHODS = {
8
- :audio => { :collection => true },
9
8
  :biographies => { :collection => true },
10
9
  :blogs => { :collection => true },
11
10
  :familiarity => { :collection => false, :key => "artist" },
@@ -27,6 +26,8 @@ module Nestling
27
26
  :video => { :collection => true }
28
27
  }
29
28
 
29
+ define_api_methods METHODS
30
+
30
31
  def initialize(name, client)
31
32
  name.kind_of?(::Hash) ? @id = name[:id] : @name = name
32
33
  super(client)
data/lib/nestling/base.rb CHANGED
@@ -5,43 +5,60 @@ module Nestling
5
5
  METHOD_PREFIX = ""
6
6
  METHODS = {}
7
7
 
8
- def initialize(client)
9
- @client = client
10
- end
11
-
12
- def method_missing(meth, *args, &block)
13
- unless method = self.class::METHODS[meth]
14
- return super(meth, *args, &block)
8
+ class << self
9
+ def define_api_methods(methods)
10
+ methods.each do |key, definition|
11
+ if definition[:collection]
12
+ define_api_method_returning_collection(key, definition)
13
+ else
14
+ define_api_method(key, definition)
15
+ end
16
+ end
15
17
  end
16
18
 
17
- opts = args[0] || {}
18
- key = meth.to_s
19
- query = self.class::METHOD_PREFIX + key
19
+ private
20
20
 
21
- resp = get(query, options(opts))["response"]
22
- payload = resp[method[:key] || key]
21
+ def define_api_method_returning_collection(key, definition)
22
+ define_method key do |*args|
23
+ resp = get_request(key, args[0])
24
+ hashes = convert_hashes(resp[definition[:key] || key.to_s])
25
+ Collection.new(resp).push(hashes).flatten!
26
+ end
27
+ end
23
28
 
24
- if method[:collection]
25
- Collection.new(resp["total"], resp["start"],
26
- resp["session_id"]).tap do |c|
27
- payload.each { |h| c << convert(h) }
29
+ def define_api_method(key, definition)
30
+ define_method key do |*args|
31
+ resp = get_request(key, args[0])
32
+ convert_hash(resp[definition[:key] || key.to_s])
28
33
  end
29
- else
30
- convert(payload)
31
34
  end
32
35
  end
33
36
 
37
+ def initialize(client)
38
+ @client = client
39
+ end
40
+
34
41
  private
35
42
 
36
- def convert(hash)
37
- hash = Hash.new(hash)
43
+ def get_request(key, opts)
44
+ opts ||= {}
45
+ query = self.class::METHOD_PREFIX + key.to_s
46
+ get(query, options(opts))["response"]
47
+ end
48
+
49
+ def convert_hashes(hashes)
50
+ hashes.map { |hash| convert_hash(hash) }
51
+ end
52
+
53
+ def convert_hash(hash)
54
+ hash = Nestling::Hash.new(hash).symbolize_keys!
38
55
 
39
56
  hash.each do |key, value|
40
57
  if value.kind_of?(String) &&
41
58
  value.match(/\d{4}(-\d\d){2}T\d{2}(:\d\d){2}/)
42
59
  hash[key] = DateTime.parse(value)
43
60
  elsif value.kind_of?(::Hash)
44
- hash[key] = convert(value)
61
+ hash[key] = convert_hash(value)
45
62
  end
46
63
  end
47
64
  end
@@ -38,7 +38,7 @@ module Nestling
38
38
  hash = JSON.parse(data)
39
39
 
40
40
  if (code = hash["response"]["status"]["code"].to_i) != 0
41
- raise Nestling::ERRNO[code], hash["response"]["status"]["message"]
41
+ raise ERRNO[code], hash["response"]["status"]["message"]
42
42
  end
43
43
 
44
44
  hash
@@ -1,11 +1,13 @@
1
1
  module Nestling
2
2
  class Collection < Array
3
- attr_accessor :results, :start, :session_id
3
+ attr_accessor :results, :start, :session_id, :type
4
4
 
5
- def initialize(results = nil, start = nil, session_id = nil, *args)
6
- @results = results
7
- @start = start
8
- @session_id = session_id
5
+ def initialize(options = {}, *args)
6
+ options = Nestling::Hash.new(options).symbolize_keys!
7
+ @results = options[:results] || options[:total]
8
+ @start = options[:start]
9
+ @session_id = options[:session_id]
10
+ @type = options[:type]
9
11
  super *args
10
12
  end
11
13
  end
data/lib/nestling/hash.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Nestling
2
2
  class Hash < ::Hash
3
3
  def initialize(hash = nil, *args)
4
- self.merge!(hash).symbolize_keys! if hash
4
+ self.merge!(hash) if hash
5
5
  super *args
6
6
  end
7
7
 
@@ -9,8 +9,6 @@ module Nestling
9
9
  (val = self[meth]) ? val : super(meth, *args, &block)
10
10
  end
11
11
 
12
- undef length # Property used by EchoNest API
13
-
14
12
  # Adapted from ActiveSupport (part of Ruby on Rails)
15
13
  # Released under the MIT license
16
14
  def symbolize_keys
@@ -7,6 +7,8 @@ module Nestling
7
7
  :dynamic => { :collection => true, :key => "songs" },
8
8
  :session_info => { :collection => false, :key => "terms" }
9
9
  }
10
+
11
+ define_api_methods METHODS
10
12
  end
11
13
  end
12
14
 
data/lib/nestling/song.rb CHANGED
@@ -7,6 +7,8 @@ module Nestling
7
7
  :profile => { :collection => true, :key => "songs" },
8
8
  :identify => { :collection => true, :key => "songs" }
9
9
  }
10
+
11
+ define_api_methods METHODS
10
12
  end
11
13
  end
12
14
 
@@ -5,6 +5,8 @@ module Nestling
5
5
  METHODS = {
6
6
  :profile => { :collection => false, :key => "track" },
7
7
  }
8
+
9
+ define_api_methods METHODS
8
10
  end
9
11
  end
10
12
 
@@ -1,8 +1,8 @@
1
1
  module Nestling
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 0
5
- PATCH = 1
4
+ MINOR = 1
5
+ PATCH = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
data/nestling.gemspec CHANGED
@@ -14,10 +14,10 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.files = `git ls-files`.split("\n")
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_dependency "json", "~> 1.5.3"
21
- s.add_development_dependency("mocha", "~> 0.9.12")
20
+ s.add_dependency "json", "~> 1.5.4"
21
+ s.add_development_dependency "mocha", "~> 0.9.12"
22
22
  end
23
23
 
data/test/test_artist.rb CHANGED
@@ -16,12 +16,13 @@ class TestArtist < MiniTest::Unit::TestCase
16
16
  "start": 11,
17
17
  "total": 1393,
18
18
  "session_id": 123,
19
- "audio": [{
19
+ "blogs": [{
20
20
  "title": "foo",
21
21
  "date": "2011-08-16T01:15:01"
22
22
  }]
23
23
  }}
24
24
  EOS
25
+ @artist = Client.new('foo').artist('bar')
25
26
  end
26
27
 
27
28
  def test_superclass
@@ -33,7 +34,7 @@ class TestArtist < MiniTest::Unit::TestCase
33
34
  end
34
35
 
35
36
  def test_number_of_methods
36
- assert_equal 20, METHODS.length
37
+ assert_equal 19, METHODS.length
37
38
  end
38
39
 
39
40
  def test_artist_with_id
@@ -49,113 +50,127 @@ class TestArtist < MiniTest::Unit::TestCase
49
50
  end
50
51
 
51
52
  def test_passes_name
52
- expect_request @collection_response, 'artist/audio', { :name => 'bar' }
53
- Client.new('foo').artist('bar').audio
53
+ expect_request @collection_response, 'artist/blogs', { :name => 'bar' }
54
+ Client.new('foo').artist('bar').blogs
54
55
  end
55
56
 
56
57
  def test_passes_id
57
- expect_request @collection_response, 'artist/audio', { :id => 'baz' }
58
- Client.new('foo').artist(:id => 'baz').audio
59
- end
60
-
61
- def test_audio
62
- assert METHODS[:audio][:collection]
63
- assert_nil METHODS[:audio][:key]
58
+ expect_request @collection_response, 'artist/blogs', { :id => 'baz' }
59
+ Client.new('foo').artist(:id => 'baz').blogs
64
60
  end
65
61
 
66
62
  def test_biographies
67
63
  assert METHODS[:biographies][:collection]
68
64
  assert_nil METHODS[:biographies][:key]
65
+ assert @artist.respond_to?(:biographies)
69
66
  end
70
67
 
71
68
  def test_blogs
72
69
  assert METHODS[:blogs][:collection]
73
70
  assert_nil METHODS[:blogs][:key]
71
+ assert @artist.respond_to?(:blogs)
74
72
  end
75
73
 
76
74
  def test_familiarity
77
75
  refute METHODS[:familiarity][:collection]
78
76
  assert_equal "artist", METHODS[:familiarity][:key]
77
+ assert @artist.respond_to?(:familiarity)
79
78
  end
80
79
 
81
80
  def test_hotttnesss
82
81
  refute METHODS[:hotttnesss][:collection]
83
82
  assert_equal "artist", METHODS[:hotttnesss][:key]
83
+ assert @artist.respond_to?(:hotttnesss)
84
84
  end
85
85
 
86
86
  def test_images
87
87
  assert METHODS[:images][:collection]
88
88
  assert_nil METHODS[:images][:key]
89
+ assert @artist.respond_to?(:images)
89
90
  end
90
91
 
91
92
  def test_list_terms
92
93
  assert METHODS[:list_terms][:collection]
93
94
  assert_nil METHODS[:list_terms][:key]
95
+ assert @artist.respond_to?(:list_terms)
94
96
  end
95
97
 
96
98
  def test_news
97
99
  assert METHODS[:news][:collection]
98
100
  assert_nil METHODS[:news][:key]
101
+ assert @artist.respond_to?(:news)
99
102
  end
100
103
 
101
104
  def test_profile
102
105
  refute METHODS[:profile][:collection]
103
106
  assert_equal "artist", METHODS[:profile][:key]
107
+ assert @artist.respond_to?(:profile)
104
108
  end
105
109
 
106
110
  def test_reviews
107
111
  assert METHODS[:reviews][:collection]
108
112
  assert_nil METHODS[:reviews][:key]
113
+ assert @artist.respond_to?(:reviews)
109
114
  end
110
115
 
111
116
  def test_search
112
117
  assert METHODS[:search][:collection]
113
118
  assert_equal "artists", METHODS[:search][:key]
119
+ assert @artist.respond_to?(:search)
114
120
  end
115
121
 
116
122
  def test_extract
117
123
  assert METHODS[:extract][:collection]
118
124
  assert_equal "artist", METHODS[:extract][:key]
125
+ assert @artist.respond_to?(:extract)
119
126
  end
120
127
 
121
128
  def test_songs
122
129
  assert METHODS[:songs][:collection]
123
130
  assert_nil METHODS[:songs][:key]
131
+ assert @artist.respond_to?(:songs)
124
132
  end
125
133
 
126
134
  def test_similar
127
135
  assert METHODS[:similar][:collection]
128
136
  assert_equal "artists", METHODS[:similar][:key]
137
+ assert @artist.respond_to?(:similar)
129
138
  end
130
139
 
131
140
  def test_suggest
132
141
  assert METHODS[:suggest][:collection]
133
142
  assert_equal "artists", METHODS[:suggest][:key]
143
+ assert @artist.respond_to?(:suggest)
134
144
  end
135
145
 
136
146
  def test_terms
137
147
  assert METHODS[:terms][:collection]
138
148
  assert_nil METHODS[:terms][:key]
149
+ assert @artist.respond_to?(:terms)
139
150
  end
140
151
 
141
152
  def test_top_hottt
142
153
  assert METHODS[:top_hottt][:collection]
143
154
  assert_equal "artists", METHODS[:top_hottt][:key]
155
+ assert @artist.respond_to?(:top_hottt)
144
156
  end
145
157
 
146
158
  def test_top_terms
147
159
  assert METHODS[:top_terms][:collection]
148
160
  assert_equal "terms", METHODS[:top_terms][:key]
161
+ assert @artist.respond_to?(:top_terms)
149
162
  end
150
163
 
151
164
  def test_urls
152
165
  refute METHODS[:urls][:collection]
153
166
  assert_nil METHODS[:urls][:key]
167
+ assert @artist.respond_to?(:urls)
154
168
  end
155
169
 
156
170
  def test_video
157
171
  assert METHODS[:video][:collection]
158
172
  assert_nil METHODS[:video][:key]
173
+ assert @artist.respond_to?(:video)
159
174
  end
160
175
  end
161
176
 
data/test/test_base.rb CHANGED
@@ -2,11 +2,14 @@ require File.join(File.dirname(__FILE__), 'helper')
2
2
 
3
3
  class BaseTest < Nestling::Base
4
4
  METHOD_PREFIX = 'test/'
5
+
5
6
  METHODS = {
6
7
  :omg => { :collection => true, :key => "foo" },
7
8
  :bar => { :collection => false, :key => "baz" },
8
9
  :zomg => { :collection => false }
9
10
  }
11
+
12
+ define_api_methods METHODS
10
13
  end
11
14
 
12
15
  class TestBase < MiniTest::Unit::TestCase
@@ -73,6 +76,16 @@ class TestBase < MiniTest::Unit::TestCase
73
76
  BaseTest.new(@client).omg :foo => 'bar'
74
77
  end
75
78
 
79
+ def test_define_api_methods
80
+ assert Base.respond_to?(:define_api_methods)
81
+ end
82
+
83
+ def test_define_api_methods_defines_instance_methods
84
+ BaseTest::METHODS.each do |method|
85
+ assert BaseTest.method_defined?(:method)
86
+ end
87
+ end
88
+
76
89
  def test_converts_hash
77
90
  stub_http_get @hash_response
78
91
  hash = BaseTest.new(@client).bar
@@ -3,6 +3,30 @@ require File.join(File.dirname(__FILE__), 'helper')
3
3
  class TestErrors < MiniTest::Unit::TestCase
4
4
  include Nestling
5
5
 
6
+ def setup
7
+ @sym_options = {
8
+ :results => 10,
9
+ :start => 2,
10
+ :session_id => 123,
11
+ :type => "mood"
12
+ }
13
+
14
+ @str_options = {
15
+ "results" => 10,
16
+ "start" => 2,
17
+ "session_id" => 123,
18
+ "type" => "mood"
19
+ }
20
+
21
+ @str_options_with_total = {
22
+ "total" => 23
23
+ }
24
+
25
+ @sym_options_with_total = {
26
+ :total => 23
27
+ }
28
+ end
29
+
6
30
  def test_superclass
7
31
  assert_equal Collection.superclass, Array
8
32
  end
@@ -15,15 +39,25 @@ class TestErrors < MiniTest::Unit::TestCase
15
39
  end
16
40
 
17
41
  def test_collection_assigns_results
18
- assert_equal 10, Collection.new(10).results
42
+ assert_equal 10, Collection.new(@str_options).results
43
+ assert_equal 10, Collection.new(@sym_options).results
44
+ assert_equal 23, Collection.new(@str_options_with_total).results
45
+ assert_equal 23, Collection.new(@sym_options_with_total).results
19
46
  end
20
47
 
21
- def test_collection_assigns_results
22
- assert_equal 2, Collection.new(10, 2).start
48
+ def test_collection_assigns_start
49
+ assert_equal 2, Collection.new(@str_options).start
50
+ assert_equal 2, Collection.new(@sym_options).start
23
51
  end
24
52
 
25
53
  def test_collection_assigns_session_id
26
- assert_equal 123, Collection.new(10, 2, 123).session_id
54
+ assert_equal 123, Collection.new(@str_options).session_id
55
+ assert_equal 123, Collection.new(@sym_options).session_id
56
+ end
57
+
58
+ def test_collection_assigns_type
59
+ assert_equal "mood", Collection.new(@str_options).type
60
+ assert_equal "mood", Collection.new(@sym_options).type
27
61
  end
28
62
  end
29
63
 
data/test/test_hash.rb CHANGED
@@ -17,13 +17,12 @@ class TestHash < MiniTest::Unit::TestCase
17
17
  h = Nestling::Hash.new
18
18
  assert_respond_to h, :symbolize_keys
19
19
  assert_respond_to h, :symbolize_keys!
20
- refute_respond_to Nestling::Hash.new, :length
21
20
  end
22
21
 
23
22
  def test_initialize
24
23
  h = Nestling::Hash.new({ :foo => "bar", "bar" => :baz})
25
24
  assert_equal "bar", h[:foo]
26
- assert_equal :baz, h[:bar]
25
+ assert_equal :baz, h["bar"]
27
26
  end
28
27
 
29
28
  def test_symbolize_keys
@@ -5,6 +5,10 @@ class TestPlaylist < MiniTest::Unit::TestCase
5
5
 
6
6
  METHODS = Playlist::METHODS
7
7
 
8
+ def setup
9
+ @playlist = Nestling.new('foo').playlist
10
+ end
11
+
8
12
  def test_superclass
9
13
  assert_equal Base, Playlist.superclass
10
14
  end
@@ -20,17 +24,19 @@ class TestPlaylist < MiniTest::Unit::TestCase
20
24
  def test_static
21
25
  assert METHODS[:static][:collection]
22
26
  assert_equal "songs", METHODS[:static][:key]
27
+ assert @playlist.respond_to?(:static)
23
28
  end
24
29
 
25
30
  def test_dynamic
26
31
  assert METHODS[:dynamic][:collection]
27
32
  assert_equal "songs", METHODS[:dynamic][:key]
33
+ assert @playlist.respond_to?(:dynamic)
28
34
  end
29
35
 
30
36
  def test_session_info
31
37
  refute METHODS[:session_info][:collection]
32
38
  assert_equal "terms", METHODS[:session_info][:key]
39
+ assert @playlist.respond_to?(:session_info)
33
40
  end
34
41
  end
35
42
 
36
-
data/test/test_song.rb CHANGED
@@ -5,6 +5,10 @@ class TestSong < MiniTest::Unit::TestCase
5
5
 
6
6
  METHODS = Song::METHODS
7
7
 
8
+ def setup
9
+ @song = Nestling.new('foo').song
10
+ end
11
+
8
12
  def test_superclass
9
13
  assert_equal Base, Song.superclass
10
14
  end
@@ -20,16 +24,19 @@ class TestSong < MiniTest::Unit::TestCase
20
24
  def test_search
21
25
  assert METHODS[:search][:collection]
22
26
  assert_equal "songs", METHODS[:search][:key]
27
+ assert @song.respond_to?(:search)
23
28
  end
24
29
 
25
30
  def test_profile
26
31
  assert METHODS[:profile][:collection]
27
32
  assert_equal "songs", METHODS[:profile][:key]
33
+ assert @song.respond_to?(:profile)
28
34
  end
29
35
 
30
36
  def test_identify
31
37
  assert METHODS[:identify][:collection]
32
38
  assert_equal "songs", METHODS[:identify][:key]
39
+ assert @song.respond_to?(:identify)
33
40
  end
34
41
  end
35
42
 
data/test/test_track.rb CHANGED
@@ -5,6 +5,10 @@ class TestTrack < MiniTest::Unit::TestCase
5
5
 
6
6
  METHODS = Track::METHODS
7
7
 
8
+ def setup
9
+ @track = Nestling.new('foo').track
10
+ end
11
+
8
12
  def test_superclass
9
13
  assert_equal Base, Track.superclass
10
14
  end
@@ -20,7 +24,7 @@ class TestTrack < MiniTest::Unit::TestCase
20
24
  def test_profile
21
25
  refute METHODS[:profile][:collection]
22
26
  assert_equal "track", METHODS[:profile][:key]
27
+ assert @track.respond_to?(:profile)
23
28
  end
24
29
  end
25
30
 
26
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nestling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-09 00:00:00.000000000Z
12
+ date: 2011-09-23 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70312819046000 !ruby/object:Gem::Requirement
16
+ requirement: &70365143049080 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 1.5.3
21
+ version: 1.5.4
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70312819046000
24
+ version_requirements: *70365143049080
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mocha
27
- requirement: &70312819045500 !ruby/object:Gem::Requirement
27
+ requirement: &70365143048260 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 0.9.12
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70312819045500
35
+ version_requirements: *70365143048260
36
36
  description: Ruby wrapper for the EchoNest API
37
37
  email:
38
38
  - tob@tobiassvensson.co.uk
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  version: '0'
89
89
  requirements: []
90
90
  rubyforge_project:
91
- rubygems_version: 1.8.6
91
+ rubygems_version: 1.8.10
92
92
  signing_key:
93
93
  specification_version: 3
94
94
  summary: Ruby wrapper for the EchoNest API