はじめに
筆者は 大学生限定 プログラミングコミュニティ 『GeekSalon』で活動している者です!
もし少しでも興味がありましたら、ぜひお話を聞きにきてください!
前提
この記事でできることを紹介します。
今回は投稿の分類をし、その後にアソシエーションを使いさらに分類するといったことをします。
例えば、音楽をジャンル毎に分ける → ジャンル毎にアーティストを投稿する → アーティストの曲ごとに分類する。
流れはこんな感じになります。
他にも、スポーツをジャンル毎に分ける → ジャンル毎にスポーツを投稿する → そのスポーツチームごとに分ける。といったこともできます。
参考記事:投稿の分類はこちらの記事を参考にしました
カテゴリー分けその1
今回は、音楽をジャンル毎に分ける → ジャンル毎にアーティストを投稿する → アーティストの曲ごとに分類することをします!
①コントローラーを作成します
rails g controller musics
②コントローラーに以下のコードを記載
def new
@music = Music.new
end
#追加箇所
def create
music = Music.new(music_params)
if music.save
# カテゴリーに応じてリダイレクト先を設定
if music.category == "idol"
redirect_to musics_idol_path
elsif music.category == "japaneserock"
redirect_to musics_japaneserock_path
else
# その他のカテゴリーに対するリダイレクト先を設定する場合、ここに追加
redirect_to musics_westernrock_path
end
else
render :new
end
end
def idol
@musics = Music.all
end
def westernrock
@musics = Music.all
end
def japaneserock
@musics = Music.all
end
def destroy
music = Music.find(params[:id])
music.destroy
redirect_to action: :index
end
private
def music_params
params.require(:music).permit(:content, :category, )
end
コード解説
今回は音楽ジャンルをアイドル・邦ロック・洋ロックに分けました。そのため、各ジャンル毎にアーティストが一覧で見れるようにします。
def create
music = Music.new(music_params)
if music.save
# カテゴリーに応じてリダイレクト先を設定
if music.category == "idol"
redirect_to musics_idol_path
elsif music.category == "japaneserock"
redirect_to musics_japaneserock_path
else
# その他のカテゴリーに対するリダイレクト先を設定する場合、ここに追加
redirect_to musics_westernrock_path
end
else
render :new
end
end
こちらはif文を使い、カテゴリー毎に投稿されたものに飛ぶようにしています。
例)邦ロックのアーティストを投稿する → 投稿されたら邦ロックの一覧ページに飛ぶようにする。
投稿するジャンル(KPOPやHIPHOP)を増やしたい場合は、elsifを追加しコードをコピーして、カテゴリーを変更すれば増やすことができます。
def idol
@musics = Music.all
end
def westernrock
@musics = Music.all
end
def japaneserock
@musics = Music.all
end
こちらのコードでジャンル毎に投稿を分けることができます。
今回は、アイドル 邦ロック 洋ロックで分けました。
ルーティング作成
get 'musics/idol' => 'musics#idol'
get 'musics/westernrock' => 'musics#westernrock'
get 'musics/japaneserock' => 'musics#japaneserock'
resources :musics
モデル作成
rails g model Music content:string category:string
rails db:migrate
こちらのコードでモデルとカラムを作成します。
それぞれのviewファイルを作成
viewのmusicsディレクトリにidol.html.erbファイル,westernrock.html.erbファイル,japaneserock.html.erbファイルの三つを右クリックで作成
<h1>アイドル</h1>
<% @musics.each do |t| %>
<% if t.category == "idol" %>
<p>アーティスト名:<%= t.content %></p>
<%= button_to "削除する", music_path(t.id), method: :delete %>
<% end %>
<% end %>
洋ロックや邦ロックの際も同様に同じのをコピぺしてください。また、コピペした後にidolを変更してください。
新規アーティストを投稿するページ作成
<%= form_for @music do |f| %>
<%= f.label :content,"アーティスト名" %>
<%= f.text_field :content %>
<%= f.select :category, [["アイドル", "idol"], ["邦ロック", "japaneserock"], ["洋ロック", "westernrock"]], include_blank: "ジャンル" %>
<%= f.submit "投稿する" %>
<% end %>
ここまでで、カテゴリーごとに投稿を分類することができるうようになりました
一つのアーティストが複数の曲を持つようにする
アーティスト一覧ページ(アーティストのリストを表示するページ)とアーティストの曲一覧ページ(特定のアーティストの曲を表示するページ)を関連付けるアソシエーションは、次のようになります:
「アーティスト一覧ページ」 → 「アーティストの曲一覧ページ」
これは、アーティスト一覧ページから特定のアーティストを選択し、そのアーティストの曲一覧ページに移動するという関連性を示しています。
このようにアソシエーションを使って、アーティスト一覧ページと曲一覧ページ、そして曲一覧ページの関連性を明確に分類できます。
モデル作成
アーティストと曲の関連性を実現するために、Music モデルと Song モデルを使い、一つのアーティストが複数の曲を持つ関係を設定します。以下に、必要なコードを示します。
rails g model Song title:string music_id:integer
マイグレーションを実行して、データベースに変更を適用します。
rails db:migrate
Music モデルと Song モデルは関連付け、アーティストが複数の曲を持つことができるようにする
class Music < ApplicationRecord
has_many :songs
has_many :songs, dependent: :destroy
end
Music モデルを修正して、has_many アソシエーションを追加します。これにより、一つのアーティスト(Music レコード)が複数の曲(Song レコード)を持つことができます。
dependent: :destroyは、この関連付けを削除するときの振る舞いを指定しています。
具体的には、関連する「songs」が削除されるときに、それに関連するすべての「song」レコードも削除されます。これは「親モデルが削除された場合、関連する子モデルも削除する」という一般的なデータベースの関連付けの設定です。例えば、アーティストが削除された場合、そのアーティストに関連する全ての曲(songs)も削除されます。
class Song < ApplicationRecord
belongs_to :music
end
この設定により、Music モデルと Song モデルは関連付けられ、アーティストが複数の曲を持つことができるようになります。
アーティストごとの新規曲投稿を作成
def new
@song = Song.new
end
def create
@song = Song.new(song_params)
if @song.save
redirect_to musics_artist_songs_path(@song.music), notice: "曲が投稿されました"
else
render :new
end
end
private
def song_params
params.require(:song).permit(:title, :music_id)
end
こちらのコードでアーティストごとの曲を投稿できるようにします。
アーティストの曲一覧ページを作成
def artist_songs
@music = Music.find(params[:id])
@new_song = Song.new
@songs = @music.songs
end
解説
このコードは、アーティスト(Music モデル)に関連付けられた音楽曲(Song モデル)を管理するためのアクションである artist_songs アクションを定義しています。
@music = Music.find(params[:id]):
この行は、指定されたID(params[:id])に基づいて特定のアーティスト(Music インスタンス)をデータベースから取得します。
@songs = @music.songs
この行は、特定のアーティスト(@music)に関連付けられた音楽曲(Song インスタンス)のリストを取得します。
@music インスタンスは、データベースから特定のアーティストを取得するために使用され、そのアーティストに関連付けられた音楽曲を取得するためにも使用されます。
ルーティング設定
get 'musics/idol' => 'musics#idol'
get 'musics/westernrock' => 'musics#westernrock'
get 'musics/japaneserock' => 'musics#japaneserock'
get 'musics/artist_songs' => 'musics#artist_songs'#ここに追加
resources :musics
resources :songs, only: [:new, :create] #ここに追加
アーティストの曲投稿ページ
<h1>アーティストごとの曲投稿</h1>
<%= form_for @song do |f| %>
<%= f.label :title, "曲のタイトル" %>
<%= f.text_field :title %>
<%= f.label :music_id, "アーティスト" %>
<%= f.collection_select :music_id, Music.all, :id, :content, prompt: "アーティストを選択" %>
<%= f.submit "曲を投稿" %>
<% end %>
曲一覧ページ作成
<h1><%= @music.content %>曲一覧</h1>
<ul>
<% @songs.each do |song| %>
<li><%= song.title %></li>
<% end %>
</ul>
以上でアソシエーションを使った投稿の分類は以上になります。完成系はこちらになります。
お疲れ様でした!