-
Notifications
You must be signed in to change notification settings - Fork 9
2 Tutorial API Discogs
Implemente o Tutorial CRUD ou comece esse tutorial a partir dessa branch. Para esse tutorial vamos precisar executar os testes da pasta tutorials/discogs_api_tutorial
somente com: rspec spec/tutorials/discogs_api_tutorial/*
.
abrir arquivo Gemfile
e adicionar abaixo da linha gem 'faker'
a seguinte linha:
gem 'discogs-wrapper'
executar bundle install
na pasta app do projeto criar uma pasta chamada services
e dentro dela um arquivo com o nome discogs_requests_service.rb
e nesse arquivo adicionar as seguintes linhas:
module DiscogsRequestsService
DISCOGS_TOKEN = 'cvxyzWiAjGkjVBIgWBwsnsoWVqckMFwyATbuZRGU'.freeze
APP_NAME = 'Getonrails'.freeze
end
verifique que as constantes estão acessíveis do console com por exemplo: DiscogsRequestsService::DISCOGS_TOKEN
modifique a mesma classe para que ela crie uma instância autenticada do wrapper Discogs:
module DiscogsRequestsService
DISCOGS_TOKEN = 'cvxyzWiAjGkjVBIgWBwsnsoWVqckMFwyATbuZRGU'.freeze
APP_NAME = 'Getonrails'.freeze
class Client
private
def client
@client ||= Discogs::Wrapper.new(APP_NAME, user_token: DISCOGS_TOKEN)
end
end
end
modifique novamente a mesma classe para criar uma função que busca artists no Discogs a partir de seu nome:
module DiscogsRequestsService
...
class Client
def search_artist_by_name(name, results_per_page: 10)
client.search(name, per_page: results_per_page, type: :artist)
end
private
def client
...
end
end
end
através do console teste algumas buscas com:
DiscogsRequestsService::Client.new.search_artist_by_name('Zé Ramalho')
modifique novamente a classe para criar uma função que resolve a id de um artist a partir de seu nome:
module DiscogsRequestsService
...
class Client
def search_artist_by_name(name, results_per_page: 10)
...
end
def resolve_artist_id(name)
search = search_artist_by_name(name)
search['results'][0]['id']
end
private
def client
...
end
end
end
agora modifique mais uma vez para que o client retorne um artist procurando por seu nome, inferindo sua id e retornando seu objeto.
module DiscogsRequestsService
...
class Client
def get_artist(name)
artist_id = resolve_artist_id(name)
client.get_artist(artist_id)
end
private
def search_artist_by_name(name, results_per_page: 10)
...
end
def resolve_artist_id(name)
...
end
def client
...
end
end
end
nesse ponto já é possível acessar as infromações do artist vindas da API mais facilmente:
artist = DiscogsRequestsService::Client.new.get_artist('Led Zeppelin')
artist.name # => "Led Zeppelin"
modifique mais uma vez a classe para que seja possível buscar as releases do artist através de seu nome:
module DiscogsRequestsService
...
class Client
def get_artist(name)
...
end
def search_artist_releases(name, max_results: 10)
artist_id = resolve_artist_id(name)
client.get_artist_releases(artist_id.to_s, { per_page: max_results})['releases']
end
private
def search_artist_by_name(name, results_per_page: 10)
...
end
def resolve_artist_id(name)
...
end
def client
...
end
end
end
com o resultado dessa requisição é possível iterar nos dados e usá-los como quisermos:
releases = DiscogsRequestsService::Client.new.search_artist_releases('Led Zeppelin')
releases[1]['title'] # => "Free Me / Whole Lotta Love"
releases[1]['year'] # => 1969
releases[1]['id'] # => 2625192
ainda não estamos tratando casos em que o artista não é encontrado.
primeiro altere a função resolve_artist_id
dessa forma:
def resolve_artist_id(name)
search = search_artist_by_name(name)
search['results'].blank? ? nil : search['results'][0]['id']
end
e agora adicione um retorno condicional nas funções públicas de busca:
def get_artist(name)
artist_id = resolve_artist_id(name)
return {} unless artist_id
client.get_artist(artist_id)
end
def search_artist_releases(name, max_results: 10)
artist_id = resolve_artist_id(name)
return {} unless artist_id
client.get_artist_releases(artist_id.to_s, { per_page: max_results})['releases']
end
no fim o módulo deve ficar dessa forma:
module DiscogsRequestsService
class Client
def get_artist(name)
artist_id = resolve_artist_id(name)
return {} unless artist_id
client.get_artist(artist_id)
end
def search_artist_releases(name, max_results: 10)
artist_id = resolve_artist_id(name)
return {} unless artist_id
client.get_artist_releases(artist_id.to_s, { per_page: max_results})['releases']
end
private
def search_artist_by_name(name, results_per_page: 10)
client.search(name, per_page: results_per_page, type: :artist)
end
def resolve_artist_id(name)
search = search_artist_by_name(name)
search['results'].blank? ? nil : search['results'][0]['id']
end
def client
@client ||= Discogs::Wrapper.new(ENV['APP_NAME'], user_token: ENV['DISCOGS_TOKEN'])
end
end
end
no ínicio do arquivo Gemfile
após a versão do ruby adicione a seguinte linha:
gem 'dotenv-rails', groups: [:development, :test]
agora execute sua instalação no console com bundle install
em seguida crie um arquivo na pasta root do projeto com o nome .env
Nesse arquivo adicione as sequintes linhas:
DISCOGS_TOKEN=cvxyzWiAjGkjVBIgWBwsnsoWVqckMFwyATbuZRGU
APP_NAME=Getonrails
agora remova as constantes definidas no módulo DiscogsRequestsService
e modifique nessa mesma classe a função que instancia o client dessa forma:
def client
@client ||= Discogs::Wrapper.new(ENV['APP_NAME'], user_token: ENV['DISCOGS_TOKEN'])
end
buscar releases de um artist qualquer deve continuar funcionando normalmente.
por fim ignore o arquivo .env
ao submeter commits ao git adicionando no arquivo .gitignore
as seguintes linhas:
# Ignore local config envs
.env
crie uma rota para importações no arquivo routes.rb
:
post 'artists/import', to: 'imports#artist'
agora crie na pasta app/controllers
um controller para importações chamado imports_controller.rb
nesse controller inclua o seguinte conteúdo:
class ImportsController < ApplicationController
def artist; end
end
agora modifique o arquivo app/views/artists/index.html.erb
para incluir um novo botão abaixo do botão já existente:
<%= link_to('Import', '#', class: "btn btn-primary btn-lg btn-block login-button", 'data-toggle' => "modal", 'data-target'=>"#importArtistModal" ) %>
no mesmo arquivo adicione um modal para receber os dados de importação:
<div class="modal fade" id="importArtistModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Import Artist</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<%= form_with(url: artists_import_path, local: true) do |form| %>
<div class="modal-body">
<div class="card-body">
<div class="row">
<div class="col-12">
<div class="form-group">
<label for="name" class="control-label custom-control-label">Name</label>
<div class="input-group">
<span class="input-group-addon"><i class="fas fa-compact-disc" aria-hidden="true"></i></span>
<input type="text" class="form-control" id="import-artist-name" name="import_artist[name]" value="">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Import</button>
</div>
</div>
<% end %>
</div>
</div>
com isso já deve ser possível ver um modal abrir na tela quando o botão Import é acionado.
modifique o arquivo app/controllers/imports_controller.rb
para receber dados do front da seguinte forma:
class ImportsController < ApplicationController
def artist; end
private
def import_artist_params
params.require(:import_artist).permit(
:name
)
end
end
agora modifique novamente para usar os dados recebidos numa requisição ao cliente Discogs:
class ImportsController < ApplicationController
def artist
client = DiscogsRequestsService::Client.new
artist = client.get_artist(import_artist_params[:name])
end
private
...
end
salve os dados recebidos no banco e redirecione o usuário dessa forma:
class ImportsController < ApplicationController
def artist
client = DiscogsRequestsService::Client.new
artist = client.get_artist(import_artist_params[:name])
Artist.new(name: artist.name, profile: artist.profile, user: current_user).save
redirect_to artists_path
end
private
...
end
por fim retorne uma mensagem para o usuário quando nenhum dado foi informado:
class ImportsController < ApplicationController
def artist
if import_artist_params[:name].blank?
redirect_to artists_path, notice: 'Please inform an artist'
return
end
...
end
private
...
end
com essas modificações já deve ser possível salvar artists a partir de dados do discogs
sem a ajuda de um tutorial, crie um endpoint imports#releases
que deve ser chamado dentro de um modal na página app/views/releases/index.html.erb
e que deve receber o número de releases desejadas. Os dados recebidos
devem ser salvos na relação artist.releases