Rails: "has_many", "blongs_to"でリレーショナルなテーブル関係を設定する_コントローラ、ビュー実装
前回、以下にて"has_many", "blongs_to"でリレーショナルなテーブル関係を設定したので実際に使えるようにコントローラとビューへ実装する.
teki-com.hateblo.jp
参考サイト
has_manyとbelongs_toについて。モデルの関連付けされたformの作り方 - Qiita
第11章ユーザーのマイクロポスト - Railsチュートリアル
html - No route matches missing required keys: [:id] - Stack Overflow
Rails のルーティング - Rails ガイド
RailsのScaffoldでネストしたResourceを作る - sometimes I laugh
ネストした form_with のリダイレクト先がエラーになってしまう - Qiita
ルーティングをネスト構造へ変更
以下でAuthorの下にBookを入れる.
[config/routes.rb]
resources :authors do resources :books end
ルーティングをネスト構造にすることで、以下のようにpathが自動的に割り当てられる.
Authorの設定
基本的に何もする必要なし。だけどBookの一覧表示へのリンクのみ作成しておく.
[app/views/authors/show.html.erb]
<%= link_to 'Book一覧', author_books_path(@author) %>
Book側の設定
ルーティング(path)が変わっているのでそれに合わせて変更する必要あり.
indexアクション
[app/controller/books_controller.rb]
FROM
# GET /books def index @books = Book.all end
TO
# GET /authors/:author_id/books def index @author = Author.find(params[:author_id]) @books = Author.find(params[:author_id]).books end
ビューを以下のようにパスを変更する.
[app/views/authors/index.html.erb]
<td><%= link_to 'Show', author_book_path(@author,book) %></td> <td><%= link_to 'Edit', edit_author_book_path(@author,book) %></td> <td><%= link_to 'Destroy', author_book_path(@author,book), method: :delete, data: { confirm: 'Are you sure?' } %></td>
showアクション
コントローラ
# GET /authors/:author_id/books/1 def show @author = Author.find(params[:author_id]) @books = Author.find(params[:author_id]).books end
ビュー
<%= link_to 'Edit', edit_author_book_path(@author,@book) %> <%= link_to 'Back', author_books_path(@author) %>
共通処理の"_form.html.erb"の一行目の処理にauthorを追加する.
[app/view/books/_form.html.erb]
<%= form_with(model: [author,book], local: true) do |form| %>
newおよびcreateアクション
コントローラ
[app/controllers/books_controller.rb]
# GET /authors/:author_id/books/new def new @author = Author.find(params[:author_id]) @book = Author.find(params[:author_id]).books.new end # POST /authors/:author_id/books def create @author = Author.find(params[:author_id]) @book = Author.find(params[:author_id]).books.new(book_params) respond_to do |format| if @book.save format.html { redirect_to [@author,@book], notice: 'Book was successfully created.' } ... else ... end end end
ビュー
[app/views/books/new.html.erb]
<%= render 'form', author: @author, book: @book %> <%= link_to 'Back', author_books_path(@author) %>
もう一度"_form.html.erb"に移動し、今度は16行目をの"form.text_field :author_id"とすることで初期値にauthor_idとしておく
<%= form.text_field :author_id, id: :book_author %>
editおよびupdateアクション
コントローラ
# GET /authors/:author_id/books/1/edit def edit @author = Author.find(params[:author_id]) @books = Author.find(params[:author_id]).books end # PATCH/PUT authors/:author_id/books/1 def update @author = Author.find(params[:author_id]) if @book.update(book_params) format.html { redirect_to [@author,@book], notice: 'Book was successfully updated.' } ... else ... end end end
ビュー
<%= render 'form', author: @author, book: @book %> <%= link_to 'Edit', edit_author_book_path(@author,@book) %> <%= link_to 'Back', author_books_path(@author) %>
updateはビューを持っていないので省略
Destroyアクション
コントローラ
[app/controllers/books_controller.rb]
# DELETE authors/:author_id/books/1 def destroy ... format.html { redirect_to author_books_url, notice: 'Book was successfully destroyed.' } ... end end private # Use callbacks to share common setup or constraints between actions. def set_book @book = Author.find(params[:author_id]).books.find(params[:id]) end ... end
Destroyはビューを持っていないので省略
以上.すごく荒削りにしか開催していないのであまり参考にしないでください.
いずれわかりやすく書き直します.今はメモ程度.