diff --git a/.gitignore b/.gitignore index 03f3ce7..882d639 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,5 @@ build-iPhoneSimulator/ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: .rvmrc + +/.env diff --git a/Gemfile b/Gemfile index 288bb87..7fb3327 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ ruby '2.3.1' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '4.2.6' # Use postgresql as the database for Active Record -gem 'pg', '~> 0.15' +# gem 'pg', '~> 0.15' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets @@ -13,9 +13,22 @@ gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.1.0' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'therubyracer', platforms: :ruby +gem 'httparty' + +gem 'yelp' -# Use jquery as the JavaScript library gem 'jquery-rails' + +gem 'rspotify' + +gem 'omniauth' +gem 'omniauth-spotify' + +gem 'omniauth-oauth2', '~> 1.3.1' + +gem 'pg', '~> 0.15' + +# Use jquery as the JavaScript library # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.0' # bundle exec rake doc:rails generates the API under doc/api. @@ -33,13 +46,27 @@ gem 'sdoc', '~> 0.4.0', group: :doc group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' + gem 'simplecov', '~> 0.11.2' + gem 'dotenv-rails' + gem 'pry-rails' + gem 'minitest-vcr' + gem 'minitest-reporters' + gem 'webmock' + gem 'vcr' end group :development do # Access an IRB console on exception pages or by using <%= console %> in views gem 'web-console', '~> 2.0' + # gem "pry-rails" + gem "better_errors" + gem "binding_of_caller" + gem 'rails-erd' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' end +group :production do + gem 'rails_12factor' +end diff --git a/Gemfile.lock b/Gemfile.lock index 6ff0f39..65d7680 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,11 +36,19 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) + addressable (2.4.0) + ansi (1.5.0) arel (6.0.3) + better_errors (2.1.1) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + rack (>= 0.9.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) builder (3.2.2) byebug (8.2.5) + choice (0.2.0) + coderay (1.1.1) coffee-rails (4.1.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.1.x) @@ -49,11 +57,27 @@ GEM execjs coffee-script-source (1.10.0) concurrent-ruby (1.0.2) + crack (0.4.3) + safe_yaml (~> 1.0.0) debug_inspector (0.0.2) + docile (1.1.5) + dotenv (2.1.1) + dotenv-rails (2.1.1) + dotenv (= 2.1.1) + railties (>= 4.0, < 5.1) erubis (2.7.0) execjs (2.6.0) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + faraday_middleware (0.10.0) + faraday (>= 0.7.4, < 0.10) globalid (0.3.6) activesupport (>= 4.1.0) + hashdiff (0.3.0) + hashie (3.4.4) + httparty (0.13.7) + json (~> 1.8) + multi_xml (>= 0.5.2) i18n (0.7.0) jbuilder (2.4.1) activesupport (>= 3.0.0, < 5.1) @@ -63,19 +87,55 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (1.8.3) + jwt (1.5.1) loofah (2.0.3) nokogiri (>= 1.5.9) mail (2.6.4) mime-types (>= 1.16, < 4) + method_source (0.8.2) mime-types (3.0) mime-types-data (~> 3.2015) mime-types-data (3.2016.0221) mini_portile2 (2.0.0) + minispec-metadata (2.0.0) + minitest minitest (5.8.4) + minitest-reporters (1.1.9) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + minitest-vcr (1.4.0) + minispec-metadata (~> 2.0) + minitest (>= 4.7.5) + vcr (>= 2.9) multi_json (1.12.0) + multi_xml (0.5.5) + multipart-post (2.0.0) + netrc (0.7.9) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) + oauth2 (1.1.0) + faraday (>= 0.8, < 0.10) + jwt (~> 1.0, < 1.5.2) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.3.1) + hashie (>= 1.2, < 4) + rack (>= 1.0, < 3) + omniauth-oauth2 (1.3.1) + oauth2 (~> 1.0) + omniauth (~> 1.2) + omniauth-spotify (0.0.9) + omniauth-oauth2 (~> 1.1) pg (0.18.4) + pry (0.10.3) + coderay (~> 1.1.0) + method_source (~> 0.8.1) + slop (~> 3.4) + pry-rails (0.3.4) + pry (>= 0.9.10) rack (1.6.4) rack-test (0.6.3) rack (>= 1.0) @@ -96,8 +156,18 @@ GEM activesupport (>= 4.2.0.beta, < 5.0) nokogiri (~> 1.6.0) rails-deprecated_sanitizer (>= 1.0.1) + rails-erd (1.4.7) + activerecord (>= 3.2) + activesupport (>= 3.2) + choice (~> 0.2.0) + ruby-graphviz (~> 1.2) rails-html-sanitizer (1.0.3) loofah (~> 2.0) + rails_12factor (0.0.3) + rails_serve_static_assets + rails_stdout_logging + rails_serve_static_assets (0.0.5) + rails_stdout_logging (0.0.5) railties (4.2.6) actionpack (= 4.2.6) activesupport (= 4.2.6) @@ -106,6 +176,14 @@ GEM rake (11.1.2) rdoc (4.2.2) json (~> 1.4) + rest_client (1.8.3) + netrc (~> 0.7.7) + rspotify (1.10.0) + omniauth-oauth2 (~> 1.1) + rest_client (~> 1.8) + ruby-graphviz (1.2.2) + ruby-progressbar (1.8.1) + safe_yaml (1.0.4) sass (3.4.22) sass-rails (5.0.4) railties (>= 4.0.0, < 5.0) @@ -116,6 +194,13 @@ GEM sdoc (0.4.1) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) + simple_oauth (0.3.1) + simplecov (0.11.2) + docile (~> 1.1.0) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) + slop (3.6.0) spring (1.7.1) sprockets (3.6.0) concurrent-ruby (~> 1.0) @@ -131,27 +216,56 @@ GEM thread_safe (~> 0.1) uglifier (3.0.0) execjs (>= 0.3.0, < 3) + vcr (3.0.3) web-console (2.3.0) activemodel (>= 4.0) binding_of_caller (>= 0.7.2) railties (>= 4.0) sprockets-rails (>= 2.0, < 4.0) + webmock (2.0.3) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff + yelp (2.1.2) + faraday (~> 0.8, >= 0.8.0) + faraday_middleware (~> 0.8, >= 0.8.0) + simple_oauth (~> 0.3.1) PLATFORMS ruby DEPENDENCIES + better_errors + binding_of_caller byebug coffee-rails (~> 4.1.0) + dotenv-rails + httparty jbuilder (~> 2.0) jquery-rails + minitest-reporters + minitest-vcr + omniauth + omniauth-oauth2 (~> 1.3.1) + omniauth-spotify pg (~> 0.15) + pry-rails rails (= 4.2.6) + rails-erd + rails_12factor + rspotify sass-rails (~> 5.0) sdoc (~> 0.4.0) + simplecov (~> 0.11.2) spring uglifier (>= 1.3.0) + vcr web-console (~> 2.0) + webmock + yelp + +RUBY VERSION + ruby 2.3.1p112 BUNDLED WITH - 1.12.3 + 1.12.4 diff --git a/app/assets/images/spotify-user-logo.jpeg b/app/assets/images/spotify-user-logo.jpeg new file mode 100644 index 0000000..2afb140 Binary files /dev/null and b/app/assets/images/spotify-user-logo.jpeg differ diff --git a/app/assets/javascripts/home.coffee b/app/assets/javascripts/home.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/home.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/sessions.coffee b/app/assets/javascripts/sessions.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/sessions.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/suggestions.coffee b/app/assets/javascripts/suggestions.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/suggestions.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/users.coffee b/app/assets/javascripts/users.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/users.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index f9cd5b3..9c8ef3e 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1,15 +1,20 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any styles - * defined in the other CSS/SCSS files in this directory. It is generally better to create a new - * file per style scope. - * - *= require_tree . - *= require_self - */ +.jumbo-fix { + margin-top: 110px; +} + +h1, h2, h3, h4, h5, h6 { + text-align: center; +} + +.card-h { + height: 65rem; + /*padding: 2rem 0rem;*/ +} + +body { + background-color: #ccc; +} + +.card-p { + padding: 3rem 0rem; +} diff --git a/app/assets/stylesheets/home.scss b/app/assets/stylesheets/home.scss new file mode 100644 index 0000000..f0ddc68 --- /dev/null +++ b/app/assets/stylesheets/home.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the home controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000..7bef9cf --- /dev/null +++ b/app/assets/stylesheets/sessions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sessions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/suggestions.scss b/app/assets/stylesheets/suggestions.scss new file mode 100644 index 0000000..c0d3b8d --- /dev/null +++ b/app/assets/stylesheets/suggestions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the suggestions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss new file mode 100644 index 0000000..31a2eac --- /dev/null +++ b/app/assets/stylesheets/users.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Users controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e..f14bcac 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,19 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + + helper_method :current_user + + before_action :require_login + + def current_user + @user ||= User.find_by(id: session[:user_id]) + end + + def require_login + if current_user.nil? + flash[:error] = "You must be logged in to view this section" + redirect_to root_path + end + end end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 0000000..3735c7c --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,48 @@ +require 'tunes_takeout' + +class HomeController < ApplicationController + skip_before_action :require_login, only: :index + + def index + @top_suggestions = TunesTakeoutWrapper.top_suggest + @suggestion_ids = @top_suggestions["suggestions"] + + @top_ideas = [] + @suggestion_ids.each do |suggestion_id| + @top_ideas << TunesTakeoutWrapper.find_suggest(suggestion_id)["suggestion"] + end + + @top_favorites = [] + @top_ideas.each do |top_idea| + top_sugg = {} + yelp = Food.yelp_find(top_idea["food_id"]) + spotify = Music.spotify_find(top_idea["music_type"], top_idea["music_id"]) + top_sugg[:suggestion_id] = top_idea["id"] + top_sugg[:business_name] = yelp.business.name + top_sugg[:business_url] = yelp.business.url + top_sugg[:business_image] = yelp.business.image_url + top_sugg[:business_rating_image] = yelp.business.rating_img_url + top_sugg[:business_phone] = yelp.business.phone + top_sugg[:music_name] = spotify.name + top_sugg[:music_type] = spotify.type + top_sugg[:music_embed] = spotify.uri + top_sugg[:music_url] = spotify.external_urls["spotify"] + + if spotify.type == "artist" + top_sugg[:music_artist] = nil + else + top_sugg[:music_artist] = spotify.artists[0].name + end + + if spotify.type == "album" + top_sugg[:music_image] = spotify.images[2]["url"] + elsif spotify.type == "artist" + top_sugg[:music_image] = "http://www.shootersconnectionstore.com/App_Themes/SC_Responsive/Images/no-thumbnail-available.png" + elsif spotify.type == "track" + top_sugg[:music_image] = spotify.album.images[2]["url"] + end + + @top_favorites << top_sugg + end + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000..3886fda --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,25 @@ +class SessionsController < ApplicationController + skip_before_action :require_login, only: [:new, :create] + + def new + + end + + def create + auth_hash = request.env['omniauth.auth'] + user = User.find_or_create_from_omniauth(auth_hash) + + if user + session[:user_id] = user.id + redirect_to users_path + else + flash[:notice] = "Nope" + redirect_to root_path + end + end + + def destroy + session.delete :user_id + redirect_to root_path + end +end diff --git a/app/controllers/suggestions_controller.rb b/app/controllers/suggestions_controller.rb new file mode 100644 index 0000000..8b82f6b --- /dev/null +++ b/app/controllers/suggestions_controller.rb @@ -0,0 +1,44 @@ +require 'tunes_takeout' + +class SuggestionsController < ApplicationController + def index + @choices = TunesTakeoutWrapper.spotify_search(params[:query], params[:limit]) + if params[:query] + @choices_hash = @choices["suggestions"] + + @suggestions = [] + @choices_hash.each do |hash_id| + sugg = {} + yelp = Food.yelp_find(hash_id["food_id"]) + spotify = Music.spotify_find(hash_id["music_type"], hash_id["music_id"]) + sugg[:suggestion_id] = hash_id["id"] + sugg[:business_name] = yelp.business.name + sugg[:business_url] = yelp.business.url + sugg[:business_image] = yelp.business.image_url + sugg[:business_rating_image] = yelp.business.rating_img_url + sugg[:business_phone] = yelp.business.phone + sugg[:music_name] = spotify.name + sugg[:music_type] = spotify.type + sugg[:music_embed] = spotify.uri + sugg[:music_url] = spotify.external_urls["spotify"] + + if spotify.type == "artist" + sugg[:music_artist] = nil + else + sugg[:music_artist] = spotify.artists[0].name + end + + if spotify.type == "album" + sugg[:music_image] = spotify.images[2]["url"] + elsif spotify.type == "artist" + sugg[:music_image] = "http://www.shootersconnectionstore.com/App_Themes/SC_Responsive/Images/no-thumbnail-available.png" + elsif spotify.type == "track" + sugg[:music_image] = spotify.album.images[2]["url"] + end + + @suggestions << sugg + end + end + end + +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000..6e7290f --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,65 @@ +class UsersController < ApplicationController + def index + @user_favorites = TunesTakeoutWrapper.favorites(current_user.uid) + @favorites = [] + @user_favorites["suggestions"].each do |user_favorite| + @favorites << TunesTakeoutWrapper.find_suggest(user_favorite)["suggestion"] + end + @your_favorites = [] + @favorites.each do |favorite| + fave_sugg = {} + yelp = Food.yelp_find(favorite["food_id"]) + spotify = Music.spotify_find(favorite["music_type"], favorite["music_id"]) + fave_sugg[:suggestion_id] = favorite["id"] + fave_sugg[:business_name] = yelp.business.name + fave_sugg[:business_url] = yelp.business.url + fave_sugg[:business_image] = yelp.business.image_url + fave_sugg[:business_rating_image] = yelp.business.rating_img_url + fave_sugg[:business_phone] = yelp.business.phone + fave_sugg[:music_name] = spotify.name + fave_sugg[:music_type] = spotify.type + fave_sugg[:music_embed] = spotify.uri + fave_sugg[:music_url] = spotify.external_urls["spotify"] + + if spotify.type == "artist" + fave_sugg[:music_artist] = nil + else + fave_sugg[:music_artist] = spotify.artists[0].name + end + + if spotify.type == "album" + fave_sugg[:music_image] = spotify.images[2]["url"] + elsif spotify.type == "artist" + fave_sugg[:music_image] = "http://www.shootersconnectionstore.com/App_Themes/SC_Responsive/Images/no-thumbnail-available.png" + elsif spotify.type == "track" + fave_sugg[:music_image] = spotify.album.images[2]["url"] + end + + @your_favorites << fave_sugg + end + end + + def favorite + response = TunesTakeoutWrapper.create_favorites(current_user.uid, params[:suggestion_id]) + if response.code == 201 + flash[:yay] = "New Favorite Saved" + else + flash[:nope] = "Something Went Wrong" + end + redirect_to users_path + end + + def destroy + response = TunesTakeoutWrapper.delete_favorites(current_user.uid, params[:suggestion_id]) + if response.code == 204 + flash[:yay] = "Favorite Deleted #{response.code}" + else + flash[:nope] = "Something Went Wrong #{response.code}" + end + redirect_to users_path + end + + def show + + end +end diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb new file mode 100644 index 0000000..23de56a --- /dev/null +++ b/app/helpers/home_helper.rb @@ -0,0 +1,2 @@ +module HomeHelper +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb new file mode 100644 index 0000000..309f8b2 --- /dev/null +++ b/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/app/helpers/suggestions_helper.rb b/app/helpers/suggestions_helper.rb new file mode 100644 index 0000000..0e358dd --- /dev/null +++ b/app/helpers/suggestions_helper.rb @@ -0,0 +1,2 @@ +module SuggestionsHelper +end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb new file mode 100644 index 0000000..2310a24 --- /dev/null +++ b/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +end diff --git a/app/models/food.rb b/app/models/food.rb new file mode 100644 index 0000000..8d84513 --- /dev/null +++ b/app/models/food.rb @@ -0,0 +1,7 @@ +require 'yelp' + +class Food #< ActiveRecord::Base + def self.yelp_find(business) + Yelp.client.business(business) + end +end diff --git a/app/models/music.rb b/app/models/music.rb new file mode 100644 index 0000000..dcab528 --- /dev/null +++ b/app/models/music.rb @@ -0,0 +1,13 @@ +require 'rspotify' + +class Music #< ActiveRecord::Base + def self.spotify_find(type, id) + if type == "album" + RSpotify::Album.find(id) + elsif type == "artist" + RSpotify::Artist.find(id) + elsif type == "track" + RSpotify::Track.find(id) + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..b8949f1 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,23 @@ +class User < ActiveRecord::Base + validates :name, :uid, :provider, presence: true + + def self.find_or_create_from_omniauth(auth_hash) + user = self.find_by(uid: auth_hash["uid"], provider: auth_hash["provider"]) + if !user.nil? + return user + else + user = User.new + user.uid = auth_hash["uid"] + user.provider = auth_hash["provider"] + user.name = auth_hash["info"]["name"] + user.image_url = auth_hash["info"]["image"] + + if user.save + return user + else + return nil + end + + end + end +end diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb new file mode 100644 index 0000000..bc613ae --- /dev/null +++ b/app/views/home/index.html.erb @@ -0,0 +1,7 @@ +

