Skip to content

Commit

Permalink
feat: 🎸 Feature モデルとインポータを追加しアソシエーションを設定した (#46)
Browse files Browse the repository at this point in the history
* feat: 🎸 $ bundle exec rails g model Feature

* feat: 🎸 $ bundle exec rails db:migrate

* feat: 🎸 $ rails runner "ImportToDb::FeatureService.new.execute"

* feat: 🎸 Album と Feature のアソシエーションを設定した

* test: 💍 Spec を追加した
  • Loading branch information
nikukyugamer authored Dec 3, 2023
1 parent 876922e commit 62f49f2
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/models/album.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class Album < ApplicationRecord
belongs_to :artist
has_many :tracks, dependent: :destroy
has_many :features, dependent: :destroy
end
3 changes: 3 additions & 0 deletions app/models/feature.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Feature < ApplicationRecord
belongs_to :album
end
55 changes: 55 additions & 0 deletions app/services/import_to_db/feature_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require 'csv'

module ImportToDb
class FeatureService
FEATURE_CSV_FILENAMES = [
'features_s1.csv',
'features_s2_1.csv',
'features_s2_2.csv',
'features_s3.csv',
'features_s4.csv',
'features_s5.csv',
'features_tk.csv',
'features_tsumutoki.csv',
].freeze

def initialize; end # rubocop:disable Style/RedundantInitialize

def execute # rubocop:disable Metrics/AbcSize
FEATURE_CSV_FILENAMES.each do |feature_csv_filename|
csv_data = CSV.read("db/csv_files/#{feature_csv_filename}", headers: true)

features = csv_data.map do |row|
album_id_str = row['album_id']

# Album がインポートされていることが前提となる
album = Album.find_by(id_str: album_id_str)
album_id = album.id

# cf. db/migrate/20231203050800_create_features.rb
Feature.new(
album_id:,
id_str: row['id'],
duration_ms: row['duration_ms'].to_i,
tempo: row['tempo'].to_f,
time_signature: row['time_signature'].to_i,
key: row['key'].to_i,
mode: row['mode'].to_i,
acousticness: row['acousticness'].to_f,
danceability: row['danceability'].to_f,
energy: row['energy'].to_f,
instrumentalness: row['instrumentalness'].to_f,
liveness: row['liveness'].to_f,
loudness: row['loudness'].to_f,
speechiness: row['speechiness'].to_f,
valence: row['valence'].to_f,
api_analysis_url: row['api_analysis_url'],
api_track_href: row['api_track_href']
)
end

Feature.import!(features, on_duplicate_key_ignore: true)
end
end
end
end
31 changes: 31 additions & 0 deletions db/migrate/20231203050800_create_features.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class CreateFeatures < ActiveRecord::Migration[7.1]
def change
# 各カラムの具体的な説明は https://python-muda.com/python/spotify-api-ep-2/ や公式ドキュメントを参照すること
create_table :features do |t|
t.references :album, null: false, foreign_key: true, comment: 'トラックが収録されているアルバム'
t.string :id_str, null: false, comment: 'Spotify のトラックID'
t.integer :duration_ms, null: false, comment: 'トラックの長さ(ミリ秒)'
t.float :tempo, null: false, comment: 'トラックのテンポ (bpm)'
t.integer :time_signature, null: false, comment: 'トラックの拍子(各小節に含まれる拍数)'
# ピッチクラス: https://ja.wikipedia.org/wiki/%E3%83%94%E3%83%83%E3%83%81%E3%82%AF%E3%83%A9%E3%82%B9
t.integer :key, null: false, comment: 'トラックのキー(ピッチクラスで表現され、0 = C、2 = D など)'
t.integer :mode, null: false, comment: 'トラックのモード(メジャーは1、マイナーは0)'
t.float :acousticness, null: false, comment: 'トラックのアコースティック度(0~1)'
t.float :danceability, null: false, comment: 'トラックのダンス性(0~1)'
t.float :energy, null: false, comment: 'トラックのエネルギッシュさ(0~1)'
t.float :instrumentalness, null: false, comment: 'トラックのインスト度(0~1)'
t.float :liveness, null: false, comment: 'トラックのライブ感(0~1)'
t.float :loudness, null: false, comment: 'トラックの音圧のデシベル値の平均'
t.float :speechiness, null: false, comment: 'トラックの話し声度(0~1)'
t.float :valence, null: false, comment: 'トラックのポジティブ度(0~1)'
t.string :api_analysis_url, null: false, comment: 'トラックの解析APIのURL'
t.string :api_track_href, null: false, comment: 'トラックのAPIのURL'

t.timestamps
end

add_index :features, :id_str, unique: true
add_index :features, :api_analysis_url, unique: true
add_index :features, :api_track_href, unique: true
end
end
29 changes: 28 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions spec/factories/features.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FactoryBot.define do
factory :feature do

end
end
5 changes: 5 additions & 0 deletions spec/models/album_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@
expect(Album.first.tracks).to be_present
expect(Album.first.tracks.first.class).to eq Track
end

it 'Feature へのアソシエーションが設定されていること' do
expect(Album.first.features).to be_present
expect(Album.first.features.first.class).to eq Feature
end
end
7 changes: 7 additions & 0 deletions spec/models/feature_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'rails_helper'

RSpec.describe Feature, type: :model do
it 'Album へのアソシエーションが設定されていること' do
expect(Feature.first.album.class).to eq Album
end
end
1 change: 1 addition & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
ImportToDb::ArtistService.new.execute
ImportToDb::AlbumService.new.execute
ImportToDb::TrackService.new.execute
ImportToDb::FeatureService.new.execute
rescue ActiveRecord::PendingMigrationError => e
abort e.to_s.strip
end
Expand Down

0 comments on commit 62f49f2

Please sign in to comment.