Skip to content

Commit

Permalink
add support for various artists album
Browse files Browse the repository at this point in the history
  • Loading branch information
aidewoode committed Jul 22, 2020
1 parent 7ff0a01 commit ad10ea9
Show file tree
Hide file tree
Showing 37 changed files with 209 additions and 45 deletions.
1 change: 0 additions & 1 deletion app/controllers/albums_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def index

def show
@songs = @album.songs

AttachAlbumImageFromDiscogsJob.perform_later(@album.id) if @album.need_attach_from_discogs?
end

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ApplicationController < ActionController::Base

before_action :find_current_user

rescue_from ActiveRecord::RecordNotFound do |exception|
rescue_from ActiveRecord::RecordNotFound, BlackCandyError::NotFound do |exception|
respond_to do |format|
format.js { head :not_found }
format.json { head :not_found }
Expand Down
20 changes: 20 additions & 0 deletions app/controllers/artists/albums_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

class Artists::AlbumsController < ApplicationController
before_action :require_login
before_action :find_artist
before_action :find_albums

def index
raise BlackCandyError::NotFound if @albums.empty?
end

private
def find_albums
@albums = @artist.albums
end

def find_artist
@artist = Artist.find(params[:artist_id])
end
end
8 changes: 8 additions & 0 deletions app/controllers/artists/appears_on_albums_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class Artists::AppearsOnAlbumsController < Artists::AlbumsController
private
def find_albums
@albums = @artist.appears_on_albums
end
end
5 changes: 4 additions & 1 deletion app/controllers/artists_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class ArtistsController < ApplicationController
ALBUMS_COUNT = 10

include Pagy::Backend

before_action :require_login
Expand All @@ -12,7 +14,8 @@ def index

def show
@artist = Artist.find(params[:id])
@pagy, @albums = pagy_countless(@artist.albums)
@albums_pagy, @albums = pagy_countless(@artist.albums, items: ALBUMS_COUNT)
@appears_on_albums_pagy, @appears_on_albums = pagy_countless(@artist.appears_on_albums, items: ALBUMS_COUNT)

AttachArtistImageFromDiscogsJob.perform_later(@artist.id) if @artist.need_attach_from_discogs?
end
Expand Down
1 change: 1 addition & 0 deletions app/lib/black_candy_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

module BlackCandyError
class Forbidden < StandardError; end
class NotFound < StandardError; end
class InvalidFilePath < StandardError; end
end
15 changes: 13 additions & 2 deletions app/models/artist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ class Artist < ApplicationRecord
include Searchable

has_many :albums, dependent: :destroy
has_many :songs, dependent: :destroy
has_many :songs

mount_uploader :image, ImageUploader

search_by :name

def title
is_unknown? ? I18n.t('text.unknown_artist') : name
return I18n.t('text.various_artists') if is_various?
return I18n.t('text.unknown_artist') if is_unknown?

name
end

def has_image?
Expand All @@ -22,6 +25,14 @@ def is_unknown?
name.blank?
end

def all_albums
Album.joins(:songs).where('albums.artist_id = ? OR songs.artist_id = ?', id, id).distinct
end

def appears_on_albums
Album.joins(:songs).where('albums.artist_id != ? AND songs.artist_id = ?', id, id).distinct
end

def need_attach_from_discogs?
Setting.discogs_token.present? && !has_image? && !is_unknown?
end
Expand Down
15 changes: 13 additions & 2 deletions app/models/media.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ def initialize(file_path)

def attach
artist = Artist.find_or_create_by(name: file_info[:artist_name])
album = Album.find_or_create_by(artist: artist, name: file_info[:album_name])

if various_artists?
various_artist = Artist.find_or_create_by(is_various: true)
album = Album.find_or_create_by(artist: various_artist, name: file_info[:album_name])
else
album = Album.find_or_create_by(artist: artist, name: file_info[:album_name])
end

# Attach image from file to the album.
AttachAlbumImageFromFileJob.perform_later(album.id, file_info[:file_path]) unless album.has_image?
Expand All @@ -25,6 +31,11 @@ def song_info
file_info.slice(:name, :tracknum, :length, :file_path)
end

def various_artists?
albumartist = file_info[:albumartist_name]
albumartist.present? && (albumartist.downcase == 'various artists' || albumartist != file_info[:artist_name])
end

class << self
def sync
media_hashes = MediaFile.file_paths.map do |file_path|
Expand All @@ -46,7 +57,7 @@ def clean_up(media_hashes)