Top Suggestions

+ +
+ <% @top_favorites.each do |top_favorite| %> + <%= render partial: "shared/suggestions", locals: { partial_variable: top_favorite, delete_button: false } %> + <% end %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 509d1a2..523ee3b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,14 +1,55 @@ - - TunesTakeout - <%= stylesheet_link_tag 'application', media: 'all' %> - <%= javascript_include_tag 'application' %> - <%= csrf_meta_tags %> - - + + TunesTakeout + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> + <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> -<%= yield %> + - + + + +
+
+

Tunes and Takeout

+

+ Rock out, while you eat out! +

+
+ + <% if !flash.empty? %> +
+ <% flash.each do |key, msg| %> + <%= content_tag :div, msg, :id => key %> + <% end %> +
+ <% end %> + + <%= yield %> + +
+ diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb new file mode 100644 index 0000000..497ef97 --- /dev/null +++ b/app/views/sessions/new.html.erb @@ -0,0 +1 @@ +Sign in with Spotify diff --git a/app/views/shared/_suggestions.html.erb b/app/views/shared/_suggestions.html.erb new file mode 100644 index 0000000..8c324a2 --- /dev/null +++ b/app/views/shared/_suggestions.html.erb @@ -0,0 +1,52 @@ + +
+
+ <%= link_to(image_tag(partial_variable[:business_image], alt: "#{partial_variable[:business_image]} food picture", class: "thumbnail"), partial_variable[:business_url], target: '_blank') %> +
+

