LoginSignup
3
5

More than 3 years have passed since last update.

Rails 選択ボックスの使い方 1 ー 蔵書管理アプリに「本のジャンル」を追加してみる 基本編 (select)

Last updated at Posted at 2020-01-16

応用編はこちら
Rails 選択ボックスの使い方 2 ー 蔵書管理アプリに「本のジャンル」を追加してみる 応用編 (collection_select)

はじめに

プログラミング学習のアウトプットとしてポートフォリオ開発に取り組む方向けの記事です。
開発初期はtext_fieldを使って「商品名」や「ユーザー名」を保存するといった簡単なCRUD機能の実装から始められる方も多いと思います。

アプリの機能拡張アイデアの一つとして、本記事では「選択ボックスの使い方」を解説します。

題材としてはscaffoldを使った簡単な蔵書管理アプリ(bookapp)を使用します。
image.png

ご覧のように現状では「書名」、「作者名」のみ登録できる状態です。
基本編ではselectメソッドを使って「本のジャンル」選択ボックスを追加してみます。

対象読者の方

Rails学習を一通り終えて、初めてポートフォリオ開発に取り組まれる方

目指すゴール

selectメソッドを使って蔵書管理アプリに「本のジャンル」選択ボックスを実装する

完成イメージ

新規投稿フォーム(Book)
image.png

投稿一覧画面 (Book)
image.png

実装の流れ

準備

1 アプリの雛形を作成

2 scaffoldで蔵書管理機能を一気に実装する(CRUD)

基本編(select)

1 Booksテーブルにgenreカラムを追加(migration)

2 「本のジャンル」選択ボックスを作成

3 strong parameterにgenreを追加

4 一覧画面に「本のジャンル」を表示する

準備1 アプリの雛形を作成

まずはターミナルで開発用のディレクトリを作成します。
ディレクトリ名は何でも構いませんが、ここでは「rails-project」としておきます。
ディレクトリ作成後は「rails-project」に移動しておいてください。

ターミナル
$ mkdir rails-project

$ cd rails-project

[rails-project]

次にアプリの雛形を作成します。
アプリ名は「bookapp」 DBはmysqlを使用します。

ターミナル
[rails-project] $ rails new bookapp -d mysql

準備2 scaffoldで蔵書管理機能を一気に実装する

アプリの雛形ができたらscaffoldを使って蔵書管理機能を一気に実装します。
ここでは「書名」・「作者名」のみ登録可能なCRUD機能を作っていきます。

1) scaffoldで蔵書管理機能を追加(CRUD)

ターミナル
# bookappに移動
[rails-project] $ cd bookapp

# scaffoldで蔵書管理機能を追加(CRUD)
[bookapp] $ rails g scaffold book title:string author:string

# DB作成 & migrationを実行
[bookapp] $ rake db:create

[bookapp] $ rake db:migrate

[補足]

2) トップページのルーティングを設定

トップページのルーティングはbooks#indexにしておきます。

route.rb
Rails.application.routes.draw do
+ root 'books#index'
  resources :books
end

3) ブラウザでTopページの表示を確認

ここまで出来たら一度サーバを起動して表示を確認しておきましょう。

ターミナル
[bookapp] rails s

[ 初期画面 ] http://localhost:3000
image.png

[ テストデータ追加]
image.png

新規登録、編集、削除も一通り動くか、確認しておくといいかもしれません。

基本編(select)

必要な準備が一通り完了しました。ここからは蔵書管理機能に「本のジャンル」選択ボックスを追加していきます。

1 Booksテーブルにgenreカラムを追加

まずは「本のジャンル」をDBに保存できるようにmigrationファイルを追加します。

ターミナル
[bookapp] rails g migration AddGenreToBooks genre:string
migrationファイル
class AddGenreToBooks < ActiveRecord::Migration[5.2]
  def change
    add_column :books, :genre, :string
  end
end

ファイル作成完了したら、migrationを実行します。

ターミナル
[bookapp] rake db:migrate
== AddGenreToBooks: migrating ==================================
-- add_column(:books, :genre, :string)

== AddGenreToBooks: migrated  =========================