# Clean up no content albums and artist.
Album.left_outer_joins(:songs).where('songs.id is null').destroy_all
Artist.left_outer_joins(:songs).where('songs.id is null').destroy_all
Artist.left_outer_joins(:songs, :albums).where('songs.album_id is null').where('albums.id is null').destroy_all
end
end
end
1 change: 1 addition & 0 deletions app/models/media_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def get_tag_info(file_path)
name: tag.title.presence || File.basename(file_path),
album_name: tag.album.presence,
artist_name: tag.artist.presence,
albumartist_name: tag.albumartist.presence,
tracknum: tag.track,
length: tag.duration
}
Expand Down
17 changes: 17 additions & 0 deletions app/views/artists/_albums.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<% if albums.present? %>
<div class='cards'>
<div class='heading heading--expand display__space-between display__full-width display__align-center'>
<div class='heading__body'>
<div class='heading__body__text heading__body__text--main'>
<%= title %>
</div>
</div>
<% if local_assigns[:all_albums_link] && all_albums_link.present? %>
<%= link_to t('text.see_all'), all_albums_link %>
<% end %>
</div>
</div>
<div class='cards'>
<%= render partial: 'albums/album', collection: albums, cached: true %>
</div>
<% end %>
18 changes: 18 additions & 0 deletions app/views/artists/_info.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<% cache artist do %>
<div class='cards'>
<div class='heading heading--expand'>
<div class='heading__image'>
<%= image_tag image_url_for(artist), class: 'image' %>
</div>
<div class='heading__body'>
<div class='heading__body__text heading__body__text--main'><%= artist.title %></div>
<div class='heading__body__text'>
<span><%= artist.all_albums.size %> <%= t('label.albums') %></span>
<span>,</span>
<span><%= artist.songs.size %> <%= t('label.songs')%></span>
</div>
</div>
</div>
</div>
<div class='line'></div>
<% end %>
2 changes: 2 additions & 0 deletions app/views/artists/albums/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%= render partial: 'artists/info', locals: { artist: @artist } %>
<%= render partial: 'artists/albums', locals: { title: t('label.albums'), albums: @albums } %>
2 changes: 2 additions & 0 deletions app/views/artists/appears_on_albums/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%= render partial: 'artists/info', locals: { artist: @artist } %>
<%= render partial: 'artists/albums', locals: { title: t('label.appears_on'), albums: @albums } %>
39 changes: 11 additions & 28 deletions app/views/artists/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
<% cache @artist do %>
<div class='cards'>
<div class='heading heading--expand'>
<div class='heading__image'>
<%= image_tag image_url_for(@artist), class: 'image' %>
</div>
<div class='heading__body'>
<div class='heading__body__text heading__body__text--main'><%= @artist.title %></div>
<div class='heading__body__text'>
<span><%= @albums.size %> <%= t('label.albums') %></span>
<span>,</span>
<span><%= @artist.songs.size %> <%= t('label.songs')%></span>
</div>
</div>
</div>
</div>
<div class='line'></div>
<% end %>
<div data-controller='infinite-scroll' data-infinite-scroll-next-url='<%= pagy_next_url(@pagy) %>'>
<div class='cards' id='js-albums-content'>
<%= render partial: 'albums/album', collection: @albums, cached: true %>
</div>
<div data-target='infinite-scroll.trigger' class='display__justify-align-center'>
<% if @pagy.next %>
<%= loader_tag %>
<% end %>
</div>
</div>
<%= render partial: 'info', locals: { artist: @artist} %>
<%= render partial: 'albums', locals: {
title: t('label.albums'),
albums: @albums,
all_albums_link: @albums_pagy.next.present? ? artist_albums_path(@artist) : '' } %>
<%= render partial: 'albums', locals: {
title: t('label.appears_on'),
albums: @appears_on_albums,
all_albums_link: @appears_on_albums_pagy.next.present? ? artist_appears_on_albums_path(@artist) : '' } %>
1 change: 0 additions & 1 deletion app/views/artists/show.js.erb

This file was deleted.

3 changes: 3 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ en:
integration: 'Integration'
close: 'Close'
more: 'More'
appears_on: 'Appears On'
error:
login: 'Wrong email or password'
media_path_blank: 'Media path is not exist'
Expand All @@ -75,6 +76,7 @@ en:
add_user: 'Add user'
create_user: 'Create User'
media_path: 'Media path'
various_artists: 'Various Artists'
unknown_artist: 'Unknown Artist'
unknown_album: 'Unknown Album'
go_back: 'Go back'
Expand All @@ -89,3 +91,4 @@ en:
expand_player: 'Expand player'
collapse_player: 'Collapse player'
personal: 'Personal'
see_all: 'See All'
6 changes: 5 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
resource :session, only: [:new, :create, :destroy]
resource :setting, only: [:show, :update]

