diff --git a/.gitignore b/.gitignore index 03f3ce7..2b147d1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ /log/* !/log/.keep /tmp +.DS_Store # From https://github.com/github/gitignore/blob/master/Ruby.gitignore *.gem @@ -26,7 +27,7 @@ /tmp/ # Used by dotenv library to load environment variables. -# .env +.env ## Specific to RubyMotion: .dat* diff --git a/Gemfile b/Gemfile index 288bb87..1eb3904 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,21 @@ gem 'jbuilder', '~> 2.0' # bundle exec rake doc:rails generates the API under doc/api. gem 'sdoc', '~> 0.4.0', group: :doc +gem 'httparty' + +gem 'rspotify' + +gem 'yelp', require: 'yelp' + +gem "omniauth" + +gem "omniauth-github" + +gem 'omniauth-oauth2', '~> 1.3.1' + + + + # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' @@ -33,13 +48,20 @@ 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 'pry-rails' + gem "better_errors" + gem "binding_of_caller" + gem "dotenv-rails" + # gem 'vcr' + gem "minitest-vcr" + gem "webmock" + gem "minitest-reporters" end group :development do # Access an IRB console on exception pages or by using <%= console %> in views gem 'web-console', '~> 2.0' - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' + # gem 'spring' end - diff --git a/Gemfile.lock b/Gemfile.lock index 6ff0f39..9b1d353 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,11 +36,18 @@ 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) + coderay (1.1.1) coffee-rails (4.1.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.1.x) @@ -49,11 +56,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 +86,56 @@ 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-github (1.1.2) + omniauth (~> 1.0) + omniauth-oauth2 (~> 1.1) + omniauth-oauth2 (1.3.1) + oauth2 (~> 1.0) + omniauth (~> 1.2) 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) @@ -106,6 +166,13 @@ 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-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,7 +183,13 @@ GEM sdoc (0.4.1) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) - spring (1.7.1) + 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) sprockets (3.6.0) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -131,27 +204,52 @@ GEM thread_safe (~> 0.1) uglifier (3.0.0) execjs (>= 0.3.0, < 3) + vcr (3.0.1) 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.2) + 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-github + omniauth-oauth2 (~> 1.3.1) pg (~> 0.15) + pry-rails rails (= 4.2.6) + rspotify sass-rails (~> 5.0) sdoc (~> 0.4.0) - spring + simplecov (~> 0.11.2) uglifier (>= 1.3.0) 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/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/stylesheets/application.css b/app/assets/stylesheets/application.css index f9cd5b3..264f23e 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -13,3 +13,21 @@ *= require_tree . *= require_self */ +.float-right { + float: right; +} + +.covers img{ + height: 170px; + width: 170px; +} + +.suggestion { + clear: both; + float: left: +} + +.user-photo img { + height: 70px; + width: 70px; +} diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000..ccb1ed2 --- /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..2ac92ee --- /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/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e..d759f2f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,70 @@ 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 + @current_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 + + def extract_suggestions(suggestions) + if suggestions.class != Array + suggestions = pull_from_id(suggestions.suggestions) + suggestions.each do |suggestion_hash| + food = suggestion_hash.suggestion["food_id"] + suggestion_hash.suggestion["food_suggestion"]= Food.retrieve(food) + suggestion_hash.suggestion["music_suggestion"] = Music.retrieve(suggestion_hash.suggestion["music_id"], suggestion_hash.suggestion["music_type"]) + end + return suggestions + end + suggestions.each do |suggestion_hash| + food = suggestion_hash["food_id"] + suggestion_hash["food_suggestion"]= Food.retrieve(food) + suggestion_hash["music_suggestion"] = Music.retrieve(suggestion_hash["music_id"], suggestion_hash["music_type"]) + end + return suggestions + end + + def pull_from_id(suggestions) + hashes = [] + suggestions.each do |id| + hashes << TunesTakeoutWrapper.specific_suggestion(id) + end + return hashes + end + + def get_food(suggestions) + if suggestions.count == 1 + food = Food.find(id) + end + food_array = [] + suggestions.each do |hash| + hash["food_id"] = id + food = Food.find(id) + food_array << food + end + return food_array + end + + def get_music(suggestions) + if suggestions.count == 1 + music = Music.find(id) + end + music_array = [] + suggestions.each do |hash| + hash["music_id"] = id + music = Music.find(id) + music_array << music + end + return music_array + end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000..b40e57e --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,29 @@ +class SessionsController < ApplicationController + skip_before_action :require_login, only: [:new, :create] + + def new + + end + + def create + auth_hash = request.env['omniauth.auth'] + if auth_hash["info"]["id"] + @user = User.find_or_create_from_omniauth(auth_hash) + if @user + session[:user_id] = @user.id + redirect_to root_path + else + redirect_to root_path, notice: "Failed to save the user" + end + else + redirect_to root_path, notice: "Failed to save the user" + 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..d97b130 --- /dev/null +++ b/app/controllers/suggestions_controller.rb @@ -0,0 +1,54 @@ +# require '/lib/tunes_takeout_wrapper' +class SuggestionsController < ApplicationController + skip_before_action :require_login, only: :index + + def index + @suggestions = extract_suggestions(TunesTakeoutWrapper.top(4)) + #shows top 20 suggestions, ranked by total number of favorites + if current_user + @spotify_user = RSpotify::User.find(@current_user.uid) + @user = current_user + @image = @spotify_user.images[0]["url"] + end + # if current_user + # @favorites = TunesTakeoutWrapper.user_favorites(@user.user_id) + # end + end + + def favorites #display user favorites + @user = current_user + @suggestions = TunesTakeoutWrapper.user_favorites(@user.uid) + unless @suggestions.suggestions ==[] + @suggestions = extract_suggestions(@suggestions) #returns array of pairing id's, FIX CALL + end + end + + def favorite + @user = current_user + @path = params[:path] + @suggestion_id = params[:format] + @suggestion = TunesTakeoutWrapper.favorite(@user.uid, @suggestion_id) + redirect_to favorites_path(current_user.uid)#path.to_sym + end + + def unfavorite + @user = current_user + @suggestion_id = params[:format] + @suggestion = TunesTakeoutWrapper.unfavorite(@user.uid, @suggestion_id) + @path = params[:path] + redirect_to favorites_path(current_user.uid)# path.to_sym + end + + def search + @user = current_user + @suggestions = TunesTakeoutWrapper.limited_search(params[:query], 4).suggestions + @suggestions = extract_suggestions(@suggestions) + render :results + end + + + +# favorites: shows all suggestions favorited by the signed-in User +# favorite: adds a suggestion into the favorite list for the signed-in User. This requires interaction with the Tunes & Takeout API. +# unfavorite: removes a suggestion from the favorite list for the signed-in User. This requires interaction with the Tunes & Takeout API. +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/models/food.rb b/app/models/food.rb new file mode 100644 index 0000000..a0ff356 --- /dev/null +++ b/app/models/food.rb @@ -0,0 +1,17 @@ +class Food +attr_reader :food, :name, :address, :url, :rating, :image + + def initialize(food) + @name = food.name + @address = food.location + @url = food.mobile_url + @rating = food.rating_img_url + @image = food.image_url + end + + def self.retrieve(id) + # food = HTTParty.get(YELP_URL + "/v2/business/#{id}") + food = Yelp.client.business(id.parameterize).business + Food.new(food) + end +end diff --git a/app/models/music.rb b/app/models/music.rb new file mode 100644 index 0000000..b4a6a07 --- /dev/null +++ b/app/models/music.rb @@ -0,0 +1,40 @@ +class Music +attr_reader :name, :artist, :url, :album, :cover + def initialize(music, type) + @name = music.name + @artist = music.artists unless type == "artist" + @url = music.artists[0].external_urls["spotify"] unless type =="artist" + # @tracks = music.tracks_cache + @cover = cover_art(music, type) + end + + def self.retrieve(id, type) + if type.downcase == "track" + music = RSpotify::Track.find(id) + elsif type.downcase == "album" + music = RSpotify::Album.find(id) + elsif type.downcase == "artist" + music = RSpotify::Artist.find(id) + else + music = "OTHER TYPE" + end + # music = HTTParty.get(SPOTIFY_URL + "/v1/#{type}/#{id}").parsed_response + Music.new(music, type) + end + + def cover_art(music, type) + if type == "album" + return music.images[0] + elsif type == "artist" + if music.images == [] + return {"url" => "http://localhost:3000/assets/artist_image.jpg"} + else + return music.images + end + elsif type == "track" + return music.album.images[0] + else + return "WHAT DO?!" + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..40d8782 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,17 @@ +class User < ActiveRecord::Base + validates :name, :id, :provider, presence: true + + def self.find_or_create_from_omniauth(auth_hash) + user = User.find_by(uid: auth_hash["uid"] ||=auth_hash["info"]["id"], provider: auth_hash["provider"]) + if user.nil? + user = User.new(uid: auth_hash["uid"] ||=auth_hash["info"]["id"], provider: auth_hash["provider"], name: auth_hash["info"]["display_name"]) + if user.save! + return user + else + return nil + end + end + return user + end + +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 509d1a2..640da3c 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,12 +1,41 @@ - TunesTakeout + TakeoutTunes <%= stylesheet_link_tag 'application', media: 'all' %> <%= javascript_include_tag 'application' %> <%= csrf_meta_tags %> +
+ +
<%= yield %> diff --git a/app/views/suggestions/_suggestion.html.erb b/app/views/suggestions/_suggestion.html.erb new file mode 100644 index 0000000..5f396e0 --- /dev/null +++ b/app/views/suggestions/_suggestion.html.erb @@ -0,0 +1,34 @@ +<% if @suggestions.class == Array %> + <% @suggestions.each do |hash|%> + +
+ <% if hash.class == TunesTakeoutWrapper %> + <% hash = hash.suggestion %> + <%end%> + Eat at + <% food = hash["food_suggestion"]%> + <%= link_to food.name, "https://yelp.com/biz/#{hash["food_id"]}" %><%= image_tag "#{food.rating}" %> +
<%= image_tag "#{food.image}" %><%= food.address.address[0]%>
+
+ While listening to the <%= hash["music_type"]%> + <% sound = hash["music_suggestion"]%> + <%= link_to sound.name, sound.url %> +
<%= (sound.cover.class == Array) ? (image_tag "#{sound.cover[0]["url"]}") : (image_tag "#{sound.cover["url"]}") %> <%= food.address.address[0]%>
+
+ <% if current_user %> + <% user_faves = TunesTakeoutWrapper.user_favorites(current_user.uid)%> + <% unless user_faves ==[]%> + <% user_faves = user_faves.suggestions%> #returns array of pairing id's %> + <%end%> + <% if user_faves.include? hash["id"] %> + <%= link_to "Unfavorite this pairing", unfave_path(hash["id"], @path), method: :delete, class: "btn btn-danger" %> + <% else%> + <%= link_to "Favorite this pairing", add_fave_path(hash["id"], @path), method: :post, class: "btn btn-primary" %> + <%end%> + <%end%> +
+
+ +
+ <%end%> +<%end%> diff --git a/app/views/suggestions/favorites.html.erb b/app/views/suggestions/favorites.html.erb new file mode 100644 index 0000000..14c1254 --- /dev/null +++ b/app/views/suggestions/favorites.html.erb @@ -0,0 +1,3 @@ +<% @path = favorites_path(current_user.id) %> +