<%= partial_variable[:business_name] %>

+
+

+ <%= image_tag(partial_variable[:business_rating_image], alt: "rating image") %> +

+ <%= number_to_phone(partial_variable[:business_phone], area_code: true) %> +

+ You should listen to +

+ <%= link_to(partial_variable[:music_name], partial_variable[:music_url], target: '_blank') %> +

+

+ while you eat here! +

+

+ Artist: + <% if partial_variable[:music_type] == "artist" %> + <%= partial_variable[:music_name] %> + <% else %> + <%= partial_variable[:music_artist] %> + <% end %> +

+

+ Type: <%= (partial_variable[:music_type]).titleize %> +

+ <%#= link_to(image_tag(partial_variable[:music_image], width: "64", height: "64"), partial_variable[:music_url], target: '_blank') %> +

+ +

+ +

+ +
+ <% if !current_user.nil? %> + <% if delete_button %> + <%= button_to favorites_path(partial_variable[:suggestion_id]), :method => :delete, data: {confirm: "Are you sure?"}, class: "btn btn-default" do %> + + <% end %> + <% else %> + <%= button_to favorite_path(partial_variable[:suggestion_id]), form: { "data-type" => "json"}, class: "btn btn-default" do %> + + <% end %> + <% end %> + <% end %> +
+
+
diff --git a/app/views/suggestions/index.html.erb b/app/views/suggestions/index.html.erb new file mode 100644 index 0000000..7efc124 --- /dev/null +++ b/app/views/suggestions/index.html.erb @@ -0,0 +1,19 @@ +<%= form_tag suggestions_path, method: :get do %> + <%= label_tag :query, "Food Craving" %> + <%= text_field_tag :query, '', :required => true %> + + <%= label_tag :limit %> + <%= number_field_tag :limit, '', :required => true, min: 1, max: 100 %> + + <%= submit_tag %> +<% end %> + +
+ +
+ <% if @suggestions %> + <% @suggestions.each do |suggestion| %> + <%= render partial: "shared/suggestions", locals: { partial_variable: suggestion, delete_button: false } %> + <% end %> + <% end %> +
diff --git a/app/views/users/favorite.html.erb b/app/views/users/favorite.html.erb new file mode 100644 index 0000000..23c8f25 --- /dev/null +++ b/app/views/users/favorite.html.erb @@ -0,0 +1,4 @@ +

You've Just Added to Your Favorites!

+ +You've Just Added +<%= params[:suggestion] %> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000..dc77b28 --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,9 @@ +

Your Favorite Places to Eat and Accompanying Music