resources :artists, only: [:index, :show]
resources :artists, only: [:index, :show] do
resources :albums, only: [:index], module: 'artists'
resources :appears_on_albums, only: [:index], module: 'artists'
end

resources :stream, only: [:new]
resources :transcoded_stream, only: [:new]
resources :songs, only: [:index, :show]
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20200721071945_add_is_various_to_artists.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddIsVariousToArtists < ActiveRecord::Migration[6.0]
def change
add_column(:artists, :is_various, :boolean, default: false)
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2020_04_25_023906) do
ActiveRecord::Schema.define(version: 2020_07_21_071945) do

# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
Expand All @@ -31,6 +31,7 @@
t.string "image"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.boolean "is_various", default: false
t.index ["name"], name: "index_artists_on_name", unique: true
end

Expand Down
19 changes: 19 additions & 0 deletions test/controllers/artists/albums_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

require 'test_helper'

class Artists::AlbumsControllerTest < ActionDispatch::IntegrationTest
test 'should get index' do
assert_login_access(url: artist_albums_path(artists :artist1)) do
assert_response :success
end
end

test 'should redirect to not found page when artists have no albums' do
empty_artist = Artist.create

assert_login_access(url: artist_albums_path(empty_artist)) do
assert_response :not_found
end
end
end
18 changes: 18 additions & 0 deletions test/controllers/artists/appears_on_albums_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require 'test_helper'

class Artists::AppearsOnAlbumsControllerTest < ActionDispatch::IntegrationTest
test 'should get index' do
assert_login_access(url: artist_appears_on_albums_path(artists :artist1)) do
assert_response :success
end
end

test 'should redirect to not found page when artists have no albums' do
assert artists(:artist2).appears_on_albums.empty?
assert_login_access(url: artist_appears_on_albums_path(artists :artist2)) do
assert_response :not_found
end
end
end
3 changes: 3 additions & 0 deletions test/fixtures/albums.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ album2:
album3:
name: 'album3'
artist: 'artist2'
album4:
name: 'album4'
artist: 'various_artists'
3 changes: 3 additions & 0 deletions test/fixtures/artists.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ artist1:

artist2:
name: 'artist2'

various_artists:
is_various: true
Binary file modified test/fixtures/files/artist1_album1.flac
Binary file not shown.
Binary file modified test/fixtures/files/artist1_album1.m4a
Binary file not shown.
Binary file modified test/fixtures/files/artist1_album2.mp3
Binary file not shown.
Binary file modified test/fixtures/files/artist2_album3.oga
Binary file not shown.
Binary file modified test/fixtures/files/artist2_album3.ogg
Binary file not shown.
Binary file modified test/fixtures/files/artist2_album3.opus
Binary file not shown.
Binary file modified test/fixtures/files/artist2_album3.wav
Binary file not shown.
Binary file modified test/fixtures/files/artist2_album3.wma
Binary file not shown.
Binary file added test/fixtures/files/various_artists.mp3
Binary file not shown.
8 changes: 8 additions & 0 deletions test/fixtures/songs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,11 @@ wma_sample:
md5_hash: 'fake_md5'
artist: 'artist2'
album: 'album3'

various_artists_sample:
id: 9
name: 'various_artists_sample'
file_path: <%= Rails.root.join('test', 'fixtures', 'files', 'various_artists.mp3') %>
md5_hash: 'fake_md5'
artist: 'artist1'
album: 'album4'
12 changes: 12 additions & 0 deletions test/models/artist_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@ class ArtistTest < ActiveSupport::TestCase
test 'should have default title when name is empty' do
assert_equal 'Unknown Artist', Artist.create(name: nil).title
end

test 'should have default title when is various artist' do
assert_equal 'Various Artists', Artist.create(is_various: true).title
end

test 'should get all albums' do
assert_equal Album.where(name: %w(album1 album2 album4)).ids.sort, artists(:artist1).all_albums.ids.sort
end

test 'should get appears on albums' do
assert_equal Album.where(name: %w(album4)).ids.sort, artists(:artist1).appears_on_albums.ids.sort
end
end
3 changes: 2 additions & 1 deletion test/models/concerns/searchable_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class SearchableTest < ActiveSupport::TestCase

album_serach_song_ids = Album.find_by_name('album1').songs.ids +
Album.find_by_name('album2').songs.ids +
Album.find_by_name('album3').songs.ids
Album.find_by_name('album3').songs.ids +
Album.find_by_name('album4').songs.ids

assert_equal album_serach_song_ids.sort, Song.search('album').ids.sort
end
Expand Down

0 comments on commit ad10ea9

Please sign in to comment.