这是一个搜索艺术家的佣金任务,如果它存在,它将存储艺术家专辑。我试图使用gem,但由于某种原因,宝石会返回我真正不需要的东西。如果我搜索艺术家,它的工作正常。
result = ITunesSearchAPI.lookup(:id => 372976 , :entity => 'album')
将返回此信息:
{"wrapperType"=>"artist", "artistType"=>"Artist", "artistName"=>"ABBA", "artistLinkUrl"=>"https://itunes.apple.com/us/artist/abba/id372976?uo=4", "artistId"=>372976, "amgArtistId"=>3492, "primaryGenreName"=>"Pop", "primaryGenreId"=>14}
这根本不是我需要的。 Here's我应该得到什么。
所以我决定自己编码,然后我意识到它保存了一个空模型,我的Album中的所有内容都是零。 2个问题:
1)我该如何解决?
2)如何保存所有专辑,而不只是一个?
require 'net/http'
task :artist,[""] => :environment do |t, args|
result = ITunesSearchAPI.search(:term => args.to_s, :entity => 'musicArtist')
if result.empty? then puts "Nothing was found. Try another artist."
puts result
elsif result
uniqueness = Artist.find_by(itunes_id: result[0]["artistId"])
if uniqueness.nil?
Artist.create(name: result[0]["artistName"], itunes_id: result[0]["artistId"])
puts result
else
puts "The artist already exists in database"
end
end
if uniqueness.nil?
album = URI('https://itunes.apple.com/lookup')
album_params = { :id => result[0]['artistId'], :entity => 'album'}
album.query = URI.encode_www_form(album_params)
album_response = Net::HTTP.get_response(album)
puts album_response.body
Album.create!(name: album_response.body[0]["collectionName"], artwork_url_100: album_response.body[0]["artworkUrl100"])
end
end
架构:
ActiveRecord::Schema.define(version: 20160418120725) do
create_table "albums", force: true do |t|
t.string "name"
t.string "artwork_url_100"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "artists", force: true do |t|
t.string "name"
t.integer "itunes_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "artists", ["itunes_id"], name: "index_artists_on_itunes_id", unique: true
end
答案 0 :(得分:1)
回答第1部分。您可能需要为唯一性和状态添加一些模型验证。在您的artist.rb文件中:
class Artist < ActiveRecord::Base
...
validates :itunes_id, presence: true, uniqueness: true
validates :name, presence: true, uniqueness: true
...
end
这应该可以防止您的模型保存在无效状态。每个属性itunes_id
和name
都必须存在(不是零)和唯一(您不能拥有2&#39; ABBA&#39;艺术家记录)。
有关ActiveRecord验证的更多信息,请访问: http://guides.rubyonrails.org/active_record_validations.html
一旦您获得了验证规则,那么检查现有记录并更新它们的代码可以简化为:
artist = Artist.where(itunes_id: result[0]["artistId"]).first_or_initialize
artist.name = result[0]["artistName"]
artist.save
然后我们检查是否有任何阻止记录持久存储到数据库的错误:
if artist.errors.any?
puts "There were errors preventing the artist being saved:"
artist.errors.full_messages.each do |message|
puts " - #{message}"
end
puts "Result data: #{result}"
exit
end
一旦我们超过了这个块(我们还没有退出),那么我们知道我们的artist
对象是一个有效且持久的模型对象。
回答第2部分。您需要在艺术家和专辑模型之间建立一对多(has_many)关联。然后你只需要遍历结果数组,为每个条目创建一个新的Album。
查看您的架构,您需要将一个整数属性添加到名为artist_id
的相册模型中。您可以使用以下命令创建迁移:
rails g migration AddArtistToAlbums artist:references
magic 命令行语法应生成一个正确的迁移文件,该文件应如下所示:
class AddArtistToAlbums < ActiveRecord::Migration
def change
add_reference :albums, :artist, index: true, foreign_key: true
end
end
运行rake db:migrate
以更新数据库架构。
在您的artist.rb模型文件中,您现在可以添加以下内容:
class Artist < ActiveRecord::Base
...
has_many :albums
...
end
您现在可以通过它的关联属性albums
访问与艺术家相关联的相册。
在您的album.rb模型文件中,您现在可以添加以下内容:
class Album < ActiveRecord::Base
...
belongs_to :artist
...
end
您现在可以通过它的关联属性artist
访问与相册相关联的艺术家。
在您直接深入解释回复正文之前,我可能会先检查一下我是否得到了正确的请求:
if !album_response.is_a?(Net::HTTPOK)
puts "There was an error fetching albums."
exit
end
在处理响应之前,您需要解析JSON。在require 'json'
文件的顶部,然后解析album_response.body
,如:
album_response_json = JSON.parse(album_response.body)
之后我还要检查以确保正文按预期填充。
if !album_response_json.is_a?(Hash)
puts "Response JSON is not a Hash as expected."
exit
end
您还可以检查响应哈希是否具有预期的results
数组。
if !album_response_json["results"].is_a?(Array)
puts "Response JSON does not contain the expected 'results' array."
exit
end
接下来,您正在通过索引album_response.body[0]
从散列中访问键值,该值将是基于您的示例JSON的整数(23)。我认为您打算访问results
数组的第一个元素。
您需要做的是迭代结果,为每张专辑创建一个新的模型对象。我注意到,在您的示例JSON响应中,有wrapperType
的&#39;艺术家&#39;我认为你想过滤掉所以代码看起来像这样:
album_response_json["results"].each do |album_hash|
next if album_hash["wrapperType"] == "artist"
artist.albums.create!(name: album_hash["collectionName"], artwork_url_100: album_hash["artworkUrl100"])
end
您现在应该按预期存储相册。
请注意。我跳过了为Album模型添加验证,但这是一个好主意。