Your favorite pairings

+<%=render partial: "suggestion"%> diff --git a/app/views/suggestions/index.html.erb b/app/views/suggestions/index.html.erb new file mode 100644 index 0000000..7cdabc7 --- /dev/null +++ b/app/views/suggestions/index.html.erb @@ -0,0 +1,3 @@ +<% @path = root_path %> +

Top rated suggestions:

+<%=render partial: "suggestion"%> diff --git a/app/views/suggestions/results.html.erb b/app/views/suggestions/results.html.erb new file mode 100644 index 0000000..5a0d849 --- /dev/null +++ b/app/views/suggestions/results.html.erb @@ -0,0 +1,4 @@ +<% @path = search_path(params[:query]) %> +

Search results for "<%= params[:query]%>"

+ +<%=render partial: "suggestion"%> diff --git a/config/application.rb b/config/application.rb index 9b37a86..086fdaf 100644 --- a/config/application.rb +++ b/config/application.rb @@ -8,6 +8,7 @@ module TunesTakeout class Application < Rails::Application + # RSpotify::authenticate(ENV["SPOTIFY_CLIENT_ID"], ENV["SPOTIFY_CLIENT_SECRET"]) # 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. @@ -22,5 +23,8 @@ class Application < Rails::Application # Do not swallow errors in after_commit/after_rollback callbacks. config.active_record.raise_in_transactional_callbacks = true + + config.autoload_paths += %W(#{config.root}/lib) + config.autoload_paths += %W(#{config.root}/extras) end end diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 0000000..cc0c5f5 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,3 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :spotify, ENV["SPOTIFY_CLIENT_ID"], ENV["SPOTIFY_CLIENT_SECRET"] +end diff --git a/config/initializers/spotify.rb b/config/initializers/spotify.rb new file mode 100644 index 0000000..ac8eee1 --- /dev/null +++ b/config/initializers/spotify.rb @@ -0,0 +1,3 @@ +require 'rspotify' + +RSpotify::authenticate(ENV["SPOTIFY_CLIENT_ID"], ENV["SPOTIFY_CLIENT_SECRET"]) diff --git a/config/initializers/yelp.rb b/config/initializers/yelp.rb new file mode 100644 index 0000000..b51eebb --- /dev/null +++ b/config/initializers/yelp.rb @@ -0,0 +1,8 @@ +require 'yelp' + +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..6b575bf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,15 @@ Rails.application.routes.draw do + + root 'suggestions#index' + # get '/auth/:provider' => 'session#login' + get '/auth/:provider/callback' => 'sessions#create' + delete '/logout' => 'sessions#destroy', as: "logout" + get '/search/:query' => 'suggestions#search', as: "search" + get '/suggestion/:id' => 'suggestions#pair', as: "specific_suggestion" + get '/user/favorites' => 'suggestions#favorites', as: "favorites" + post '/user/suggestion' => 'suggestions#favorite', as: "add_fave" + delete '/user/suggestion' => 'suggestions#unfavorite', as: "unfave" + # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". diff --git a/config/secrets.yml b/config/secrets.yml index be83593..9de716b 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -11,10 +11,10 @@ # if you're sharing your code publicly. development: - secret_key_base: 553149b03d6ba63414be540733245f323d241c1c9a37f3266d1216d93effd901fefb43f0782e4d2b739d61a3de1488c681a90435b22318114f638d9fc6e0f8c1 + secret_key_base: 79252673745894b33179f707df65b3248f272f2e46bfa2078120f8c252f7e59331033872fe13be2b2259f0b01fc7d73d6d8e58c3b54969ff67d348bef69f959f test: - secret_key_base: 0c9e2ff02abb06b715fccfbd8a7fb390a12595cf1c4d8b58cae707903a17a4a58ea0762f4a2125da40cf59b211620b81e702e13d58c4a50e4591f48dcbf1cbaa + secret_key_base: 51273e88b99c66c8b3c1bfec07acd6decb4c824853659d0323bf3fd0927909240544f0f6a6bb7f2bed8e8761fd8439a43ae31f2a06571c8ad95282f73ed15c84 # Do not keep production secrets in the repository, # instead read values from the environment. diff --git a/db/migrate/20160516231845_create_users.rb b/db/migrate/20160516231845_create_users.rb new file mode 100644 index 0000000..fc91a6e --- /dev/null +++ b/db/migrate/20160516231845_create_users.rb @@ -0,0 +1,11 @@ +class CreateUsers < ActiveRecord::Migration + def change + create_table :users do |t| + t.string :provider, null: false + t.string :uid, null: false + t.string :name, null: false + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20160516232252_create_foods.rb b/db/migrate/20160516232252_create_foods.rb new file mode 100644 index 0000000..7e72f05 --- /dev/null +++ b/db/migrate/20160516232252_create_foods.rb @@ -0,0 +1,9 @@ +class CreateFoods < ActiveRecord::Migration + def change + create_table :foods do |t| + t.string :restaurant + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20160516232327_create_musics.rb b/db/migrate/20160516232327_create_musics.rb new file mode 100644 index 0000000..6df76b5 --- /dev/null +++ b/db/migrate/20160516232327_create_musics.rb @@ -0,0 +1,10 @@ +class CreateMusics < ActiveRecord::Migration + def change + create_table :musics do |t| + t.string :object + t.string :type + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000..206f970 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,40 @@ +# 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: 20160516232327) 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.string "restaurant" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "musics", force: :cascade do |t| + t.string "object" + t.string "type" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "users", force: :cascade do |t| + t.string "provider", null: false + t.string "uid", null: false + t.string "name", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + +end diff --git a/lib/tunes_takeout_wrapper.rb b/lib/tunes_takeout_wrapper.rb new file mode 100644 index 0000000..7034d98 --- /dev/null +++ b/lib/tunes_takeout_wrapper.rb @@ -0,0 +1,73 @@ +require 'httparty' + +class TunesTakeoutWrapper + BASE_URL = "https://tunes-takeout-api.herokuapp.com/" + attr_reader :suggestions, :suggestion + + def initialize(data) + if data["suggestions"] + if data["suggestions"].class == Array + @suggestions = data["suggestions"] + else + @suggestions = data["suggestions"].suggestions + end + elsif data["suggestion"] + if data["suggestion"].class == Array|| data["suggestion"].class == Hash + @suggestion = data["suggestion"] + else + @suggestion = data["suggestion"].suggestion + end + else + @errors = "No data returned" + end + end + # + # def favorite_move + # HTTParty.get(moves.sample["move"]["url"]).parsed_response + # end + + def self.search(query) + data = HTTParty.get(BASE_URL + "/v1/suggestions/search?query=#{query}").parsed_response + self.new(data) + end + + def self.limited_search(query, n) + data = HTTParty.get(BASE_URL + "/v1/suggestions/search?query=#{query}&limit=#{n}").parsed_response + self.new(data) + end + + def self.random(query, n, seed = random(99999)) + data = HTTParty.get(BASE_URL + "/v1/suggestions/search?query=#{query}&limit=#{n}&seed=#{seed}").parsed_response + self.new(data) + end + + def self.specific_suggestion(suggestion_id) + data = HTTParty.get(BASE_URL + "/v1/suggestions/#{suggestion_id}").parsed_response + self.new(data) + end + + def self.user_favorites(user_id) #returns "suggestions":["VzoxXvLQUmT7dPJ5", "VzoxXvLQUmT7dPJ6"] + data = HTTParty.get(BASE_URL + "/v1/users/#{user_id}/favorites").parsed_response + self.new(data) + end + + def self.favorite(user_id, suggestion_id) + fave_request = HTTParty.post(BASE_URL + "/v1/users/#{user_id}/favorites", + body: {"suggestion"=> "#{suggestion_id}"}.to_json, + headers: {"Content-Type" => "application/json" }) + return fave_request.code + end + + def self.unfavorite(user_id, suggestion_id) + unfave_request = HTTParty.delete(BASE_URL + "/v1/users/#{user_id}/favorites", + body: {"suggestion"=> "#{suggestion_id}"}.to_json, + headers: {"Content-Type" => "application/json" }) + return unfave_request.code + end + + def self.top(limit = 20) + data = HTTParty.get(BASE_URL + "/v1/suggestions/top?limit=#{limit}").parsed_response + self.new(data) + end + +end diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 0000000..d30ebc3 --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class SessionsControllerTest < ActionController::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/suggestions_controller_test.rb b/test/controllers/suggestions_controller_test.rb new file mode 100644 index 0000000..f4587a5 --- /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/fixtures/foods.yml b/test/fixtures/foods.yml new file mode 100644 index 0000000..82a42f5 --- /dev/null +++ b/test/fixtures/foods.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + restaurant: MyString + +two: + restaurant: MyString diff --git a/test/fixtures/musics.yml b/test/fixtures/musics.yml new file mode 100644 index 0000000..6f08ce6 --- /dev/null +++ b/test/fixtures/musics.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + object: MyString + type: + +two: + object: MyString + type: diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000..451c27a --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +known_user: + provider: spotify + uid: known_user + name: known_user + +spotiy_unknown: + provider: spotify + name: testusertwo + uid: fgdo235 diff --git a/test/models/food_test.rb b/test/models/food_test.rb new file mode 100644 index 0000000..8ad7dff --- /dev/null +++ b/test/models/food_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class FoodTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/music_test.rb b/test/models/music_test.rb new file mode 100644 index 0000000..c5c6737 --- /dev/null +++ b/test/models/music_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class MusicTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 0000000..92c2b5c --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,53 @@ +require 'test_helper' + +class UserTest < ActiveSupport::TestCase + + describe "API" do + before do + @suggestions = TunesTakeout.search(1) + end + + it "has the right data type for an array of suggestions", :vcr do + assert_instance_of Array, @suggestions + end + + it "isn't an empty array of suggestions", :vcr do + refute @suggestions.empty? + end + + it "has a hash in the suggestion array element", :vcr do + assert_instance_of Hash, @suggestions[1] + end + end + + + def setup + # @known = OmniAuth.config.mock_auth[:spotify_known] + @known = { "provider" => 'spotify', "info" => { "id" => "known_user", "display_name" => "known user" } } + @unknown = OmniAuth.config.mock_auth[:spotify_unknown] + @unknown_with_uid = OmniAuth.config.mock_auth[:spotify_uid] + end + + test "can find an existing user given an oauth spotify hash" do + assert_equal users(:known_user), User.find_or_create_from_omniauth(@known) + end + + test "can make a new user given the oauth spotify hash of an unknown user" do + assert_difference 'User.count', 1 do + @user = User.find_or_create_from_omniauth @unknown + end + end + + test "uses oauth data to set user name, provider and uid for new users" do + user = User.find_or_create_from_omniauth @unknown + + assert_equal @unknown['info']['display_name'], user.name + assert_equal @unknown['provider'], user.provider + assert_equal @unknown['info']['id'], user.uid + end + + test "prefers a top-level uid over a nested id when creating an oauth user" do + user = User.find_or_create_from_omniauth @unknown_with_uid + assert_equal @unknown_with_uid['uid'], user.uid + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 92e39b2..9989d9a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,6 +2,22 @@ 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