rockstar-custom 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.travis.yml +6 -0
  2. data/Gemfile +11 -0
  3. data/Gemfile.lock +22 -0
  4. data/History.txt +6 -0
  5. data/MIT-LICENSE +19 -0
  6. data/Manifest +72 -0
  7. data/README.md +135 -0
  8. data/Rakefile +34 -0
  9. data/VERSION +1 -0
  10. data/examples/.gitignore +1 -0
  11. data/examples/album.rb +16 -0
  12. data/examples/artist.rb +23 -0
  13. data/examples/geo.rb +9 -0
  14. data/examples/lastfm.yml_example +3 -0
  15. data/examples/scrobble.rb +45 -0
  16. data/examples/tag.rb +20 -0
  17. data/examples/track.rb +14 -0
  18. data/examples/user.rb +18 -0
  19. data/lib/rockstar.rb +50 -0
  20. data/lib/rockstar/album.rb +109 -0
  21. data/lib/rockstar/artist.rb +182 -0
  22. data/lib/rockstar/auth.rb +21 -0
  23. data/lib/rockstar/base.rb +48 -0
  24. data/lib/rockstar/chart.rb +31 -0
  25. data/lib/rockstar/event.rb +73 -0
  26. data/lib/rockstar/geo.rb +22 -0
  27. data/lib/rockstar/metro.rb +26 -0
  28. data/lib/rockstar/playing.rb +50 -0
  29. data/lib/rockstar/rest.rb +66 -0
  30. data/lib/rockstar/scrobble.rb +68 -0
  31. data/lib/rockstar/session.rb +19 -0
  32. data/lib/rockstar/simpleauth.rb +62 -0
  33. data/lib/rockstar/tag.rb +100 -0
  34. data/lib/rockstar/tokenauth.rb +84 -0
  35. data/lib/rockstar/track.rb +260 -0
  36. data/lib/rockstar/user.rb +200 -0
  37. data/lib/rockstar/venue.rb +59 -0
  38. data/lib/rockstar/version.rb +3 -0
  39. data/rockstar.gemspec +174 -0
  40. data/test/fixtures/xml/album/getinfo_album_Radio_Retalation_artist_Thievery_Corporation.xml +21 -0
  41. data/test/fixtures/xml/album/getinfo_album_Some_Hearts_artist_Carrie_Underwood.xml +63 -0
  42. data/test/fixtures/xml/artist/getevents_artist_Metallica.xml +1064 -0
  43. data/test/fixtures/xml/artist/getimages_artist_Metallica_page_2.xml +1074 -0
  44. data/test/fixtures/xml/artist/getinfo_artist_Metallica.xml +115 -0
  45. data/test/fixtures/xml/artist/getsimilar_artist_Metallica.xml +1203 -0
  46. data/test/fixtures/xml/artist/gettopalbums_artist_Metallica.xml +704 -0
  47. data/test/fixtures/xml/artist/gettopfans_artist_Metallica.xml +504 -0
  48. data/test/fixtures/xml/artist/gettoptags_artist_Metallica.xml +403 -0
  49. data/test/fixtures/xml/artist/gettoptracks_artist_Metallica.xml +800 -0
  50. data/test/fixtures/xml/geo/getevents_location_london.xml +531 -0
  51. data/test/fixtures/xml/geo/getmetros_country_germany.xml +44 -0
  52. data/test/fixtures/xml/tag/gettopalbums_tag_rock.xml +654 -0
  53. data/test/fixtures/xml/tag/gettopartists_tag_rock.xml +504 -0
  54. data/test/fixtures/xml/tag/gettoptags.xml +1253 -0
  55. data/test/fixtures/xml/tag/gettoptracks_tag_rock.xml +704 -0
  56. data/test/fixtures/xml/track/getinfo_artist_Carrie_Underwood_track_Before_He_Cheats.xml +55 -0
  57. data/test/fixtures/xml/track/gettopfans_artist_Carrie_Underwood_track_Before_He_Cheats.xml +504 -0
  58. data/test/fixtures/xml/track/gettoptags_artist_Carrie_Underwood_track_Before_He_Cheats.xml +403 -0
  59. data/test/fixtures/xml/track/love_artist_Carrie_Underwood_sk_tag_track_Before_He_Cheats.xml +2 -0
  60. data/test/fixtures/xml/track/updatenowplaying_artist_Carrie_Underwood_sk_tag_track_Before_He_Cheats.xml +10 -0
  61. data/test/fixtures/xml/user/getevents_sk_token_user_bodot.xml +513 -0
  62. data/test/fixtures/xml/user/getfriends_user_jnunemaker.xml +173 -0
  63. data/test/fixtures/xml/user/getinfo_user_jnunemaker.xml +22 -0
  64. data/test/fixtures/xml/user/getinfo_user_oaknd1.xml +22 -0
  65. data/test/fixtures/xml/user/getinfo_user_wharle.xml +22 -0
  66. data/test/fixtures/xml/user/getlovedtracks_user_jnunemaker.xml +775 -0
  67. data/test/fixtures/xml/user/getneighbours_user_jnunemaker.xml +503 -0
  68. data/test/fixtures/xml/user/getrecenttracks_user_jnunemaker.xml +133 -0
  69. data/test/fixtures/xml/user/getrecommendedartists_sk_token_user_jnunemaker.xml +553 -0
  70. data/test/fixtures/xml/user/gettopalbums_user_jnunemaker.xml +704 -0
  71. data/test/fixtures/xml/user/gettopartists_period_overall_user_jnunemaker.xml +554 -0
  72. data/test/fixtures/xml/user/gettoptags_user_jnunemaker.xml +63 -0
  73. data/test/fixtures/xml/user/gettoptracks_user_jnunemaker.xml +750 -0
  74. data/test/fixtures/xml/user/getweeklyalbumchart_from_1138536002_to_1139140802_user_jnunemaker.xml +143 -0
  75. data/test/fixtures/xml/user/getweeklyalbumchart_from__to__user_jnunemaker.xml +31 -0
  76. data/test/fixtures/xml/user/getweeklyartistchart_from_1138536002_to_1139140802_user_jnunemaker.xml +201 -0
  77. data/test/fixtures/xml/user/getweeklyartistchart_from__to__user_jnunemaker.xml +21 -0
  78. data/test/fixtures/xml/user/getweeklychartlist_user_jnunemaker.xml +232 -0
  79. data/test/fixtures/xml/user/getweeklytrackchart_from_1138536002_to_1139140802_user_jnunemaker.xml +883 -0
  80. data/test/fixtures/xml/user/getweeklytrackchart_from__to__user_jnunemaker.xml +423 -0
  81. data/test/fixtures/xml/venue/getevents_venue_8807850.xml +280 -0
  82. data/test/fixtures/xml/venue/search_country__limit__page__venue_country_DE_venue_cotton.xml +72 -0
  83. data/test/mocks/rest.rb +67 -0
  84. data/test/test_helper.rb +18 -0
  85. data/test/unit/test_album.rb +76 -0
  86. data/test/unit/test_artist.rb +102 -0
  87. data/test/unit/test_chart.rb +35 -0
  88. data/test/unit/test_geo.rb +25 -0
  89. data/test/unit/test_playing.rb +53 -0
  90. data/test/unit/test_scrobble.rb +69 -0
  91. data/test/unit/test_simpleauth.rb +45 -0
  92. data/test/unit/test_tag.rb +57 -0
  93. data/test/unit/test_tokenauth.rb +45 -0
  94. data/test/unit/test_track.rb +82 -0
  95. data/test/unit/test_user.rb +299 -0
  96. data/test/unit/test_venue.rb +20 -0
  97. metadata +269 -0
