From b5f616a9d91629114c034b92afeb4e24fdc97bf8 Mon Sep 17 00:00:00 2001 From: Gregory Eremin Date: Mon, 27 Aug 2012 03:53:30 +0400 Subject: [PATCH] Artist import, page --- .gitignore | 1 + Gemfile | 7 + Gemfile.lock | 74 ++- app/assets/javascripts/application.js | 7 + .../javascripts/backbone/beat_haven.js.coffee | 18 + .../backbone/models/artist.js.coffee | 2 + .../backbone/routers/artist_router.js.coffee | 9 + .../backbone/templates/artists/show.mustache | 39 ++ .../views/artist/artist_show.js.coffee | 10 + app/assets/stylesheets/application.css | 13 - app/assets/stylesheets/application.css.scss | 20 + app/assets/stylesheets/artist.css.scss | 132 ++++ app/controllers/api/albums_controller.rb | 8 + app/controllers/api/artists_controller.rb | 10 + app/controllers/application_controller.rb | 4 + app/models/album.rb | 24 + app/models/artist.rb | 88 +++ app/models/artist_genre.rb | 3 + app/models/genre.rb | 3 + app/models/performer.rb | 6 + app/models/track.rb | 14 + app/views/application/main.html | 0 app/views/layouts/application.html.erb | 11 +- config/api_keys.example.yml | 7 + config/initializers/beatparser.rb | 13 + config/initializers/hogan_templates.rb | 3 + config/routes.rb | 62 +- db/migrate/20120826170848_create_genres.rb | 10 + .../20120826171119_create_artist_genres.rb | 10 + db/migrate/20120826171313_create_artists.rb | 13 + db/migrate/20120826171911_create_albums.rb | 13 + db/migrate/20120826172032_create_tracks.rb | 14 + .../20120826172120_create_performers.rb | 10 + db/schema.rb | 68 ++ public/index.html | 241 ------- vendor/assets/javascripts/mustache.js | 613 ++++++++++++++++++ 36 files changed, 1268 insertions(+), 312 deletions(-) create mode 100644 app/assets/javascripts/backbone/beat_haven.js.coffee create mode 100644 app/assets/javascripts/backbone/models/artist.js.coffee create mode 100644 app/assets/javascripts/backbone/routers/artist_router.js.coffee create mode 100644 app/assets/javascripts/backbone/templates/artists/show.mustache create mode 100644 app/assets/javascripts/backbone/views/artist/artist_show.js.coffee delete mode 100644 app/assets/stylesheets/application.css create mode 100644 app/assets/stylesheets/application.css.scss create mode 100644 app/assets/stylesheets/artist.css.scss create mode 100644 app/controllers/api/albums_controller.rb create mode 100644 app/controllers/api/artists_controller.rb create mode 100644 app/models/album.rb create mode 100644 app/models/artist.rb create mode 100644 app/models/artist_genre.rb create mode 100644 app/models/genre.rb create mode 100644 app/models/performer.rb create mode 100644 app/models/track.rb create mode 100644 app/views/application/main.html create mode 100644 config/api_keys.example.yml create mode 100644 config/initializers/beatparser.rb create mode 100644 config/initializers/hogan_templates.rb create mode 100644 db/migrate/20120826170848_create_genres.rb create mode 100644 db/migrate/20120826171119_create_artist_genres.rb create mode 100644 db/migrate/20120826171313_create_artists.rb create mode 100644 db/migrate/20120826171911_create_albums.rb create mode 100644 db/migrate/20120826172032_create_tracks.rb create mode 100644 db/migrate/20120826172120_create_performers.rb create mode 100644 db/schema.rb delete mode 100644 public/index.html create mode 100644 vendor/assets/javascripts/mustache.js diff --git a/.gitignore b/.gitignore index b2dae98..b836692 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /config/database.yml +/config/api_keys.yml /log/*.log /tmp diff --git a/Gemfile b/Gemfile index 15f132e..3d3b661 100644 --- a/Gemfile +++ b/Gemfile @@ -8,6 +8,7 @@ group :assets do gem "coffee-rails", "~> 3.2.1" gem "therubyracer", platforms: :ruby + gem "hogan_assets" gem "uglifier", ">= 1.0.3" end @@ -21,3 +22,9 @@ gem "thin" # Deploy with Capistrano gem "capistrano" + +gem "robbie", path: "../robbie" +gem "beatparser", path: "../beatparser" +gem "rails-backbone" +gem "eco" +gem 'bootstrap-sass', '~> 2.0.4.0' diff --git a/Gemfile.lock b/Gemfile.lock index af41caa..ccf9f06 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,5 +1,20 @@ +PATH + remote: ../beatparser + specs: + beatparser (0.0.1) + lastfm-client + musicbrainz + robbie + +PATH + remote: ../robbie + specs: + robbie (0.0.1) + httparty + oj + GEM - remote: https://rubygems.org/ + remote: http://rubygems.org/ specs: actionmailer (3.2.8) actionpack (= 3.2.8) @@ -29,7 +44,14 @@ GEM i18n (~> 0.6) multi_json (~> 1.0) arel (3.0.2) + bootstrap-sass (2.0.4.0) builder (3.0.0) + capistrano (2.12.0) + highline + net-scp (>= 1.0.0) + net-sftp (>= 2.0.0) + net-ssh (>= 2.0.14) + net-ssh-gateway (>= 1.1.0) coffee-rails (3.2.2) coffee-script (>= 2.2.0) railties (~> 3.2.0) @@ -37,22 +59,53 @@ GEM coffee-script-source execjs coffee-script-source (1.3.3) + daemons (1.1.9) + eco (1.0.0) + coffee-script + eco-source + execjs + eco-source (1.1.0.rc.1) + ejs (1.0.0) erubis (2.7.0) + eventmachine (0.12.10) execjs (1.4.0) multi_json (~> 1.0) + highline (1.6.13) hike (1.2.1) + hogan_assets (1.3.2) + execjs (>= 1.2.9) + sprockets (>= 2.0.3) + tilt (>= 1.3.3) + httparty (0.8.3) + multi_json (~> 1.0) + multi_xml i18n (0.6.0) journey (1.0.4) jquery-rails (2.1.1) railties (>= 3.1.0, < 5.0) thor (~> 0.14) json (1.7.5) + lastfm-client (0.0.3) + json (>= 1.4.6) + libv8 (3.3.10.4) mail (2.4.4) i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) mime-types (1.19) multi_json (1.3.6) + multi_xml (0.5.1) + musicbrainz (0.7.0) + nokogiri + net-scp (1.0.4) + net-ssh (>= 1.99.1) + net-sftp (2.0.5) + net-ssh (>= 2.0.9) + net-ssh (2.5.2) + net-ssh-gateway (1.1.0) + net-ssh (>= 1.99.1) + nokogiri (1.5.5) + oj (1.3.4) pg (0.14.0) polyglot (0.3.3) rack (1.4.1) @@ -70,6 +123,10 @@ GEM activesupport (= 3.2.8) bundler (~> 1.0) railties (= 3.2.8) + rails-backbone (0.7.2) + coffee-script (~> 2.2.0) + ejs (~> 1.0.0) + railties (>= 3.1.0) railties (3.2.8) actionpack (= 3.2.8) activesupport (= 3.2.8) @@ -89,6 +146,12 @@ GEM hike (~> 1.2) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) + therubyracer (0.10.2) + libv8 (~> 3.3.10) + thin (1.4.1) + daemons (>= 1.0.9) + eventmachine (>= 0.12.6) + rack (>= 1.0.0) thor (0.16.0) tilt (1.3.3) treetop (1.4.10) @@ -103,9 +166,18 @@ PLATFORMS ruby DEPENDENCIES + beatparser! + bootstrap-sass (~> 2.0.4.0) + capistrano coffee-rails (~> 3.2.1) + eco + hogan_assets jquery-rails pg rails (= 3.2.8) + rails-backbone + robbie! sass-rails (~> 3.2.3) + therubyracer + thin uglifier (>= 1.0.3) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 9097d83..8428731 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,4 +12,11 @@ // //= require jquery //= require jquery_ujs +//= require mustache +//= require hogan +//= require underscore +//= require backbone +//= require backbone_rails_sync +//= require backbone_datalink +//= require backbone/beat_haven //= require_tree . diff --git a/app/assets/javascripts/backbone/beat_haven.js.coffee b/app/assets/javascripts/backbone/beat_haven.js.coffee new file mode 100644 index 0000000..c88d4f2 --- /dev/null +++ b/app/assets/javascripts/backbone/beat_haven.js.coffee @@ -0,0 +1,18 @@ +#= require_self +#= require_tree ./templates +#= require_tree ./models +#= require_tree ./views +#= require_tree ./routers + +window.BeatHaven = + Models: {} + Collections: {} + Routers: {} + Views: {} + + init: -> + new BeatHaven.Routers.Artist() + Backbone.history.start(); + +$ -> + BeatHaven.init() diff --git a/app/assets/javascripts/backbone/models/artist.js.coffee b/app/assets/javascripts/backbone/models/artist.js.coffee new file mode 100644 index 0000000..ecdf6f8 --- /dev/null +++ b/app/assets/javascripts/backbone/models/artist.js.coffee @@ -0,0 +1,2 @@ +class BeatHaven.Models.Artist extends Backbone.Model + urlRoot: "/api/artists" diff --git a/app/assets/javascripts/backbone/routers/artist_router.js.coffee b/app/assets/javascripts/backbone/routers/artist_router.js.coffee new file mode 100644 index 0000000..d7f2f8d --- /dev/null +++ b/app/assets/javascripts/backbone/routers/artist_router.js.coffee @@ -0,0 +1,9 @@ +class BeatHaven.Routers.Artist extends Backbone.Router + routes: + "artist/:name": "show" + + show: (name) -> + artist = new BeatHaven.Models.Artist(id: name) + artist.fetch() + view = new BeatHaven.Views.ArtistShow(model: artist) + $("#main").html(view.render().el) diff --git a/app/assets/javascripts/backbone/templates/artists/show.mustache b/app/assets/javascripts/backbone/templates/artists/show.mustache new file mode 100644 index 0000000..cc2da89 --- /dev/null +++ b/app/assets/javascripts/backbone/templates/artists/show.mustache @@ -0,0 +1,39 @@ +
+

{{name}}

+
+
+ {{name}} +
+
{{bio}}
+
+
+ {{#albums}} +
+ +

{{title}} ({{year}})

+
+ + + {{#tracks}} + + + + + {{/tracks}} + +
+ + {{title}} + + {{length}} + +
+
+
+ {{/albums}} +
+
diff --git a/app/assets/javascripts/backbone/views/artist/artist_show.js.coffee b/app/assets/javascripts/backbone/views/artist/artist_show.js.coffee new file mode 100644 index 0000000..f895978 --- /dev/null +++ b/app/assets/javascripts/backbone/views/artist/artist_show.js.coffee @@ -0,0 +1,10 @@ +class BeatHaven.Views.ArtistShow extends Backbone.View + template: HoganTemplates["backbone/templates/artists/show"] + + initialize: -> + @model.on("change", @render, this) + + render: -> + return this if typeof @model.attributes.id is "string" + $(@el).html(@template.render(@model.toJSON())) + this diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css deleted file mode 100644 index 3192ec8..0000000 --- a/app/assets/stylesheets/application.css +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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 vendor/assets/stylesheets of plugins, if any, 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 top of the - * compiled file, but it's generally better to create a new file per style scope. - * - *= require_self - *= require_tree . - */ diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss new file mode 100644 index 0000000..c1f6c3f --- /dev/null +++ b/app/assets/stylesheets/application.css.scss @@ -0,0 +1,20 @@ +@import "bootstrap"; +@import "artist"; +@import url(http://fonts.googleapis.com/css?family=Lobster); +@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro); + +body { + background: url(data:image/png;base64,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) +} + +#main { + margin-top: 50px; +} + +.navbar a.brand { + font-family: Lobster, Georgia, Serif; + font-size: 24px; + color: #fafafa; + letter-spacing: 1px; + text-shadow: 1px 1px 0 rgba(255, 255, 255, .2); +} diff --git a/app/assets/stylesheets/artist.css.scss b/app/assets/stylesheets/artist.css.scss new file mode 100644 index 0000000..82d41c1 --- /dev/null +++ b/app/assets/stylesheets/artist.css.scss @@ -0,0 +1,132 @@ +.artist-page { + h1 { + font-family: Lobster, Georgia, serif; + font-size: 42px; + line-height: 64px; + letter-spacing: 1px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .2); + } + + .artist-info { + min-height: 250px; + margin-bottom: 50px; + + .pic { + float: left; + + img { + width: 250px; + height: 250px; + border-size: 1px; + border-style: solid; + border-color: rgba(255, 255, 255, .2); + border-radius: 5px; + box-shadow: 1px 1px 5px rgba(0, 0, 0, .2); + } + } + .bio { + margin-left: 270px; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 22px; + line-height: 26px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .1); + } + } + + .album { + min-height: 250px; + margin-bottom: 30px; + + h2 { + font-family: Lobster, Georgia, Serif; + font-size: 26px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .2); + } + .pic { + float: left; + height: 300px; + text-align: center; + + img { + background-color: #a0a0a0; + width: 250px; + height: 250px; + border-size: 1px; + border-style: solid; + border-color: rgba(255, 255, 255, .2); + border-radius: 5px; + box-shadow: 1px 1px 5px rgba(0, 0, 0, .2); + margin-bottom: 10px; + } + } + .title { + margin-left: 270px; + margin-bottom: 10px; + } + .tracks { + margin-left: 270px; + + tr:hover { + td { + background-color: rgba(200, 200, 200, .3); + + .track-play i { + opacity: 1; + } + &.length { + .track-add { + display: block; + } + .length { + display: none; + } + } + } + } + + td { + position: relative; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 20px; + line-height: 28px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .1); + + .btn-round { + width: 10px; + height: 22px; + border-radius: 50px; + + i { + margin: 3px 0 0 -1px; + } + } + } + + td.title { + padding-left: 40px; + .track-play { + position: absolute; + margin: -2px 0 0 -40px; + + i { + opacity: .3; + } + } + .track-link { + color: #303030; + } + } + + td.length { + text-align: right; + + .track-add { + position: absolute; + right: 8px; + margin: -2px 0 0 0; + display: none; + } + } + } + } +} diff --git a/app/controllers/api/albums_controller.rb b/app/controllers/api/albums_controller.rb new file mode 100644 index 0000000..dbab9a9 --- /dev/null +++ b/app/controllers/api/albums_controller.rb @@ -0,0 +1,8 @@ +module Api + class AlbumsController < ::ApplicationController + def picture + album = Album.find(params[:id]) + redirect_to album.load_pic + end + end +end diff --git a/app/controllers/api/artists_controller.rb b/app/controllers/api/artists_controller.rb new file mode 100644 index 0000000..463406c --- /dev/null +++ b/app/controllers/api/artists_controller.rb @@ -0,0 +1,10 @@ +module Api + class ArtistsController < ::ApplicationController + def show + artist = Artist.with_name(params[:id].gsub("+", " ")) + return render json: { fail: true } if artist.nil? + + render json: artist.dump_json + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e8065d9..676ede8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,7 @@ class ApplicationController < ActionController::Base protect_from_forgery + + def main + + end end diff --git a/app/models/album.rb b/app/models/album.rb new file mode 100644 index 0000000..a7a8947 --- /dev/null +++ b/app/models/album.rb @@ -0,0 +1,24 @@ +class Album < ActiveRecord::Base + belongs_to :artist + has_many :tracks + + attr_accessible :artist_id, :pic, :rovi_id, :title, :year + + def pic_safe + unless pic.nil? + pic + else + "/api/albums/#{id}/picture" + end + end + + def load_pic + info = BeatParser::Sources::Lastfm.album_info(artist.name, title) + unless info[:pic].nil? + update_attributes(pic: info[:pic]) + info[:pic] + else + "/assets/images/album-dummy.png" + end + end +end diff --git a/app/models/artist.rb b/app/models/artist.rb new file mode 100644 index 0000000..447a50b --- /dev/null +++ b/app/models/artist.rb @@ -0,0 +1,88 @@ +class Artist < ActiveRecord::Base + has_many :albums + has_many :performers + has_many :tracks, through: :performers + has_many :genres, through: :artist_genres + + attr_accessible :bio, :is_group, :name, :pic, :rovi_id + + def loaded? + pic? && bio? + end + + def dump_json + serialized = to_json( + include: { + albums: { + include: { + tracks: { + methods: [:length], + except: [:created_at, :updated_at, :rovi_id, :album_id] + } + }, + except: [:created_at, :updated_at, :rovi_id, :pic], + methods: [:pic_safe] + } + }, + except: [:created_at, :updated_at, :rovi_id], + ) + end + + class << self + def with_name(name) + # DB lookup + artist = find_by_name(name) + return artist unless artist.nil? + + # Rovi correction + rovi_artist = Robbie::Artist.find_by_name(name) + return artist if rovi_artist && artist = find_by_rovi_id(rovi_artist.id) + + # Parsing artist if ok + import(rovi_artist) if rovi_artist + end + + def import(rovi_artist) + data = BeatParser::Aggregator.new.combine(rovi_artist.id) + artist = Artist.find_or_create_by_rovi_id(data[:id]) + artist.update_attributes( + name: data[:name], + is_group: data[:is_group], + pic: data[:pic], + bio: data[:bio] + ) + data[:albums].each do |album_meta| + album = Album.find_or_create_by_rovi_id(album_meta[:id]) + album.update_attributes( + artist_id: artist.id, + title: album_meta[:title], + year: album_meta[:year].to_i + ) + album_meta[:tracks].each do |track_meta| + track = Track.find_or_create_by_rovi_id(track_meta[:id]) + track.update_attributes( + album_id: album.id, + disc_id: track_meta[:disc_id], + position: track_meta[:position], + title: track_meta[:title], + duration: track_meta[:duration] + ) + track_meta[:artists].each do |performer| + performer_artist = Artist.find_or_create_by_rovi_id(performer[:id]) + performer_artist.update_attributes( + name: performer[:name] + ) + Performer.find_or_create_by_artist_id_and_track_id(performer_artist.id, track.id) + end + end + end + data[:genres].each do |genre_meta| + genre = Genre.find_or_create_by_rovi_id(genre_meta[:id]) + genre.update_attributes( + name: genre_meta[:name] + ) + ArtistGenre.find_or_create_by_artist_id_and_genre_id(artist.id, genre.id) + end + end + end +end diff --git a/app/models/artist_genre.rb b/app/models/artist_genre.rb new file mode 100644 index 0000000..e7a4271 --- /dev/null +++ b/app/models/artist_genre.rb @@ -0,0 +1,3 @@ +class ArtistGenre < ActiveRecord::Base + attr_accessible :artist_id, :genre_id +end diff --git a/app/models/genre.rb b/app/models/genre.rb new file mode 100644 index 0000000..25b9626 --- /dev/null +++ b/app/models/genre.rb @@ -0,0 +1,3 @@ +class Genre < ActiveRecord::Base + attr_accessible :name, :rovi_id +end diff --git a/app/models/performer.rb b/app/models/performer.rb new file mode 100644 index 0000000..6958b10 --- /dev/null +++ b/app/models/performer.rb @@ -0,0 +1,6 @@ +class Performer < ActiveRecord::Base + belongs_to :artist + belongs_to :track + + attr_accessible :artist_id, :track_id +end diff --git a/app/models/track.rb b/app/models/track.rb new file mode 100644 index 0000000..17515e0 --- /dev/null +++ b/app/models/track.rb @@ -0,0 +1,14 @@ +class Track < ActiveRecord::Base + belongs_to :album + has_many :performers + has_many :artists, through: :performers + + attr_accessible :album_id, :disc_id, :duration, :position, :rovi_id, :title + + def length + return if duration.nil? + length = duration.divmod(60).map(&:to_s) + length[1] = "0" << length[1] if length[1].length == 1 + length.join(":") + end +end diff --git a/app/views/application/main.html b/app/views/application/main.html new file mode 100644 index 0000000..e69de29 diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 2bdac2b..a6bb5af 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -2,13 +2,20 @@ BeatHaven - <%= stylesheet_link_tag "application", :media => "all" %> + <%= stylesheet_link_tag "application", media: "all" %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> -<%= yield %> + +
Loading...
diff --git a/config/api_keys.example.yml b/config/api_keys.example.yml new file mode 100644 index 0000000..784b272 --- /dev/null +++ b/config/api_keys.example.yml @@ -0,0 +1,7 @@ +lastfm: + api_key: secret + api_secret: secret + client_name: BeatHaven +rovi: + api_key: secret + api_secret: secret diff --git a/config/initializers/beatparser.rb b/config/initializers/beatparser.rb new file mode 100644 index 0000000..f15911a --- /dev/null +++ b/config/initializers/beatparser.rb @@ -0,0 +1,13 @@ +File.open("#{Rails.root}/config/api_keys.yml") do |file| + config = YAML.load(file.read) + + LastFM.api_key = config["lastfm"]["api_key"] + LastFM.secret = config["lastfm"]["api_secret"] + LastFM.client_name = config["lastfm"]["client_name"] + + Robbie.setup( + api_key: config["rovi"]["api_key"], + api_secret: config["rovi"]["api_secret"] + ) + Robbie.enable_cache +end diff --git a/config/initializers/hogan_templates.rb b/config/initializers/hogan_templates.rb new file mode 100644 index 0000000..122204f --- /dev/null +++ b/config/initializers/hogan_templates.rb @@ -0,0 +1,3 @@ +HoganAssets::Config.configure do |config| + config.path_prefix = "backbone/templates/" +end diff --git a/config/routes.rb b/config/routes.rb index d06904e..5bb6d03 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,58 +1,10 @@ BeatHaven::Application.routes.draw do - # The priority is based upon order of creation: - # first created -> highest priority. + namespace :api do + resources :artists, only: [:show], constraints: { id: /.+/ } + resources :albums, only: [:picture] do + member { get :picture } + end + end - # Sample of regular route: - # match 'products/:id' => 'catalog#view' - # Keep in mind you can assign values other than :controller and :action - - # Sample of named route: - # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase - # This route can be invoked with purchase_url(:id => product.id) - - # Sample resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Sample resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Sample resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Sample resource route with more complex sub-resources - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', :on => :collection - # end - # end - - # Sample resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end - - # You can have the root of your site routed with "root" - # just remember to delete public/index.html. - # root :to => 'welcome#index' - - # See how all your routes lay out with "rake routes" - - # This is a legacy wild controller route that's not recommended for RESTful applications. - # Note: This route will make all actions in every controller accessible via GET requests. - # match ':controller(/:action(/:id))(.:format)' + root to: "application#main" end diff --git a/db/migrate/20120826170848_create_genres.rb b/db/migrate/20120826170848_create_genres.rb new file mode 100644 index 0000000..c380cdd --- /dev/null +++ b/db/migrate/20120826170848_create_genres.rb @@ -0,0 +1,10 @@ +class CreateGenres < ActiveRecord::Migration + def change + create_table :genres do |t| + t.string :rovi_id + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20120826171119_create_artist_genres.rb b/db/migrate/20120826171119_create_artist_genres.rb new file mode 100644 index 0000000..f1b0cde --- /dev/null +++ b/db/migrate/20120826171119_create_artist_genres.rb @@ -0,0 +1,10 @@ +class CreateArtistGenres < ActiveRecord::Migration + def change + create_table :artist_genres do |t| + t.integer :artist_id + t.integer :genre_id + + t.timestamps + end + end +end diff --git a/db/migrate/20120826171313_create_artists.rb b/db/migrate/20120826171313_create_artists.rb new file mode 100644 index 0000000..c8652f5 --- /dev/null +++ b/db/migrate/20120826171313_create_artists.rb @@ -0,0 +1,13 @@ +class CreateArtists < ActiveRecord::Migration + def change + create_table :artists do |t| + t.string :rovi_id + t.string :name + t.boolean :is_group + t.text :bio + t.string :pic + + t.timestamps + end + end +end diff --git a/db/migrate/20120826171911_create_albums.rb b/db/migrate/20120826171911_create_albums.rb new file mode 100644 index 0000000..1afb99a --- /dev/null +++ b/db/migrate/20120826171911_create_albums.rb @@ -0,0 +1,13 @@ +class CreateAlbums < ActiveRecord::Migration + def change + create_table :albums do |t| + t.integer :artist_id + t.string :rovi_id + t.string :title + t.integer :year + t.string :pic + + t.timestamps + end + end +end diff --git a/db/migrate/20120826172032_create_tracks.rb b/db/migrate/20120826172032_create_tracks.rb new file mode 100644 index 0000000..d32d390 --- /dev/null +++ b/db/migrate/20120826172032_create_tracks.rb @@ -0,0 +1,14 @@ +class CreateTracks < ActiveRecord::Migration + def change + create_table :tracks do |t| + t.integer :album_id + t.string :rovi_id + t.integer :disc_id + t.integer :position + t.string :title + t.integer :duration + + t.timestamps + end + end +end diff --git a/db/migrate/20120826172120_create_performers.rb b/db/migrate/20120826172120_create_performers.rb new file mode 100644 index 0000000..2d72405 --- /dev/null +++ b/db/migrate/20120826172120_create_performers.rb @@ -0,0 +1,10 @@ +class CreatePerformers < ActiveRecord::Migration + def change + create_table :performers do |t| + t.integer :track_id + t.integer :artist_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000..3ac82e1 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,68 @@ +# 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 to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20120826172120) do + + create_table "albums", :force => true do |t| + t.integer "artist_id" + t.string "rovi_id" + t.string "title" + t.integer "year" + t.string "pic" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "artist_genres", :force => true do |t| + t.integer "artist_id" + t.integer "genre_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "artists", :force => true do |t| + t.string "rovi_id" + t.string "name" + t.boolean "is_group" + t.text "bio" + t.string "pic" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "genres", :force => true do |t| + t.string "rovi_id" + t.string "name" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "performers", :force => true do |t| + t.integer "track_id" + t.integer "artist_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "tracks", :force => true do |t| + t.integer "album_id" + t.string "rovi_id" + t.integer "disc_id" + t.integer "position" + t.string "title" + t.integer "duration" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + +end diff --git a/public/index.html b/public/index.html deleted file mode 100644 index a1d5099..0000000 --- a/public/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - Ruby on Rails: Welcome aboard - - - - -
- - -
- - - - -
-

Getting started

-

Here’s how to get rolling:

- -
    -
  1. -

    Use rails generate to create your models and controllers

    -

    To see all available options, run it without parameters.

    -
  2. - -
  3. -

    Set up a default route and remove public/index.html

    -

    Routes are set up in config/routes.rb.

    -
  4. - -
  5. -

    Create your database

    -

    Run rake db:create to create your database. If you're not using SQLite (the default), edit config/database.yml with your username and password.

    -
  6. -
-
-
- - -
- - diff --git a/vendor/assets/javascripts/mustache.js b/vendor/assets/javascripts/mustache.js new file mode 100644 index 0000000..9e20b87 --- /dev/null +++ b/vendor/assets/javascripts/mustache.js @@ -0,0 +1,613 @@ +/*! + * mustache.js - Logic-less {{mustache}} templates with JavaScript + * http://github.com/janl/mustache.js + */ + +/*global define: false*/ + +var Mustache; + +(function (exports) { + if (typeof module !== "undefined" && typeof module.exports !== "undefined") { + module.exports = exports; // CommonJS + } else if (typeof define === "function") { + define(exports); // AMD + } else { + Mustache = exports; //