+ +
+ <% if @your_favorites %> + <% @your_favorites.each do |your_favorite| %> + <%= render partial: "shared/suggestions", locals: { partial_variable: your_favorite, delete_button: true } %> + <% end %> + <% end %> +
diff --git a/config/application.rb b/config/application.rb index 9b37a86..88fc9b7 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,8 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' +# require 'yelp' +# require 'rspotify' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. @@ -8,19 +10,10 @@ module TunesTakeout class Application < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' + config.autoload_paths += %W(#{config.root}/lib) + config.autoload_paths += %W(#{config.root}/extras) - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de - - # Do not swallow errors in after_commit/after_rollback callbacks. config.active_record.raise_in_transactional_callbacks = true end end diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 0000000..023c922 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,5 @@ +# require 'omniauth-spotify' +# config/initializers/omniauth.rb +Rails.application.config.middleware.use OmniAuth::Builder do + provider :spotify, ENV["SPOTIFY_CLIENT_ID"], ENV["SPOTIFY_CLIENT_SECRET"] +end diff --git a/config/initializers/yelp.rb b/config/initializers/yelp.rb new file mode 100644 index 0000000..609fc99 --- /dev/null +++ b/config/initializers/yelp.rb @@ -0,0 +1,6 @@ +Yelp.client.configure do |config| + config.consumer_key = ENV["YELP_CONSUMER_KEY"] + config.consumer_secret = ENV["YELP_CONSUMER_SECRET"] + config.token = ENV["YELP_TOKEN"] + config.token_secret = ENV["YELP_TOKEN_SECRET"] +end diff --git a/config/routes.rb b/config/routes.rb index 3f66539..c2424a5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,56 +1,13 @@ Rails.application.routes.draw do - # The priority is based upon order of creation: first created -> highest priority. - # See how all your routes lay out with "rake routes". + root "home#index" - # You can have the root of your site routed with "root" - # root 'welcome#index' + resources :users, :only => [:show, :index] + resources :suggestions, :only => [:index] - # Example of regular route: - # get 'products/:id' => 'catalog#view' + post "users/favorites/:suggestion_id" => "users#favorite", as: :favorite + delete "users/favorites/:suggestion_id" => "users#destroy", as: :favorites - # Example of named route that can be invoked with purchase_url(id: product.id) - # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase + get "/auth/spotify/callback" => "sessions#create" + delete "/logout" => "sessions#destroy" - # Example resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Example resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Example resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Example resource route with more complex sub-resources: - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', on: :collection - # end - # end - - # Example resource route with concerns: - # concern :toggleable do - # post 'toggle' - # end - # resources :posts, concerns: :toggleable - # resources :photos, concerns: :toggleable - - # Example resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end end diff --git a/db/migrate/20160517175357_create_users.rb b/db/migrate/20160517175357_create_users.rb new file mode 100644 index 0000000..9f20750 --- /dev/null +++ b/db/migrate/20160517175357_create_users.rb @@ -0,0 +1,11 @@ +class CreateUsers < ActiveRecord::Migration + def change + create_table :users do |t| + t.string :provider, default: "spotify", null: false + t.string :uid, null: false + t.string :name + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20160518164423_update_users_table_add_images.rb b/db/migrate/20160518164423_update_users_table_add_images.rb new file mode 100644 index 0000000..8aba8d1 --- /dev/null +++ b/db/migrate/20160518164423_update_users_table_add_images.rb @@ -0,0 +1,5 @@ +class UpdateUsersTableAddImages < ActiveRecord::Migration + def change + add_column :users, :image_url, :string + end +end diff --git a/db/migrate/20160518193216_change_default_url_users.rb b/db/migrate/20160518193216_change_default_url_users.rb new file mode 100644 index 0000000..49b32a8 --- /dev/null +++ b/db/migrate/20160518193216_change_default_url_users.rb @@ -0,0 +1,5 @@ +class ChangeDefaultUrlUsers < ActiveRecord::Migration + def change + change_column :users, :image_url, :string, default: "http://www.hiapphere.com/data/icon/201312/HiAppHere_com_com.spotify.mobile.android.ui.png" + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000..6df4c0e --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,45 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 20160518193216) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "foods", force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "musics", force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "suggestions", force: :cascade do |t| + t.string "suggestion_id" + t.string "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "users", force: :cascade do |t| + t.string "provider", default: "spotify", null: false + t.string "uid", null: false + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "image_url", default: "http://www.hiapphere.com/data/icon/201312/HiAppHere_com_com.spotify.mobile.android.ui.png" + end + +end diff --git a/lib/tunes_takeout.rb b/lib/tunes_takeout.rb new file mode 100644 index 0000000..78f6632 --- /dev/null +++ b/lib/tunes_takeout.rb @@ -0,0 +1,33 @@ +require 'httparty' +# require 'yelp' +# require 'rspotify' + +module TunesTakeoutWrapper + BASE_URL = "https://tunes-takeout-api.herokuapp.com/" + + def self.spotify_search(query, limit = 10) + HTTParty.get(BASE_URL + "v1/suggestions/search?query=#{query}&limit=#{limit}").parsed_response + end + + def self.favorites(user_id) + HTTParty.get(BASE_URL + "/v1/users/#{user_id}/favorites").parsed_response + end + + def self.create_favorites(user_id, suggestion_id) + response = HTTParty.post(BASE_URL + "/v1/users/#{user_id}/favorites", :body => { :suggestion => suggestion_id }.to_json, :headers => { 'Content-Type' => 'application/json' }) + return response + end + + def self.delete_favorites(user_id, suggestion_id) + response = HTTParty.delete(BASE_URL + "/v1/users/#{user_id}/favorites", :body => { :suggestion => suggestion_id }.to_json, :headers => { 'Content-Type' => 'application/json' }) + return response + end + + def self.top_suggest(limit = 10) + HTTParty.get(BASE_URL + "v1/suggestions/top?limit=#{limit}").parsed_response + end + + def self.find_suggest(suggestion_id) + HTTParty.get(BASE_URL + "v1/suggestions/#{suggestion_id}").parsed_response + end +end diff --git a/test/cassettes/Food/Knows_various_attributes.yml b/test/cassettes/Food/Knows_various_attributes.yml new file mode 100644 index 0000000..25c918d --- /dev/null +++ b/test/cassettes/Food/Knows_various_attributes.yml @@ -0,0 +1,89 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.yelp.com/v2/business/india-bistro-seattle + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - Faraday v0.9.2 + Authorization: + - OAuth oauth_consumer_key="DOZfhe1yESBrcYsFC_c53g", oauth_nonce="44f255003b6c506b60572d1c5f6a657e", + oauth_signature="jeTuSaWHTh0QQiHQPEViBGrWwlA%3D", oauth_signature_method="HMAC-SHA1", + oauth_timestamp="1463967058", oauth_token="-1E4rzH9gpDSawEw2r__LDIUlg04SqWq", + oauth_version="1.0" + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 23 May 2016 01:30:59 GMT + Content-Type: + - application/json; charset=UTF-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Set-Cookie: + - __cfduid=dab968353636eca73d2dba5de4a5f35a41463967059; expires=Tue, 23-May-17 + 01:30:59 GMT; path=/; domain=.yelp.com; HttpOnly + - bse=f94dcf01013d1838bb45ff7ce987a4af; Domain=.yelp.com; Path=/; HttpOnly + - yuv=VjPpd-t7Hy2DvptDaGD8iLMM4ovKSco_O2MFyqRM9o1598U7MVipVB4ZeVtmmq1_f_N8a3MTqsMUu0zP1AZOXld258L2-xw2; + Domain=.yelp.com; Max-Age=630720000; Path=/; expires=Sun, 18-May-2036 01:30:59 + GMT + X-Node: + - api_com + - web63-r7-sfo2 + Cache-Control: + - max-age=0, must-revalidate, no-cache, no-store, private + Expires: + - Mon, 23 May 2016 01:30:59 GMT + Pragma: + - no-cache + Vary: + - Accept-Encoding,User-Agent + X-Mode: + - ro + X-Proxied: + - extlb7-r10-sfo2 + Server: + - cloudflare-nginx + Cf-Ray: + - 2a74bee9c5fb1bd9-SEA + body: + encoding: ASCII-8BIT + string: '{"is_claimed": true, "rating": 3.5, "mobile_url": "http://m.yelp.com/biz/india-bistro-seattle?utm_campaign=yelp_api\u0026utm_medium=api_v2_business\u0026utm_source=DOZfhe1yESBrcYsFC_c53g", + "rating_img_url": "https://s3-media1.fl.yelpcdn.com/assets/2/www/img/5ef3eb3cb162/ico/stars/v1/stars_3_half.png", + "review_count": 267, "name": "India Bistro", "rating_img_url_small": "https://s3-media1.fl.yelpcdn.com/assets/2/www/img/2e909d5d3536/ico/stars/v1/stars_small_3_half.png", + "url": "http://www.yelp.com/biz/india-bistro-seattle?utm_campaign=yelp_api\u0026utm_medium=api_v2_business\u0026utm_source=DOZfhe1yESBrcYsFC_c53g", + "categories": [["Indian", "indpak"], ["Buffets", "buffets"]], "menu_date_updated": + 1455157947, "reviews": [{"rating": 4, "excerpt": "Ate dinner here last night. + Enjoyed the murg masala and the chicken coconut curry was delicious!\n\nDon''t + miss the garlic naan. Huge piece and I wish I had...", "time_created": 1458923372, + "rating_image_url": "https://s3-media4.fl.yelpcdn.com/assets/2/www/img/c2f3dd9799a5/ico/stars/v1/stars_4.png", + "rating_image_small_url": "https://s3-media4.fl.yelpcdn.com/assets/2/www/img/f62a5be2f902/ico/stars/v1/stars_small_4.png", + "user": {"image_url": "http://s3-media1.fl.yelpcdn.com/photo/w58cMKJawxivNw8nmeKMRA/ms.jpg", + "id": "6Xv5PcR-yAatNNOahI0gNw", "name": "Sarah F."}, "rating_image_large_url": + "https://s3-media2.fl.yelpcdn.com/assets/2/www/img/ccf2b76faa2c/ico/stars/v1/stars_large_4.png", + "id": "EPBXa3ijwAaWlO87E91A2A"}], "phone": "2067835080", "snippet_text": "Ate + dinner here last night. Enjoyed the murg masala and the chicken coconut curry + was delicious!\n\nDon''t miss the garlic naan. Huge piece and I wish I had...", + "image_url": "https://s3-media2.fl.yelpcdn.com/bphoto/zr-A22q08n2GYI1CGW7yBQ/ms.jpg", + "snippet_image_url": "http://s3-media1.fl.yelpcdn.com/photo/w58cMKJawxivNw8nmeKMRA/ms.jpg", + "display_phone": "+1-206-783-5080", "rating_img_url_large": "https://s3-media3.fl.yelpcdn.com/assets/2/www/img/bd9b7a815d1b/ico/stars/v1/stars_large_3_half.png", + "menu_provider": "eat24", "id": "india-bistro-seattle", "is_closed": false, + "location": {"cross_streets": "N Ballard Ave \u0026 N 24th Ave", "city": "Seattle", + "display_address": ["2301 NW Market St", "Ballard", "Seattle, WA 98107"], + "geo_accuracy": 9.5, "neighborhoods": ["Ballard"], "postal_code": "98107", + "country_code": "US", "address": ["2301 NW Market St"], "coordinate": {"latitude": + 47.6684978107312, "longitude": -122.386471302877}, "state_code": "WA"}}' + http_version: + recorded_at: Mon, 23 May 2016 01:30:59 GMT +recorded_with: VCR 3.0.3 diff --git a/test/cassettes/Music/Knows_various_album_attributes.yml b/test/cassettes/Music/Knows_various_album_attributes.yml new file mode 100644 index 0000000..4261784 --- /dev/null +++ b/test/cassettes/Music/Knows_various_album_attributes.yml @@ -0,0 +1,232 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.spotify.com/v1/tracks/0fDFzVTG8c2fW9EM5f1RHM + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:31:59 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAOxVyXLaQBC95ytUOjvWaJe42YCBBDAxeIlTKWo0GpmJkZC1 + eC3/e6QngY0DDqkccsnlldTdev2mp7v19EGSZDr38lCWGtJT8bZ8n2YPMS+N + tXuv9t1SMafenE9DmlzzLC1DvknywYm8V+ApcFLiYRt4DIT3sFNi8wDYB8Lb + hLf5FXhZYuszEN4WeNpNIJ7HZyUe9YD4tlMh8naHQDB0oac3BuLbHmL6YOhX + z4gZIPsAlsFFiUMoHELPELmG0DOC/hHiR+AcdYGIH4FhjJOOoaGN7GNENhE5 + OQdC8yl4ThHTOUT1WlCFjAOcuteSpe91/fl9xpOIzqd5Mk9f7qzwpPEiE8ED + rmyWZXHaUJRFzKP92rHPFqGCu1TUtGt61/6nNklviP4jGh4fJX4gg+m5TjRL + eLDGRWOxRnWrVmzpNrqaSPig+U1QSK943UurE824uJplpdEyyN7SWhx8TVeh + ivlRIUkBiaL7tucHjFgGs4pnylQ18JljMN2mph4EhmMHjsuYvGK8E342q9PU + NdgkQie7i3A0lxuM+czlmmkGLiWOY3mOYRGqEo1qvqNbmu9aG0QUad4RYRm7 + a3BVi9uaagQO16lhE0elNrVczTFV0/KIplue5Xn2xkJUElZtF9GwWgZfchpl + eSj1OY2Xl7d5U+SJgLHumQacje2th8aTaZKJNFvrhL/ueVAqpk7Eg955PJ7c + nHO33+biMi82zJ83faVwG996178ftKpqKw+9hdQp1qk0oP6vdUXKrYWFt7H9 + fPU1/t/d/3J3y75I2TQqLponZd3VypgnNBOLaBriMjRVtx0LHn4fzwUTGPqA + zlNeW+tREP6rSZBFmrBqPAejzxeqrmqq474M1ZYB2m18soSya4UEraPHs0nH + YVpw7rYHZqCedAcvKXaZHDCl26hAU4/NeyGroelFvqCRdLRYVBMjx4s4n9NE + ZDiRSSpjwm8Fv5u+3ZbxaluGsf6xjlKKHRkY1DadYj1qKqGu6To6Ycw1OXE9 + 4hVbPKBMq34eMg706k61yrocW7iryLczC1djW1GffwIAAP//AwB63aiglwkA + AA== + http_version: + recorded_at: Mon, 23 May 2016 01:31:59 GMT +- request: + method: get + uri: https://api.spotify.com/v1/albums/1OYLLmDS0pJVFRbUo19vrG + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:31:59 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAOybW2/iyBKA3+dXWDzsRcosfW93pNVRJmRynzAh96NV1O3u + Dp6A7TGGhFnNfz/GEOcCNjlmxcPCSwjd5ap2VX3VLmP//cFxarKj+t3bZBiZ + mrM5+VrbyGbixO8lvdHwf52/05F0zDwmJg5k57Yfd7KZ8Xg604vCxLfDTEk7 + SaLeZr0eRib4YzLxhxd262OVdbT9eNTkRHT7EQ68Znx1tx0MzmuZqp8bY0vt + 2NhXymTkv9I1gBN1vSJ9E02+zvSUCwWyO3bAXr+rOsZp+uZp6tk3mbmn4X7s + Z6OTNW2OZzeLz+2n89fYrwPpd2Rq5LYr43vz5OHa9lZtw6kdX43+nrdqE2kv + jIaxf9d+E4gkjURm/rft3x0oOHG2fjl2To0Xxro3tfLtzP7G9MHNdxzcfLn4 + PAF8/SL+tX7kZbIAMIAo4ZhjhMTY6ofivHln1oxysg5Pro+Ouo0WiA4uPp+q + 8xCKQbz7bOLOBLGZOGm81nel0Eh3r0h5pmaSP6UiXXlnXgeobUZBGw0xAvKU + 6bxaT7oaTwfpUuqZgrrHsSbAU0BB4TLDkEWuEpRJphCHBDBKMHZRnpkPvk7a + ExOvAvxsHIP3GicaMtfFTCCqhGssJkhBCaSSnGFkpDEEYWDxlPHURIFxRt5p + WykmPG2lBzAnDApDFUZaWmIMtVa4gFPuSY/NOPEXuZkzfNbuB9rEKnwchycK + o35Hxn6SJRqC2WBsOkb2zK2WyfioEQi1qanbKDae3/PDIBMaGhmPhZJYevcv + c3nhdKuPVf4ntLZnkj/BLx2/6yd/UpBXssR0X2XZ7CpdXqn/0Wr9omL/s1X7 + 3ZV7TvUuqeDVqnh2xuOEG/v//6nm2RHa73m3QbpQE49k4fNEP5ZJmmi34yAj + ISBG+ax5jDq+52dgWdnpmRczhaF+X6CzvKsDeHIa4sPm5xO47Xk7e59u7Fb8 + fM65uffEeJzJRSpzVZMAzxMrAjubTPkc+Obh9m2NifIa043wx4lUHSmjcFpc + XIKh9ChTUguPcyq5tRpQawSE1NXgWX92KjPjladVJvJ8xNucyqY3y9ybF881 + 0P9ioCFmjC4RaB6JU3jR8nsX4prAo+TSvTukfCGgC1S+BXqeWB7e3TgMB37w + q3PpJ23nwPT6vapkA5FeqcD0qskKSDwsUs4JRdxI6EHCXYyYcIV0WTHZqCLZ + ZX5ek70KZCOMwDLJxqTRuvpxf3Nj8PA6anfvGjF1Dxciu0DlW7LnieXh3Xe2 + ZfBr4rQSGWjnrG2cU+kHVeEWgnABMLTp3s1F1hYoQr3U78wTStlRuwQxwcVw + 44pwl7l6DfdKwJ22vYgtD2765VN//+vuPuPtg0HrvnfhGzbUC8FdoPIt3PPE + 8vBuBYF0ftsNnbPQ2fO7v1fesw3S2sPAAo4Q1FICD5N0n8aSc53u2Vpijakr + irEmFbEuc/Ia61XAGjJGlrlng73OiR+3zrn6AsHOEO58T+Seu1h7PVvlVHs9 + RywP75fQuZTDqjBbQLhCQDKpOdSu5RAQ5FEDXNdIizlgiCENYTHMtGprXeLa + NcyrAbNwuVgizGzgnZ3pk+4j3v024MNm/PCDosVgnq1yCuY5Ynl4T43sdIbj + xnqr41feotMdWXKhUoQt4kwxzij30v+kEkhZoCVXmogSqllVqkt8vKZ6Jajm + HC/zDjg6Of0K+0hx4Z0Hvv0W7O2dtq4XorpA5Vuq54nl4W2Eo6b6Mozj4Ybz + yTh7Mooq79iGeEa7wiLrKqVN2ktblDbSLtUAUqa50EBYxVAx27wi22WeXrO9 + EmwzutSuGtIj3b0cJFcH/iHv4wM7ONp/HC7EdoHKt2zPE3u+/PYDkww/jj6c + ZtgPdOV74VpxJbh0tQKMpG21QohxY/ToXhlK+x4JAWaKmmKw3Ypgl7l5DfYq + gI1QeiW+xEtx+ijAwePudWP/+EJJ+u07v2xIttjtstkqp26XzRHLw7szMPHQ + afnBXRrkRvUOW1BgoMLCcznhAEEhBTEeMkBQaFD6RWKPMl7y47WoiHWZk9dY + rwTWDIllYg0Oro8VpPuDvvr8A+7fHEmyvdNcrMOerXKqw54j9vJ22XEYmKHT + CB8q/7KFJZUyRde6EpH0WtuVymWulMh6AhPCXSZdj5cxDUHVBrvExWuoVwJq + SDhZ5k9b3RZ2v1+1701wd3lqHjx4Pjz8sthePVvl1F49R+y5wY59mzhbD9V3 + aYoQhxhjqTkljEPIraREWaVcArQSRLueTedLiK76jFmZf9dErwTRnAC2zLaa + tFT0ddgayBu43Rhckx9Nii8Xa6tnq5xqq+eI5eE9aTtH8mPDfGzIqki7FgFI + RHrVLThjFioPU09aV3AkGRfMGpcKDcs26aoPl5U5OE+pWvak+Oho+vS4fzB5 + xyPodzqTofFz5aPBJ6Hs/MJ+741gEiayM171h6fXK2a9ITTFwWhqs+hFjZ// + AwAA//8DAJ35z7pwNAAA + http_version: + recorded_at: Mon, 23 May 2016 01:31:59 GMT +- request: + method: get + uri: https://api.spotify.com/v1/artists/0cOpQTKJdCEzz2wplnnyP6 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:31:59 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAIySS08DIRSF9/6KyaybzpuBLjVuNEZNujPGMDw6JBQIw1jb + pv9dhpkam1rTsOLAPd/hcvc3URSzL8eswvKjt7KLo0W096rXO6Od4NtBiVvn + TLdIEm2Ymk8Hc6LXCbZOdC5JybN5XT4+0Lv73S7fGKnU9gXE3ugwGxhcS6k3 + zP72by3jw1b1Us5GyWmH5aBlP5UrpiwLZW/Re1COdT+hsBEnmT6zKVZ3KVfw + ETS4/HtljVdH+DE1E6vWDRIo0ym2b9xJIB+HUOWzJMEgYYzAmpMM4SKlsGFV + A2nVVBDhiiJECSAoRRVs4slvI6hrJ0RoxDm8SK+FIw5oTVPAK8g5LvOSlFmG + cUZrDOq8zEqOSUFofQb3iAtwUF7JLpuMAlQjCAtEClBQAitMKkLyIYfPhWqW + FpT/8fABPX24wmsWME+i09EtVn5FSyv0+ElGm15iK1wY1dCW2G3NWDIOwnix + tyJo06wsxrPFpdk9fAMAAP//AwBXgrNaHgMAAA== + http_version: + recorded_at: Mon, 23 May 2016 01:31:59 GMT +recorded_with: VCR 3.0.3 diff --git a/test/cassettes/Music/Knows_various_artist_attributes.yml b/test/cassettes/Music/Knows_various_artist_attributes.yml new file mode 100644 index 0000000..a014481 --- /dev/null +++ b/test/cassettes/Music/Knows_various_artist_attributes.yml @@ -0,0 +1,232 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.spotify.com/v1/tracks/0fDFzVTG8c2fW9EM5f1RHM + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:32:00 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAOxVyXLaQBC95ytUOjvWaJe42YCBBDAxeIlTKWo0GpmJkZC1 + eC3/e6QngY0DDqkccsnlldTdev2mp7v19EGSZDr38lCWGtJT8bZ8n2YPMS+N + tXuv9t1SMafenE9DmlzzLC1DvknywYm8V+ApcFLiYRt4DIT3sFNi8wDYB8Lb + hLf5FXhZYuszEN4WeNpNIJ7HZyUe9YD4tlMh8naHQDB0oac3BuLbHmL6YOhX + z4gZIPsAlsFFiUMoHELPELmG0DOC/hHiR+AcdYGIH4FhjJOOoaGN7GNENhE5 + OQdC8yl4ThHTOUT1WlCFjAOcuteSpe91/fl9xpOIzqd5Mk9f7qzwpPEiE8ED + rmyWZXHaUJRFzKP92rHPFqGCu1TUtGt61/6nNklviP4jGh4fJX4gg+m5TjRL + eLDGRWOxRnWrVmzpNrqaSPig+U1QSK943UurE824uJplpdEyyN7SWhx8TVeh + ivlRIUkBiaL7tucHjFgGs4pnylQ18JljMN2mph4EhmMHjsuYvGK8E342q9PU + NdgkQie7i3A0lxuM+czlmmkGLiWOY3mOYRGqEo1qvqNbmu9aG0QUad4RYRm7 + a3BVi9uaagQO16lhE0elNrVczTFV0/KIplue5Xn2xkJUElZtF9GwWgZfchpl + eSj1OY2Xl7d5U+SJgLHumQacje2th8aTaZKJNFvrhL/ueVAqpk7Eg955PJ7c + nHO33+biMi82zJ83faVwG996178ftKpqKw+9hdQp1qk0oP6vdUXKrYWFt7H9 + fPU1/t/d/3J3y75I2TQqLponZd3VypgnNBOLaBriMjRVtx0LHn4fzwUTGPqA + zlNeW+tREP6rSZBFmrBqPAejzxeqrmqq474M1ZYB2m18soSya4UEraPHs0nH + YVpw7rYHZqCedAcvKXaZHDCl26hAU4/NeyGroelFvqCRdLRYVBMjx4s4n9NE + ZDiRSSpjwm8Fv5u+3ZbxaluGsf6xjlKKHRkY1DadYj1qKqGu6To6Ycw1OXE9 + 4hVbPKBMq34eMg706k61yrocW7iryLczC1djW1GffwIAAP//AwB63aiglwkA + AA== + http_version: + recorded_at: Mon, 23 May 2016 01:32:00 GMT +- request: + method: get + uri: https://api.spotify.com/v1/albums/1OYLLmDS0pJVFRbUo19vrG + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:32:00 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + 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 + AwAA//8DAJ35z7pwNAAA + http_version: + recorded_at: Mon, 23 May 2016 01:32:00 GMT +- request: + method: get + uri: https://api.spotify.com/v1/artists/0cOpQTKJdCEzz2wplnnyP6 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:32:00 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAIySS08DIRSF9/6KyaybzpuBLjVuNEZNujPGMDw6JBQIw1jb + pv9dhpkam1rTsOLAPd/hcvc3URSzL8eswvKjt7KLo0W096rXO6Od4NtBiVvn + TLdIEm2Ymk8Hc6LXCbZOdC5JybN5XT4+0Lv73S7fGKnU9gXE3ugwGxhcS6k3 + zP72by3jw1b1Us5GyWmH5aBlP5UrpiwLZW/Re1COdT+hsBEnmT6zKVZ3KVfw + ETS4/HtljVdH+DE1E6vWDRIo0ym2b9xJIB+HUOWzJMEgYYzAmpMM4SKlsGFV + A2nVVBDhiiJECSAoRRVs4slvI6hrJ0RoxDm8SK+FIw5oTVPAK8g5LvOSlFmG + cUZrDOq8zEqOSUFofQb3iAtwUF7JLpuMAlQjCAtEClBQAitMKkLyIYfPhWqW + FpT/8fABPX24wmsWME+i09EtVn5FSyv0+ElGm15iK1wY1dCW2G3NWDIOwnix + tyJo06wsxrPFpdk9fAMAAP//AwBXgrNaHgMAAA== + http_version: + recorded_at: Mon, 23 May 2016 01:32:00 GMT +recorded_with: VCR 3.0.3 diff --git a/test/cassettes/Music/Knows_various_track_attributes.yml b/test/cassettes/Music/Knows_various_track_attributes.yml new file mode 100644 index 0000000..9dbac3f --- /dev/null +++ b/test/cassettes/Music/Knows_various_track_attributes.yml @@ -0,0 +1,232 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.spotify.com/v1/tracks/0fDFzVTG8c2fW9EM5f1RHM + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:31:57 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAOxVyXLaQBC95ytUOjvWaJe42YCBBDAxeIlTKWo0GpmJkZC1 + eC3/e6QngY0DDqkccsnlldTdev2mp7v19EGSZDr38lCWGtJT8bZ8n2YPMS+N + tXuv9t1SMafenE9DmlzzLC1DvknywYm8V+ApcFLiYRt4DIT3sFNi8wDYB8Lb + hLf5FXhZYuszEN4WeNpNIJ7HZyUe9YD4tlMh8naHQDB0oac3BuLbHmL6YOhX + z4gZIPsAlsFFiUMoHELPELmG0DOC/hHiR+AcdYGIH4FhjJOOoaGN7GNENhE5 + OQdC8yl4ThHTOUT1WlCFjAOcuteSpe91/fl9xpOIzqd5Mk9f7qzwpPEiE8ED + rmyWZXHaUJRFzKP92rHPFqGCu1TUtGt61/6nNklviP4jGh4fJX4gg+m5TjRL + eLDGRWOxRnWrVmzpNrqaSPig+U1QSK943UurE824uJplpdEyyN7SWhx8TVeh + ivlRIUkBiaL7tucHjFgGs4pnylQ18JljMN2mph4EhmMHjsuYvGK8E342q9PU + NdgkQie7i3A0lxuM+czlmmkGLiWOY3mOYRGqEo1qvqNbmu9aG0QUad4RYRm7 + a3BVi9uaagQO16lhE0elNrVczTFV0/KIplue5Xn2xkJUElZtF9GwWgZfchpl + eSj1OY2Xl7d5U+SJgLHumQacje2th8aTaZKJNFvrhL/ueVAqpk7Eg955PJ7c + nHO33+biMi82zJ83faVwG996178ftKpqKw+9hdQp1qk0oP6vdUXKrYWFt7H9 + fPU1/t/d/3J3y75I2TQqLponZd3VypgnNBOLaBriMjRVtx0LHn4fzwUTGPqA + zlNeW+tREP6rSZBFmrBqPAejzxeqrmqq474M1ZYB2m18soSya4UEraPHs0nH + YVpw7rYHZqCedAcvKXaZHDCl26hAU4/NeyGroelFvqCRdLRYVBMjx4s4n9NE + ZDiRSSpjwm8Fv5u+3ZbxaluGsf6xjlKKHRkY1DadYj1qKqGu6To6Ycw1OXE9 + 4hVbPKBMq34eMg706k61yrocW7iryLczC1djW1GffwIAAP//AwB63aiglwkA + AA== + http_version: + recorded_at: Mon, 23 May 2016 01:31:57 GMT +- request: + method: get + uri: https://api.spotify.com/v1/albums/1OYLLmDS0pJVFRbUo19vrG + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:31:58 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAOybW2/iyBKA3+dXWDzsRcosfW93pNVRJmRynzAh96NV1O3u + Dp6A7TGGhFnNfz/GEOcCNjlmxcPCSwjd5ap2VX3VLmP//cFxarKj+t3bZBiZ + mrM5+VrbyGbixO8lvdHwf52/05F0zDwmJg5k57Yfd7KZ8Xg604vCxLfDTEk7 + SaLeZr0eRib4YzLxhxd262OVdbT9eNTkRHT7EQ68Znx1tx0MzmuZqp8bY0vt + 2NhXymTkv9I1gBN1vSJ9E02+zvSUCwWyO3bAXr+rOsZp+uZp6tk3mbmn4X7s + Z6OTNW2OZzeLz+2n89fYrwPpd2Rq5LYr43vz5OHa9lZtw6kdX43+nrdqE2kv + jIaxf9d+E4gkjURm/rft3x0oOHG2fjl2To0Xxro3tfLtzP7G9MHNdxzcfLn4 + PAF8/SL+tX7kZbIAMIAo4ZhjhMTY6ofivHln1oxysg5Pro+Ouo0WiA4uPp+q + 8xCKQbz7bOLOBLGZOGm81nel0Eh3r0h5pmaSP6UiXXlnXgeobUZBGw0xAvKU + 6bxaT7oaTwfpUuqZgrrHsSbAU0BB4TLDkEWuEpRJphCHBDBKMHZRnpkPvk7a + ExOvAvxsHIP3GicaMtfFTCCqhGssJkhBCaSSnGFkpDEEYWDxlPHURIFxRt5p + WykmPG2lBzAnDApDFUZaWmIMtVa4gFPuSY/NOPEXuZkzfNbuB9rEKnwchycK + o35Hxn6SJRqC2WBsOkb2zK2WyfioEQi1qanbKDae3/PDIBMaGhmPhZJYevcv + c3nhdKuPVf4ntLZnkj/BLx2/6yd/UpBXssR0X2XZ7CpdXqn/0Wr9omL/s1X7 + 3ZV7TvUuqeDVqnh2xuOEG/v//6nm2RHa73m3QbpQE49k4fNEP5ZJmmi34yAj + ISBG+ax5jDq+52dgWdnpmRczhaF+X6CzvKsDeHIa4sPm5xO47Xk7e59u7Fb8 + fM65uffEeJzJRSpzVZMAzxMrAjubTPkc+Obh9m2NifIa043wx4lUHSmjcFpc + XIKh9ChTUguPcyq5tRpQawSE1NXgWX92KjPjladVJvJ8xNucyqY3y9ybF881 + 0P9ioCFmjC4RaB6JU3jR8nsX4prAo+TSvTukfCGgC1S+BXqeWB7e3TgMB37w + q3PpJ23nwPT6vapkA5FeqcD0qskKSDwsUs4JRdxI6EHCXYyYcIV0WTHZqCLZ + ZX5ek70KZCOMwDLJxqTRuvpxf3Nj8PA6anfvGjF1Dxciu0DlW7LnieXh3Xe2 + ZfBr4rQSGWjnrG2cU+kHVeEWgnABMLTp3s1F1hYoQr3U78wTStlRuwQxwcVw + 44pwl7l6DfdKwJ22vYgtD2765VN//+vuPuPtg0HrvnfhGzbUC8FdoPIt3PPE + 8vBuBYF0ftsNnbPQ2fO7v1fesw3S2sPAAo4Q1FICD5N0n8aSc53u2Vpijakr + irEmFbEuc/Ia61XAGjJGlrlng73OiR+3zrn6AsHOEO58T+Seu1h7PVvlVHs9 + RywP75fQuZTDqjBbQLhCQDKpOdSu5RAQ5FEDXNdIizlgiCENYTHMtGprXeLa + NcyrAbNwuVgizGzgnZ3pk+4j3v024MNm/PCDosVgnq1yCuY5Ynl4T43sdIbj + xnqr41feotMdWXKhUoQt4kwxzij30v+kEkhZoCVXmogSqllVqkt8vKZ6Jajm + HC/zDjg6Of0K+0hx4Z0Hvv0W7O2dtq4XorpA5Vuq54nl4W2Eo6b6Mozj4Ybz + yTh7Mooq79iGeEa7wiLrKqVN2ktblDbSLtUAUqa50EBYxVAx27wi22WeXrO9 + EmwzutSuGtIj3b0cJFcH/iHv4wM7ONp/HC7EdoHKt2zPE3u+/PYDkww/jj6c + ZtgPdOV74VpxJbh0tQKMpG21QohxY/ToXhlK+x4JAWaKmmKw3Ypgl7l5DfYq + gI1QeiW+xEtx+ijAwePudWP/+EJJ+u07v2xIttjtstkqp26XzRHLw7szMPHQ + afnBXRrkRvUOW1BgoMLCcznhAEEhBTEeMkBQaFD6RWKPMl7y47WoiHWZk9dY + rwTWDIllYg0Oro8VpPuDvvr8A+7fHEmyvdNcrMOerXKqw54j9vJ22XEYmKHT + CB8q/7KFJZUyRde6EpH0WtuVymWulMh6AhPCXSZdj5cxDUHVBrvExWuoVwJq + SDhZ5k9b3RZ2v1+1701wd3lqHjx4Pjz8sthePVvl1F49R+y5wY59mzhbD9V3 + aYoQhxhjqTkljEPIraREWaVcArQSRLueTedLiK76jFmZf9dErwTRnAC2zLaa + tFT0ddgayBu43Rhckx9Nii8Xa6tnq5xqq+eI5eE9aTtH8mPDfGzIqki7FgFI + RHrVLThjFioPU09aV3AkGRfMGpcKDcs26aoPl5U5OE+pWvak+Oho+vS4fzB5 + xyPodzqTofFz5aPBJ6Hs/MJ+741gEiayM171h6fXK2a9ITTFwWhqs+hFjZ// + AwAA//8DAJ35z7pwNAAA + http_version: + recorded_at: Mon, 23 May 2016 01:31:58 GMT +- request: + method: get + uri: https://api.spotify.com/v1/artists/0cOpQTKJdCEzz2wplnnyP6 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 23 May 2016 01:31:58 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Keep-Alive: + - timeout=600 + Cache-Control: + - public, max-age=7200 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - GET, POST, OPTIONS, PUT, DELETE + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Max-Age: + - '604800' + Access-Control-Allow-Headers: + - Accept, Authorization, Origin, Content-Type + Content-Encoding: + - gzip + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000; + body: + encoding: ASCII-8BIT + string: !binary |- + H4sIAAAAAAAAAIySS08DIRSF9/6KyaybzpuBLjVuNEZNujPGMDw6JBQIw1jb + pv9dhpkam1rTsOLAPd/hcvc3URSzL8eswvKjt7KLo0W096rXO6Od4NtBiVvn + TLdIEm2Ymk8Hc6LXCbZOdC5JybN5XT4+0Lv73S7fGKnU9gXE3ugwGxhcS6k3 + zP72by3jw1b1Us5GyWmH5aBlP5UrpiwLZW/Re1COdT+hsBEnmT6zKVZ3KVfw + ETS4/HtljVdH+DE1E6vWDRIo0ym2b9xJIB+HUOWzJMEgYYzAmpMM4SKlsGFV + A2nVVBDhiiJECSAoRRVs4slvI6hrJ0RoxDm8SK+FIw5oTVPAK8g5LvOSlFmG + cUZrDOq8zEqOSUFofQb3iAtwUF7JLpuMAlQjCAtEClBQAitMKkLyIYfPhWqW + FpT/8fABPX24wmsWME+i09EtVn5FSyv0+ElGm15iK1wY1dCW2G3NWDIOwnix + tyJo06wsxrPFpdk9fAMAAP//AwBXgrNaHgMAAA== + http_version: + recorded_at: Mon, 23 May 2016 01:31:59 GMT +recorded_with: VCR 3.0.3 diff --git a/test/controllers/home_controller_test.rb b/test/controllers/home_controller_test.rb new file mode 100644 index 0000000..0bc87d9 --- /dev/null +++ b/test/controllers/home_controller_test.rb @@ -0,0 +1,22 @@ +# require 'test_helper' +# +# class HomeControllerTest < ActionController::TestCase +# it "Should render home#index page", :vcr do +# get :index +# assert_response :success +# end +# end + +# describe "Food" do +# before do +# @food = Food.yelp_find("india-bistro-seattle") +# end +# +# it "Knows various attributes", :vcr do +# assert_equal @food.business.name, "India Bistro" +# assert_equal @food.business.phone, "2067835080" +# assert_equal @food.business.url, "http://www.yelp.com/biz/india-bistro-seattle?utm_campaign=yelp_api&utm_medium=api_v2_business&utm_source=DOZfhe1yESBrcYsFC_c53g" +# assert_equal @food.business.image_url, "https://s3-media2.fl.yelpcdn.com/bphoto/zr-A22q08n2GYI1CGW7yBQ/ms.jpg" +# assert_equal @food.business.rating_img_url, "https://s3-media1.fl.yelpcdn.com/assets/2/www/img/5ef3eb3cb162/ico/stars/v1/stars_3_half.png" +# end +# end diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 0000000..4ca3926 --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,8 @@ +# require 'test_helper' +# +# class SessionsControllerTest < ActionController::TestCase + # test "should go to home#index" do + # get :index + # end + +# end diff --git a/test/controllers/suggestions_controller_test.rb b/test/controllers/suggestions_controller_test.rb new file mode 100644 index 0000000..b248bbe --- /dev/null +++ b/test/controllers/suggestions_controller_test.rb @@ -0,0 +1,7 @@ +# require 'test_helper' +# +# class SuggestionsControllerTest < ActionController::TestCase +# # test "the truth" do +# # assert true +# # end +# end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb new file mode 100644 index 0000000..37cd41e --- /dev/null +++ b/test/controllers/users_controller_test.rb @@ -0,0 +1,7 @@ +# require 'test_helper' +# +# class UsersControllerTest < ActionController::TestCase +# # test "the truth" do +# # assert true +# # end +# end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000..c819726 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,10 @@ + +known_user: + provider: "spotify" + uid: "dri19tcc" + name: Adriana Cannon + +unknown_user: + provider: "spotify" + uid: "1226771573" + name: "Suzanne Convertino Harrison" diff --git a/test/models/food_test.rb b/test/models/food_test.rb new file mode 100644 index 0000000..6b19eef --- /dev/null +++ b/test/models/food_test.rb @@ -0,0 +1,18 @@ +require 'test_helper' + +class FoodTest < ActiveSupport::TestCase + + describe "Food" do + before do + @food = Food.yelp_find("india-bistro-seattle") + end + + it "Knows various attributes", :vcr do + assert_equal @food.business.name, "India Bistro" + assert_equal @food.business.phone, "2067835080" + assert_equal @food.business.url, "http://www.yelp.com/biz/india-bistro-seattle?utm_campaign=yelp_api&utm_medium=api_v2_business&utm_source=DOZfhe1yESBrcYsFC_c53g" + assert_equal @food.business.image_url, "https://s3-media2.fl.yelpcdn.com/bphoto/zr-A22q08n2GYI1CGW7yBQ/ms.jpg" + assert_equal @food.business.rating_img_url, "https://s3-media1.fl.yelpcdn.com/assets/2/www/img/5ef3eb3cb162/ico/stars/v1/stars_3_half.png" + end + end +end diff --git a/test/models/music_test.rb b/test/models/music_test.rb new file mode 100644 index 0000000..9364346 --- /dev/null +++ b/test/models/music_test.rb @@ -0,0 +1,32 @@ +require 'test_helper' + +class MusicTest < ActiveSupport::TestCase + describe "Music" do + before do + @music_track = Music.spotify_find("track", "0fDFzVTG8c2fW9EM5f1RHM") + @music_album = Music.spotify_find("album", "1OYLLmDS0pJVFRbUo19vrG") + @music_artist = Music.spotify_find("artist", "0cOpQTKJdCEzz2wplnnyP6") + end + + it "Knows various track attributes", :vcr do + assert_equal @music_track.name, "Indian Food" + assert_equal @music_track.type, "track" + assert_equal @music_track.uri, "spotify:track:0fDFzVTG8c2fW9EM5f1RHM" + assert_equal @music_track.external_urls["spotify"], "https://open.spotify.com/track/0fDFzVTG8c2fW9EM5f1RHM" + end + + it "Knows various album attributes", :vcr do + assert_equal @music_album.name, "Thunderbox" + assert_equal @music_album.type, "album" + assert_equal @music_album.uri, "spotify:album:1OYLLmDS0pJVFRbUo19vrG" + assert_equal @music_album.external_urls["spotify"], "https://open.spotify.com/album/1OYLLmDS0pJVFRbUo19vrG" + end + + it "Knows various artist attributes", :vcr do + assert_equal @music_artist.name, "Miso Banana Trio" + assert_equal @music_artist.type, "artist" + assert_equal @music_artist.uri, "spotify:artist:0cOpQTKJdCEzz2wplnnyP6" + assert_equal @music_artist.external_urls["spotify"], "https://open.spotify.com/artist/0cOpQTKJdCEzz2wplnnyP6" + end + end +end diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 0000000..3551aa5 --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,30 @@ +require 'test_helper' + +class UserTest < ActiveSupport::TestCase + def setup + # @known = OmniAuth.config.mock_auth[:spotify_known] + @known = users(:known_user) + @unknown = users(:unknown_user) + end + + test "can find an existing user given an oauth spotify hash" do + @auth_hash = {"info" => {"name" => "Adriana Cannon"}, "provider" => "spotify", "uid" => "dri19tcc"} + assert_equal @known, User.find_or_create_from_omniauth(@auth_hash) + end + + test "can make a new user given the oauth spotify hash of an unknown user" do + @auth_hash = {"info" => {"name" => "Chris Cannon"}, "provider" => "spotify", "uid" => "cannonc"} + assert_difference 'User.count', 1 do + @user = User.find_or_create_from_omniauth(@auth_hash) + end + end + + test "uses oauth data to set user name, provider and uid for new users" do + @auth_hash = {"info" => {"name" => "Suzanne Convertino Harrison"}, "provider" => "spotify", "uid" => "1226771573"} + user = User.find_or_create_from_omniauth(@auth_hash) + + assert_equal @unknown['name'], user.name + assert_equal @unknown['provider'], user.provider + assert_equal @unknown['uid'], user.uid + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 92e39b2..81cc548 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,10 +1,32 @@ +SimpleCov.start 'rails' + ENV['RAILS_ENV'] ||= 'test' + require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' +require 'minitest/spec' +require 'minispec-metadata' +require 'vcr' +require 'minitest-vcr' +require 'webmock/minitest' +require 'minitest/reporters' + +VCR.configure do |c| + c.cassette_library_dir = 'test/cassettes' + c.hook_into :webmock +end + +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new +MinitestVcr::Spec.configure! + class ActiveSupport::TestCase - # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. fixtures :all - # Add more helper methods to be used by all tests here... + OmniAuth.config.test_mode = true + OmniAuth.config.mock_auth[:spotify_known] = OmniAuth::AuthHash.new( { provider: 'spotify', info: { id: "known_user", display_name: "known user" } }) + + OmniAuth.config.mock_auth[:spotify_unknown] = OmniAuth::AuthHash.new( { provider: 'spotify', info: { id: "dri19tcc", display_name: "Adriana Cannon" } }) + + OmniAuth.config.mock_auth[:spotify_uid] = OmniAuth::AuthHash.new( { provider: 'spotify', uid: "preferred", info: { id: "not", display_name: " " } }) end