data/examples/track.rb ADDED
@@ -0,0 +1,14 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'rockstar'))
2
+ require 'pp'
3
+
4
+ # Please enter your API-Keys into lastfm.yml first.
5
+ # You can find them here : http://www.lastfm.de/api/account
6
+ Rockstar.lastfm = YAML.load_file(File.join(File.dirname(__FILE__), 'lastfm.yml'))
7
+
8
+ track = Rockstar::Track.new('Carrie Underwood', 'Before He Cheats')
9
+ puts 'Fans'
10
+ puts "=" * 4
11
+ track.fans.each { |u| puts "(#{u.weight}) #{u.username}" }
12
+
13
+ track = Rockstar::Track.new('U2 & Green Day', 'The Saints Are Coming')
14
+ pp track.tags
data/examples/user.rb ADDED
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'rockstar'))
2
+
3
+ # Please enter your API-Keys into lastfm.yml first.
4
+ # You can find them here : http://www.lastfm.de/api/account
5
+ Rockstar.lastfm = YAML.load_file(File.join(File.dirname(__FILE__), 'lastfm.yml'))
6
+
7
+ user = Rockstar::User.new('jnunemaker')
8
+
9
+ puts "#{user.username}'s Recent Tracks"
10
+ puts "=" * (user.username.length + 16)
11
+ user.recent_tracks.each { |t| puts t.name }
12
+
13
+ puts
14
+ puts
15
+
16
+ puts "#{user.username}'s Top Tracks"
17
+ puts "=" * (user.username.length + 13)
18
+ user.top_tracks.each { |t| puts "(#{t.playcount}) #{t.name}" }
data/lib/rockstar.rb ADDED
@@ -0,0 +1,50 @@
1
+ $: << File.expand_path(File.dirname(__FILE__))
2
+
3
+ require 'rubygems'
4
+ require 'cgi'
5
+ require 'hpricot'
6
+ require 'active_support'
7
+ require 'active_support/core_ext/object/blank'
8
+ require 'active_support/core_ext/string/inflections'
9
+ require 'time'
10
+ require 'yaml'
11
+
12
+ require 'rockstar/base'
13
+ require 'rockstar/version'
14
+
15
+ require 'rockstar/album'
16
+ require 'rockstar/artist'
17
+ require 'rockstar/chart'
18
+ require 'rockstar/event'
19
+ require 'rockstar/geo'
20
+ require 'rockstar/metro'
21
+ require 'rockstar/user'
22
+ require 'rockstar/tag'
23
+ require 'rockstar/track'
24
+ require 'rockstar/venue'
25
+
26
+ require 'rockstar/simpleauth'
27
+ require 'rockstar/auth'
28
+ require 'rockstar/session'
29
+ require 'rockstar/tokenauth'
30
+ require 'rockstar/scrobble'
31
+ require 'rockstar/playing'
32
+
33
+ require 'rockstar/rest'
34
+
35
+ module Rockstar
36
+ extend self
37
+
38
+ def lastfm=(args)
39
+ @api_key = args["api_key"]
40
+ @api_secret = args["api_secret"]
41
+ end
42
+
43
+ def lastfm_api_key
44
+ @api_key
45
+ end
46
+
47
+ def lastfm_api_secret
48
+ @api_secret
49
+ end
50
+ end
@@ -0,0 +1,109 @@
1
+ # Getting information about an album such as release date and the summary or description on it is very easy.
2
+ #
3
+ # album = Rockstar::Album.new('Carrie Underwood', 'Some Hearts', :include_info => true)
4
+ #
5
+ # puts "Album: #{album.name}"
6
+ # puts "Artist: #{album.artist}"
7
+ # puts "URL: #{album.url}"
8
+ # puts "Release Date: #{album.release_date.strftime('%m/%d/%Y')}"
9
+ #
10
+ # Would output:
11
+ #
12
+ # Album: Some Hearts
13
+ # Artist: Carrie Underwood
14
+ # URL: http://www.last.fm/music/Carrie+Underwood/Some+Hearts
15
+ # Release Date: 11/15/2005
16
+ #
17
+ module Rockstar
18
+ class Album < Base
19
+ attr_accessor :artist, :artist_mbid, :name, :mbid, :playcount, :rank, :url, :release_date
20
+ attr_accessor :image_large, :image_medium, :image_small, :summary, :content, :images
21
+
22
+ # needed on top albums for tag
23
+ attr_accessor :count, :streamable
24
+
25
+ # needed for weekly album charts
26
+ attr_accessor :chartposition
27
+
28
+ class << self
29
+ def find(artist, name, o={})
30
+ new(artist, name, o)
31
+ end
32
+
33
+ def new_from_xml(xml, doc=nil)
34
+ name = (xml).at(:name).inner_html if (xml).at(:name)
35
+ name = xml['name'] if name.nil? && xml['name']
36
+ name = xml.at(:title).inner_html if name.nil? && (xml).at(:title)
37
+ artist = (xml).at(:artist).at(:name).inner_html if (xml).at(:artist) && (xml).at(:artist).at(:name)
38
+ artist = (xml).at(:artist).inner_html if artist.nil? && (xml).at(:artist)
39
+ artist = doc.root['artist'] if artist.nil? && doc && doc.root['artist']
40
+
41
+ album = Album.new(artist, name)
42
+ album.load_info(xml)
43
+ album
44
+ end
45
+ end
46
+
47
+ def initialize(artist, name, o={})
48
+ raise ArgumentError, "Artist is required" if artist.blank?
49
+ raise ArgumentError, "Name is required" if name.blank?
50
+ @artist = artist
51
+ @name = name
52
+
53
+ options = {:include_info => false}.merge(o)
54
+ load_info if options[:include_info]
55
+ end
56
+
57
+ def load_info(xml=nil)
58
+ unless xml
59
+ doc = self.class.fetch_and_parse("album.getInfo", {:artist => @artist, :album =>@name})
60
+ xml = (doc / :album).first
61
+ end
62
+
63
+ return self if xml.nil?
64
+
65
+ self.artist_mbid = (xml).at(:artist)['mbid'] if (xml).at(:artist) && (xml).at(:artist)['mbid']
66
+ self.artist_mbid = (xml).at(:artist).at(:mbid).inner_html if artist_mbid.nil? && (xml).at(:artist) && (xml).at(:artist).at(:mbid)
67
+ self.mbid = (xml).at(:mbid).inner_html if (xml).at(:mbid)
68
+ self.playcount = (xml).at(:playcount).inner_html if (xml).at(:playcount)
69
+ self.rank = xml['rank'] if xml['rank']
70
+ self.rank = (xml).at(:rank).inner_html if (xml).at(:rank) if rank.nil?
71
+ self.url = Base.fix_url((xml).at(:url).inner_html) if (xml).at(:url)
72
+
73
+ self.summary = (xml).at(:summary).to_plain_text if (xml).at(:summary)
74
+ self.content = (xml).at(:content).to_plain_text if (xml).at(:content)
75
+
76
+ self.release_date = Base.parse_time((xml).at(:releasedate).inner_html.strip) if (xml).at(:releasedate)
77
+ self.chartposition = rank
78
+
79
+ self.images = {}
80
+ (xml/'image').each {|image|
81
+ self.images[image['size']] = image.inner_html if self.images[image['size']].nil?
82
+ }
83
+
84
+ self.image_large = images['large']
85
+ self.image_medium = images['medium']
86
+ self.image_small = images['small']
87
+
88
+ # needed on top albums for tag
89
+ self.count = xml['count'] if xml['count']
90
+ self.streamable = xml['streamable'] if xml['streamable']
91
+
92
+ self
93
+ end
94
+
95
+ def tracks
96
+ warn "[DEPRECATION] `tracks` is deprecated. The current api doesn't offer this function"
97
+ []
98
+ end
99
+
100
+ def image(which=:small)
101
+ which = which.to_s
102
+ raise ArgumentError unless ['small', 'medium', 'large', 'extralarge'].include?(which)
103
+ if (self.images.nil?)
104
+ load_info
105
+ end
106
+ self.images[which]
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,182 @@
1
+ # Below are examples of how to find an artists top tracks and similar artists.
2
+ #
3
+ # artist = Rockstar::Artist.new('Carrie Underwood')
4
+ #
5
+ # puts 'Top Tracks'
6
+ # puts "=" * 10
7
+ # artist.top_tracks.each { |t| puts "#{t.name}" }
8
+ #
9
+ # puts
10
+ #
11
+ # puts 'Similar Artists'
12
+ # puts "=" * 15
13
+ # artist.similar.each { |a| puts "(#{a.match}%) #{a.name}" }
14
+ #
15
+ # Would output something similar to:
16
+ #
17
+ # Top Tracks
18
+ # ==========
19
+ # (8797) Before He Cheats
20
+ # (3574) Don't Forget to Remember Me
21
+ # (3569) Wasted
22
+ # (3246) Some Hearts
23
+ # (3142) Jesus, Take the Wheel
24
+ # (2600) Starts With Goodbye
25
+ # (2511) Jesus Take The Wheel
26
+ # (2423) Inside Your Heaven
27
+ # (2328) Lessons Learned
28
+ # (2040) I Just Can't Live a Lie
29
+ # (1899) Whenever You Remember
30
+ # (1882) We're Young and Beautiful
31
+ # (1854) That's Where It Is
32
+ # (1786) I Ain't in Checotah Anymore
33
+ # (1596) The Night Before (Life Goes On)
34
+ #
35
+ # Similar Artists
36
+ # ===============
37
+ # (100%) Rascal Flatts
38
+ # (84.985%) Keith Urban
39
+ # (84.007%) Kellie Pickler
40
+ # (82.694%) Katharine McPhee
41
+ # (81.213%) Martina McBride
42
+ # (79.397%) Faith Hill
43
+ # (77.121%) Tim McGraw
44
+ # (75.191%) Jessica Simpson
45
+ # (75.182%) Sara Evans
46
+ # (75.144%) The Wreckers
47
+ # (73.034%) Kenny Chesney
48
+ # (71.765%) Dixie Chicks
49
+ # (71.084%) Kelly Clarkson
50
+ # (69.535%) Miranda Lambert
51
+ # (66.952%) LeAnn Rimes
52
+ # (66.398%) Mandy Moore
53
+ # (65.817%) Bo Bice
54
+ # (65.279%) Diana DeGarmo
55
+ # (65.115%) Gretchen Wilson
56
+ # (62.982%) Clay Aiken
57
+ # (62.436%) Ashlee Simpson
58
+ # (62.160%) Christina Aguilera
59
+ module Rockstar
60
+ class Artist < Base
61
+ attr_accessor :name, :mbid, :listenercount, :playcount, :rank, :url, :thumbnail
62
+ attr_accessor :summary, :content, :images, :count, :streamable
63
+ attr_accessor :chartposition
64
+
65
+ # used for similar artists
66
+ attr_accessor :match
67
+
68
+ class << self
69
+ def new_from_xml(xml, doc=nil)
70
+ # occasionally name can be found in root of artist element (<artist name="">) rather than as an element (<name>)
71
+ name = (xml).at(:name).inner_html if (xml).at(:name)
72
+ name = xml['name'] if name.nil? && xml['name']
73
+
74
+ artist = Artist.new(name)
75
+ artist.load_info(xml)
76
+ artist
77
+ end
78
+ end
79
+
80
+ def initialize(name, o={})
81
+ raise ArgumentError, "Name is required" if name.blank?
82
+ @name = name
83
+
84
+ options = {:include_info => false}.merge(o)
85
+ load_info if options[:include_info]
86
+ end
87
+
88
+ def load_info(xml=nil)
89
+ unless xml
90
+ doc = self.class.fetch_and_parse("artist.getInfo", {:artist => @name})
91
+ xml = (doc / :artist).first
92
+ end
93
+
94
+ return self if xml.nil?
95
+
96
+ self.mbid = (xml).at(:mbid).inner_html if (xml).at(:mbid)
97
+ self.listenercount = (xml).at(:listeners).inner_html if (xml).at(:listeners)
98
+ self.playcount = (xml).at(:playcount).inner_html if (xml).at(:playcount)
99
+ self.chartposition = self.rank = xml['rank'] if xml['rank']
100
+ self.chartposition = self.rank = (xml).at(:rank).inner_html if (xml).at(:rank) if self.rank.nil?
101
+ self.url = Base.fix_url((xml).at(:url).inner_html) if (xml).at(:url)
102
+
103
+ if bio_xml = xml.at(:bio)
104
+ self.summary = bio_xml.at(:summary).to_plain_text if bio_xml.at(:summary)
105
+ self.content = bio_xml.at(:content).to_plain_text if bio_xml.at(:content)
106
+ end
107
+
108
+ self.images = {}
109
+ (xml/'image').each {|image|
110
+ self.images[image['size']] = image.inner_html if self.images[image['size']].nil?
111
+ }
112
+
113
+ self.thumbnail = self.images['small']
114
+ self.match = (xml).at(:match).inner_html if (xml).at(:match)
115
+
116
+ # in top artists for tag
117
+ self.count = xml['count'] if xml['count']
118
+ self.streamable = xml['streamable'] if xml['streamable']
119
+
120
+ self.streamable = (xml).at(:streamable).inner_html == '1' ? 'yes' : 'no' if self.streamable.nil? && (xml).at(:streamable)
121
+
122
+ self
123
+ end
124
+
125
+ def current_events(format=:ics)
126
+ warn "[DEPRECATION] the `current_events` method is deprecated. Please use artist.events"
127
+ events
128
+ end
129
+
130
+ def events(force=false)
131
+ get_instance("artist.getEvents", :events, :event, {:artist => @name}, force)
132
+ end
133
+
134
+ def similar(force=false)
135
+ get_instance("artist.getSimilar", :similar, :artist, {:artist => @name}, force)
136
+ end
137
+
138
+ def top_fans(force=false)
139
+ get_instance("artist.getTopFans", :top_fans, :user, {:artist => @name}, force)
140
+ end
141
+
142
+ def top_tracks(force=false)
143
+ get_instance("artist.getTopTracks", :top_tracks, :track, {:artist => @name}, force)
144
+ end
145
+
146
+ def top_albums(force=false)
147
+ get_instance("artist.getTopAlbums", :top_albums, :album, {:artist => @name}, force)
148
+ end
149
+
150
+ def top_tags(force=false)
151
+ get_instance("artist.getTopTags", :top_tags, :tag, {:artist => @name}, force)
152
+ end
153
+
154
+ def image(which=:medium)
155
+ which = which.to_s
156
+ raise ArgumentError unless ['small', 'medium', 'large', 'extralarge'].include?(which)
157
+ load_info if self.images.nil?
158
+ self.images[which]
159
+ end
160
+
161
+ def user_images(opts={})
162
+ if mbid.nil?
163
+ opts[:artist] = name
164
+ else
165
+ opts[:mbid] = mbid
166
+ end
167
+
168
+ images = []
169
+ image_doc = self.class.fetch_and_parse("artist.getImages", opts, false)
170
+ (image_doc/'image').each do |xml|
171
+ image_sizes = {}
172
+ xml.search('/sizes/size').each do |image|
173
+ image_sizes[image['name']] = image.inner_html
174
+ end
175
+
176
+ images << image_sizes
177
+ end
178
+
179
+ images
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,21 @@
1
+ module Rockstar
2
+
3
+ class Auth < Base
4
+ # Returns the token for a session. You have to use
5
+ # TokenAuth first and then use this class with the token
6
+ # that is given by last.fm to create a session token
7
+ # This session token can be stored in your database, it is
8
+ # not expiring.
9
+ # See Rockstar::TokenAuth for a detailed example
10
+ def session(token)
11
+ doc = self.class.fetch_and_parse("auth.getSession", {:token => token}, true)
12
+ Rockstar::Session.new_from_xml(doc)
13
+ end
14
+
15
+ def token
16
+ doc = self.class.fetch_and_parse("auth.getToken", {}, true)
17
+ token = (doc).at(:token).inner_html if (doc).at(:token)
18
+ token
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ module Rockstar
2
+
3
+ API_URL = 'http://ws.audioscrobbler.com/'
4
+ API_VERSION = '2.0'
5
+
6
+ class Base
7
+ class << self
8
+ def connection
9
+ @connection ||= REST::Connection.new(API_URL + API_VERSION + "/")
10
+ end
11
+
12
+ def fetch_and_parse(resource, params = {}, sign_request = false)
13
+ Hpricot::XML(connection.get(resource, sign_request, params))
14
+ end
15
+
16
+ def get_instance(api_method, instance_name, element, params, sign_request = false)
17
+ rockstar_class = "rockstar/#{element.to_s}".camelize.constantize
18
+ doc = self.fetch_and_parse(api_method, params, sign_request)
19
+ (doc/element).inject([]) { |elements, el| elements << rockstar_class.new_from_xml(el, doc); elements }
20
+ end
21
+ end
22
+
23
+ private
24
+ # in order for subclass to use, it must have api_path method
25
+ def get_instance(api_method, instance_name, element, params, force = false, sign_request = false)
26
+ rockstar_class = "rockstar/#{element.to_s}".camelize.constantize
27
+
28
+ if instance_variable_get("@#{instance_name}").nil? || force
29
+ doc = self.class.fetch_and_parse(api_method, params, sign_request)
30
+ elements = (doc/element).inject([]) { |elements, el| elements << rockstar_class.new_from_xml(el, doc); elements }
31
+ instance_variable_set("@#{instance_name}", elements)
32
+ end
33
+ instance_variable_get("@#{instance_name}")
34
+ end
35
+
36
+ def self.fix_url(url)
37
+ if (!url.blank? && !url.match("^http://"))
38
+ url = "http://#{url}"
39
+ end
40
+ url
41
+ end
42
+
43
+ def self.parse_time(time_str)
44
+ return nil if time_str.blank?
45
+ Time.parse(time_str)
46
+ end
47
+ end
48
+ end