これでgenreカラムの追加は完了です。

[補足]

2 「本のジャンル」選択ボックスを作成

次は新規投稿フォームに「本のジャンル」選択ボックスを作っていきます。
現状は以下のようにtitleとauthorのみ入力できる状態です。

image.png

新規投稿フォームに以下を追加します。選択肢の例は適宜変更してください。

views/books/_form.html.erb

<%= form_with(model: book, local: true) do |form| %>
  <% if book.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(book.errors.count, "error") %> prohibited this book from being saved:</h2>

      <ul>
      <% book.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>

  <div class="field">
    <%= form.label :author %>
    <%= form.text_field :author %>
  </div>


+ <div class="field">
+  <%= form.label :genre %>
+  <%= form.select :genre, ['小説', 'プログラミング', 'ビジネス'], {include_blank: '---'} %>
+ </div>

ブラウザで確認すると以下のように選択ボックスが追加されます。

image.png

[解説]
1) selectメソッドの使い方
選択ボックス作成で一番シンプルに使えるのがselectメソッドです。

[構文]
select プロパティ名(シンボル), 選択肢(配列 or ハッシュ), {オプション}, {HTMLオプション}(id,class等)

例:<%= form.select :genre,  ['小説', 'プログラミング', 'ビジネス'],  {include_blank: '---'} %>

2) include_blankについて
選択肢にブランクを入れたい場合はselectメソッドのオプションにinclude_blankを追加します。
incliude_blank:trueとすれば選択肢にブランクが追加されます。
上記例('---')のようにブランク用の表示テキストを指定することも可能です。

3) 選択肢(配列 or ハッシュ)の違いについて
選択肢は配列orハッシュで定義できます。配列の場合、フォームのvalue属性が文字列になります。
DBにも文字列型(string)として保存されます。

HTML表示(配列の場合)
['小説', 'プログラミング', 'ビジネス']
=>
<select name="book[genre]" id="book_genre"><option value="">---</option>
  <option value="小説">小説</option>
  <option value="プログラミング">プログラミング</option>
  <option value="ビジネス">ビジネス</option>
</select>

一方で「選択肢は文字で表示したい、でもDB保存は数値で行いたい」というケースもあります。
その場合、選択肢をハッシュで定義すれば、DBに保存するvalue属性を数値(integer)にできます。

HTML表示(ハッシュの場合)
{'小説' => 1, 'プログラミング' => 2, 'ビジネス' =>3}
=>
<select name="book[genre]" id="book_genre">
  <option value="">---</option>
  <option value="1">小説</option>
  <option value="2">プログラミング</option>
  <option value="3">ビジネス</option>
</select>

3 strong parameterにgenreを追加

新たに追加した「本のジャンル」をDB保存できるようにcontrollerを編集します。
strong parameterに:genreを追加します。

books_controller.rb
private

(省略)

def book_params
-   params.require(:book).permit(:title, :author)
+   params.require(:book).permit(:title, :author, :genre)
end

4 一覧画面に「本のジャンル」を表示する

最後に一覧画面で「本のジャンル」表示欄を追加しましょう。

views/books/index.html.erb

<p id="notice"><%= notice %></p>

<h1>Books</h1>

<table>
  <thead>
  <tr>
    <th>Title</th>
    <th>Author</th>
+   <th>Genre</th>
     <th colspan="3"></th>
   </tr>
  </thead>

  <tbody>
    <% @books.each do |book| %>
      <tr>
        <td><%= book.title %></td>
        <td><%= book.author %></td>
+       <td><%= book.genre %></td>
        <td><%= link_to 'Show', book %></td>
        <td><%= link_to 'Edit', edit_book_path(book) %></td>
        <td><%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
 </table>

<br>

<%= link_to 'New Book', new_book_path %>

ここまで出来たらブラウザに接続して本のジャンル登録&一覧画面での表示ができるか確認します。

以下例のように一覧画面で本のジャンルの表示ができれば基本編は完成です。

image.png

応用編はこちら
Rails 選択ボックスの使い方 2 ー 蔵書管理アプリに「本のジャンル」を追加してみる 応用編 (collection_select)

関連記事

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5