はじめに
本記事はRailsでポケモン図鑑を作ろうで作成したアプリケーションに課題として機能を追加していきます。様々なヒントややり方を載せていますので参考にしてチャレンジしてください。
1. 編集機能
投稿したものの内容を変更できる機能があると便利です。
ポケモンの情報を編集できる機能を実装していきましょう。
1.1 routes・controllers・view の3点に、編集ページを新規作成する
まずはconfig/routes.rbを編集します。
Rails.application.routes.draw do
get 'pokemons/index'
get 'pokemons/show/:id', to:'pokemons#show', as: 'pokemon'
get 'pokemons/new'
post 'pokemons', to: 'pokemons#create'
# 以下の2行を追加
get 'pokemons/:id/edit', to: 'pokemons#edit', as: 'edit_pokemon'
patch 'pokemons/:id/', to: 'pokemons#update'
# ここまで
end
データを更新するアクションは、HTTPメソッドの「PATCH」または「PUT」を使用します。
patchとputのどちらを使うか迷った場合は、Railsで推奨されているpatchを使用しましょう。
as:オプションを使うとルーティングに名前を指定できます。
上記だと、名前付きヘルパーとしてedit_pokemon_path
とedit_pokemon_url
が作成されます。
edit_pokemon_path
を呼び出すとpokemons/:id/edit
が返されます。
次にpokemons_controller.rb
のcreateアクションの下にeditアクションを作成します。
def create
# 省略
end
# 下の3行を追加
def edit
@pokemon = Pokemon.find(params[:id])
end
# ここまで
アクション名は「edit」です。
編集ページで必要な情報は、「一つのpokemon」です。
よって、今回は「params[:id]」で、一つだけidを取得します
これはshowアクションと同様のことを行っています。
次にビューを作成します。
コマンドプロンプトで下のコマンドを実行すると、edit.html.erb
が生成します。
(エディタから新規ファイルを作成からでも構いません)
app/views/pokemons/edit.html.erbは下記のようにしましょう。
コードはこちら(クリックしてください)
<div class="container mt-6">
<div class="columns">
<div class="column is-three-fifths is-offset-one-fifth">
<%= form_with model:@pokemon, url:"/pokemons/#{@pokemon.id}", local:true do |f| %>
<!-- エラーメッセージ -->
<% if @pokemon.errors %>
<% @pokemon.errors.full_messages.each do |message| %>
<div class='alert'>
<ul>
<li><%= message %></li>
</ul>
</div>
<% end %>
<% end %>
<!-- ここまでエラーメッセージ -->
<div class="field">
<%= f.label :name, "なまえ", class: 'label'%>
<div class="control">
<%= f.text_field :name, class:'input'%>
</div>
</div>
<div class="field">
<%= f.label :number, "ばんごう", class: 'label' %>
<div class="control">
<%= f.text_field :number, class: 'input'%>
</div>
</div>
<div class='field'>
<%= f.label :zokusei, "タイプ", class: 'label' %>
<div class="control">
<%= f.text_field :zokusei, class: 'input'%>
</div>
</div>
<div class="field">
<%= f.label :description, "せつめい", class: 'label' %>
<div class="control">
<%= f.text_area :description, class: 'textarea' %>
</div>
</div>
<div class="file">
<label class="file-label"></label>
</div>
<br/>
<br/>
<div class="file is-boxed">
<label class="file-label">
<%= f.file_field :image, class: 'file-input'%>
<span class="file-cta">
<span class="file-icon">
<i class="fas fa-upload"></i>
</span>
<span class="file-label">
<%= f.label :image, 'がぞう', class: 'label'%>
</span>
</span>
</label>
</div>
<%= f.submit "登録", class: 'button is-link'%>
<% end %>
</div>
</div>
</div>
form_withでモデルにインスタンス変数を渡すことで(model:@pokemon)、編集したいポケモンの情報が既にフォーム内に入っています。
フォームはnew.html.erbのときとほとんど同じです。
そして、再びコントローラにコードを追加していきます。
app/controllers/pokemons_controller.rbのeditアクションにupdateアクションを追加します。
def edit
@pokemon = Pokemon.find(params[:id]
end
# ここから追加する
def update
pokemon = Pokemon.find(params[:id])
pokemon.update(pokemon_params)
redirect_to pokemon_path(pokemon.id)
# ↑ ポケモンのshowページに移動する
end
private
def pokemon_params
params.require(:pokemon).permit(:name, :zokusei, :number, :description, :image)
end
# ここまで追加する
最後にポケモン詳細ページに編集ページのリンクを貼りましょう。
(中略)
<div class="column is-8">
<div class="p-description">
<%= @pokemon.description %>
</div>
<p class="p-edit"> <%= link_to 'へんしゅう', edit_pokemon_path, class: 'button is-info'%> </p>
<!-- 上の1行を追加する -->
(中略)
</div>
ポケモン検索機能
検索機能には色々とありますが、ポケモン名を完全一致で検索できるものを作っていきます。
1.検索フォームを作成する
既存にあるindex.html.erbの上部に検索フォームを追加します。
new.html.erbやedit.html.erbとほとんど似ていますが、
:search
など、検索に関わるカラムを追加しています。
<!-- ここから -->
<div class="field has-addons">
<div class="control">
<%= form_with(url: pokemons_index_path, class: 'search_form', method: :get, local:true) do |f| %>
<%= f.text_field :search, class:'field', value: params[:search], placeholder: "ポケモンけんさく", class: 'input'%>
</div>
<div class="control">
<%= f.submit 'けんさく', class: "button is-info" %>
<% end %>
</div>
</div>
<!-- ここまで -->
<div class="container mt-6">
<h1 class="title has-text-centered"> ポケモンいちらん </h1>
<!-- 省略 -->
</div>
2.コントローラーの編集
pokemon_controller.rbのindexアクションを以下に書き換えましょう。
indexアクション内1行目の@pokemons = Pokemon.all
は一覧ページが表示されたときは登録しているポケモンすべてを表示するようにしており、
indexアクション2行目の@pokemons = params[:search].present? ? Pokemon.pokemon_serach(params[:search]) : Pokemon.all
は検索フォームに入力されたものがPokemonモデルにあるかどうかを判定し、存在していれば、@pokemons
にいれ、表示をします。存在していなかったら、ポケモンすべてを表示します。
class PokemonsController < ApplicationController
def index
@pokemons = params[:search].present? ? Pokemon.pokemon_serach(params[:search]) : Pokemon.all
end
3.モデルの編集
検索機能の詳しい実装はモデル内でしていきましょう。
class Pokemon < ApplicationRecord
(省略)
def self.pokemon_serach(search)
Pokemon.where(['name LIKE ?', "%#{search}%"])
end
end
ポケモンいちらんページで名前を検索(カタカナで)すると
一致したポケモンのみ表示されます。
詳しく知りたい人は以下のサイトを参考にしてください。