1
0
Fork 0

created new track_search binding to allow searching for tracks (really recordings). Modified existing model classes to call super() to handle search (open/closed principle, attempting to reduce duplicate code). Fixed xml namespace issue in specs.

This commit is contained in:
Thomas Wolfe 2013-05-05 18:14:44 -05:00
parent 687ce1b785
commit d8184565a2
13 changed files with 96 additions and 26 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ coverage
tmp tmp
Gemfile.lock Gemfile.lock
.gem .gem
*.swp

View File

@ -4,3 +4,4 @@ Applicat (https://github.com/Applicat)
Jens Fahnenbruck (https://github.com/jigfox) Jens Fahnenbruck (https://github.com/jigfox)
Sander Nieuwenhuizen (https://github.com/munkius) Sander Nieuwenhuizen (https://github.com/munkius)
Savater Sebastien (https://github.com/blakink) Savater Sebastien (https://github.com/blakink)
Thomas Wolfe (https://github.com/tomwolfe)

View File

@ -1,2 +1,2 @@
source :rubygems source 'https://rubygems.org'
gemspec gemspec

View File

@ -80,9 +80,9 @@ MusicBrainz::ReleaseGroup
```ruby ```ruby
# Class Methods # Class Methods
MusicBrainz::ReleaseGroup.find(id) MusicBrainz::ReleaseGroup.find(id)
MusicBrainz::ReleaseGroup.find_by_artist_and_title(artist_name, title, type: 'Album') MusicBrainz::ReleaseGroup.find_by_artist_and_title(artist_name, title, 'Album') # 3rd arg optional
MusicBrainz::ReleaseGroup.search(artist_name, title) MusicBrainz::ReleaseGroup.search(artist_name, title)
MusicBrainz::ReleaseGroup.search(artist_name, title, type: 'Album') MusicBrainz::ReleaseGroup.search(artist_name, title, 'Album') # 3rd arg optional
# Instance Methods # Instance Methods
@release_group.releases @release_group.releases
@ -125,6 +125,7 @@ MusicBrainz::Track
```ruby ```ruby
# Class Methods # Class Methods
MusicBrainz::Track.find(id) MusicBrainz::Track.find(id)
MusicBrainz::ReleaseGroup.search(artist_name, track_name)
# Fields # Fields
{ {

View File

@ -29,6 +29,7 @@ require "musicbrainz/bindings/release_group_releases"
require "musicbrainz/bindings/release" require "musicbrainz/bindings/release"
require "musicbrainz/bindings/release_tracks" require "musicbrainz/bindings/release_tracks"
require "musicbrainz/bindings/track" require "musicbrainz/bindings/track"
require "musicbrainz/bindings/track_search"
module MusicBrainz module MusicBrainz
GH_PAGE_URL = "http://git.io/brainz" GH_PAGE_URL = "http://git.io/brainz"

View File

@ -0,0 +1,21 @@
# encoding: UTF-8
module MusicBrainz
module Bindings
module TrackSearch
def parse(xml)
xml.xpath('./recording-list/recording').map do |xml|
{
id: (xml.attribute('id').value rescue nil),
mbid: (xml.attribute('id').value rescue nil), # Old shit
title: (xml.xpath('./title').text.gsub(/[`]/, "'") rescue nil),
artist: (xml.xpath('./artist-credit/name-credit/artist/name').text rescue nil),
releases: (xml.xpath('./release-list/release/title').map{ |xml| xml.text } rescue []),
score: (xml.attribute('score').value.to_i rescue nil)
} rescue nil
end.delete_if{ |item| item.nil? }
end
extend self
end
end
end

View File

@ -25,11 +25,7 @@ module MusicBrainz
end end
def search(name) def search(name)
name = CGI.escape(name).gsub(/\!/, '\!') super({artist: name})
client.load(:artist, { query: "artist:#{name}", limit: 10 }, {
binding: :artist_search
})
end end
def discography(mbid) def discography(mbid)

View File

@ -23,6 +23,38 @@ module MusicBrainz
def client def client
MusicBrainz.client MusicBrainz.client
end end
def search(hash)
hash = escape_strings(hash)
query_val = build_query(hash)
underscore_name = self.name[13..-1].underscore
client.load(underscore_name.to_sym, { query: query_val, limit: 10 }, { binding: underscore_name.insert(-1,"_search").to_sym })
end
class ::String
def underscore
self.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end
end
def build_query(hash)
return ["#{hash.first[0].to_s}:\"#{hash.first[1]}\""] if hash.size ==1
arr ||= []
hash.each { |k, v| arr << "#{k.to_s}:\"#{hash[k]}\"" }
arr.join(' AND ')
end
def escape_strings(hash)
hash.each { |k, v| hash[k] = CGI.escape(v).gsub(/\!/, '\!') }
hash
end
# these probably should be private... but I'm not sure how to get it to work in a module...
# private_class_method :build_query, :escape_strings
end end
module InstanceMethods module InstanceMethods

View File

@ -25,20 +25,16 @@ module MusicBrainz
}) })
end end
def search(artist_name, title, options = {}) def search(artist_name, title, type = nil)
artist_name = CGI.escape(artist_name).gsub(/\!/, '\!') if type
title = CGI.escape(title).gsub(/\!/, '\!') super({artist: artist_name, releasegroup: title, type: type})
query = ["artist:\"#{artist_name}\"", "releasegroup:\"#{title}\""] else
query << "type: #{options[:type]}" if options[:type] super({artist: artist_name, releasegroup: title})
end
client.load(
:release_group, { query: query.join(' AND '), limit: 10 },
{ binding: :release_group_search }
)
end end
def find_by_artist_and_title(artist_name, title, options = {}) def find_by_artist_and_title(artist_name, title, type = nil )
matches = search(artist_name, title, options) matches = search(artist_name, title, type)
matches.empty? ? nil : find(matches.first[:id]) matches.empty? ? nil : find(matches.first[:id])
end end
end end

View File

@ -12,6 +12,10 @@ module MusicBrainz
create_model: :track create_model: :track
}) })
end end
def search(artist_name, track_name)
super({artist: artist_name, recording: track_name})
end
end end
end end
end end

View File

@ -5,8 +5,8 @@ require "spec_helper"
describe MusicBrainz::Bindings::ReleaseGroupSearch do describe MusicBrainz::Bindings::ReleaseGroupSearch do
describe '.parse' do describe '.parse' do
it "gets correct release group data" do it "gets correct release group data" do
response = '<release-group-list><release-group id="246bc928-2dc8-35ba-80ee-7a0079de1632" type="Single" ext:score="100"><title>Empire</title></release-group>' response = '<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#" xmlns:ext="http://musicbrainz.org/ns/ext#-2.0"><release-group-list><release-group id="246bc928-2dc8-35ba-80ee-7a0079de1632" type="Single" ext:score="100"><title>Empire</title></release-group></release-group-list></metadata>'
described_class.parse(Nokogiri::XML.parse(response)).should == [ described_class.parse(Nokogiri::XML.parse(response).remove_namespaces!.xpath('/metadata')).should == [
{ {
id: '246bc928-2dc8-35ba-80ee-7a0079de1632', mbid: '246bc928-2dc8-35ba-80ee-7a0079de1632', id: '246bc928-2dc8-35ba-80ee-7a0079de1632', mbid: '246bc928-2dc8-35ba-80ee-7a0079de1632',
title: 'Empire', type: 'Single', score: 100 title: 'Empire', type: 'Single', score: 100
@ -14,4 +14,4 @@ describe MusicBrainz::Bindings::ReleaseGroupSearch do
] ]
end end
end end
end end

View File

@ -0,0 +1,17 @@
# -*- encoding: utf-8 -*-
require "spec_helper"
describe MusicBrainz::Bindings::TrackSearch do
describe '.parse' do
it "gets correct Track (really recording) data" do
response = '<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#" xmlns:ext="http://musicbrainz.org/ns/ext#-2.0"><recording-list offset="0" count="1"><recording id="0b382a13-32f0-4743-9248-ba5536a6115e" ext:score="100"><title>King Fred</title><artist-credit><name-credit><artist id="f52f7a92-d495-4d32-89e7-8b1e5b8541c8"><name>Too Much Joy</name></artist></name-credit></artist-credit><release-list><release id="8442e42b-c40a-4817-89a0-dbe663c94d2d"><title>Green Eggs and Crack</title></release></release-list></recording></recording-list></metadata>'
described_class.parse(Nokogiri::XML.parse(response).remove_namespaces!.xpath('/metadata')).should == [
{
id: '0b382a13-32f0-4743-9248-ba5536a6115e', mbid: '0b382a13-32f0-4743-9248-ba5536a6115e',
title: 'King Fred', artist: 'Too Much Joy', releases: ['Green Eggs and Crack'], score: 100
}
]
end
end
end

View File

@ -31,13 +31,13 @@ describe MusicBrainz::ReleaseGroup do
matches = MusicBrainz::ReleaseGroup.search('Kasabian', 'Empire') matches = MusicBrainz::ReleaseGroup.search('Kasabian', 'Empire')
matches.length.should be > 0 matches.length.should be > 0
matches.first[:title].should == 'Empire' matches.first[:title].should == 'Empire'
matches.first[:type].should == 'Single' matches.first[:type].should == 'Album'
end end
end end
context 'with type filter' do context 'with type filter' do
it "searches release group by artist name and title" do it "searches release group by artist name and title" do
matches = MusicBrainz::ReleaseGroup.search('Kasabian', 'Empire', type: 'Album') matches = MusicBrainz::ReleaseGroup.search('Kasabian', 'Empire', 'Album')
matches.length.should be > 0 matches.length.should be > 0
matches.first[:title].should == 'Empire' matches.first[:title].should == 'Empire'
matches.first[:type].should == 'Album' matches.first[:type].should == 'Album'
@ -48,7 +48,7 @@ describe MusicBrainz::ReleaseGroup do
describe '.find_by_artist_and_title' do describe '.find_by_artist_and_title' do
it "gets first release group by artist name and title" do it "gets first release group by artist name and title" do
release_group = MusicBrainz::ReleaseGroup.find_by_artist_and_title('Kasabian', 'Empire') release_group = MusicBrainz::ReleaseGroup.find_by_artist_and_title('Kasabian', 'Empire')
release_group.id.should == '246bc928-2dc8-35ba-80ee-7a0079de1632' release_group.id.should == '6f33e0f0-cde2-38f9-9aee-2c60af8d1a61'
end end
end end