ルーティングの設定
わからない言葉が増えてきた。リソースというのは操作可能(作成・削除・更新・編集)なデータ群のことであり、ネストとは親子構造のことだった。私はUserとPlantをネストで扱いたかった。URLで考えると以下のようなイメージだ。
/users/(ユーザーid) /plants/ (ユーザーが所持しているplantのid)
これを実現するには第3回で書いたように、モデルに対して関連付けをする必要がある。また、ルーティングに対してもいろいろやらなくてはいけない。
config/routes.rb
Rails.application.routes.draw do
root to: 'users#index'
devise_for :users
resources :users do
resources :plants
end
end
root to: 'users#index'
とはトップページの設定、 devise_for :users
はログイン機能に関するものだ。ここでは詳しく述べない。resources...
が大事だ。このように入れ子構造にすることでネストされたリソースが実現できる。
記述が終わったらターミナルで rails routes
を打ち込んで、どのようなルーティングがなされているか確認して欲しい。
Userのコントローラーの追記とViewの作成
次はUserのコントローラーに追記をする。すでに以前の記事ですでにコントローラーはつくられているはずだ。以下のようにする。
app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
@users = User.all
end
def show
@user = User.find(params[:id])
end
end
ここではindexアクションとshowアクションのみ作る。
次にviewファイルをつくろう。index.html.erbとshow.html.erbだ。
app/views/users/index.html.erb
<h1>ユーザー一覧</h1>
<% @users.each do |user| %>
<p> アドレス <%= link_to user.email, user %></p>
<% end %>
app/views/users/show.html.erb
<h3>メールアドレス</h3>
<%= @user.email %><br>
<h3> 所有している植物 </h3>
<% @user.plants.each do |p| %>
<li><%= p.plant_name %></li>
<% end %>
<%= link_to user.email, user %>
によってindex.html.erbから ユーザーごとの詳細ページへ移動するリンクが貼られる。詳細ページでは p.plant_name によってユーザーが所有しているplantの名前が表示される。
Plantコントローラの追記とViewの作成
今度はPlantコントローラーも書いていこう。index,newアクションなどを一気に書きくだす。(このあたりも後々解説していきたい)
class PlantsController < ApplicationController
def index
@user = User.find(params[:user_id])
@plants = @user.plants
end
def new
@user = User.find(params[:user_id])
@plant = Plant.new
end
def create
@plant = Plant.new(plant_params)
current_user.plants.create(plant_params)
end
def show
@user = User.find(params[:user_id])
@plant = @user.plants.find(params[:id])
end
private
def plant_params
params.require(:plant).permit(:user_id, :plant_name, :img)
end
end
Viewファイルだが、今のところ使っているのはplants/create.html.erb ,plants/show.html.erb , plants/new.html.erbだけだ。 plants/index.html.erbは存在はしているが、通常のリンクではたどれない。
User一覧 > User詳細 > Plants詳細
という順序で閲覧するためだ。
plants/create.html.erb
<h1>登録完了</h1>
<%= link_to 'マイページへ', user_path(current_user.id) %>
plants/show.html.erb
<h1>植物 詳細</h1>
<h3>植物の名前</h3>
<%= @plant.plant_name %><br>
<h3> 植物の写真 </h3>
<%= @plant.img %><br>
plants/new.html.erb
<h1>植物-新規登録</h1>
<%= form_with model: [@user, @plant], local: true do |f| %>
<p>植物名:<%= f.text_field :plant_name %></p>
<%= f.submit "登録" %>
<% end %>
ネストされているリンク先の指定
自分が一番悩んだのがこれだ。以下の三つ。
- User詳細ページからPlant詳細ページへのリンク
- User詳細ページからPlantの新規登録ページへのリンク
- Plant新規登録ページからcreateアクション実行へのリンク
順に紹介する。
User詳細ページからPlant詳細ページへのリンク
<!-- 略 -->
<% @user.plants.each do |p| %>
<li><%= link_to p.plant_name ,[@user,p]%></li>
<% end %>
<!-- 略 -->
このようにlink_toのリンク先を配列にしてやることでネストされたページへリンクを貼ることができる。
以下のページが参考になった。
User詳細ページからPlantの新規登録ページへのリンク
<!-- 略 -->
<%= link_to '植物登録' ,new_user_plant_path(current_user.id) %>
<!-- 略 -->
current_user.idを利用することで、現在ログインしているUserのidを参照できる。これでリンクが貼れる。
Plant新規登録ページからcreateアクション実行へのリンク
<%= form_with model: [@user, @plant], local: true do |f| %>
<p>植物名:<%= f.text_field :plant_name %></p>
<%= f.submit "登録" %>
<% end %>
このform_with記法のリンク先もさきのlink_toと似ている。 今回の場合は [@user, @plant]とすることでネストされたリンクについてcreateアクションを行うことができる。
(この表現の仕方があっているのか…?)
おわりに
現状のことがらはひとまず書き終えることができた。まだ、他人のIDのCRUD処理ができてしまうなど、問題は多い。間違いを質しながら個人開発をすすめていこう。