1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Before Rails Tutorial ポケモン図鑑をつくろう

Last updated at Posted at 2022-04-27

はじめに

本投稿は講義資料であり、Rubyの基礎は理解しているが、rails tutorialで躓く読者を対象としています。

今回作るものの完成図

ポケモン図鑑一覧ページ

スクリーンショット 2023-04-19 12.41.37.png

ポケモン詳細ページ

スクリーンショット 2023-04-19 12.42.11.png

ポケモン登録ページ

スクリーンショット 2023-04-19 12.42.37.png

今回はポケモンずかんの開発を進める中で、webサービス開発の基礎知識を学んでいきます。

講義は基本的にテキスト通りに進めますが、
講師が実際に現場で使われている経験や知識を交えながら進行していきます。
区切りの良いところで止めて、教室を見回るので詰まっている方は気軽に呼び止めてください。

目次

1章: 環境構築
2章: ポケモン図鑑をつくろう ◀ いまここ
3章: ポケモン図鑑 課題


本テキストに沿ってRailsアプリケーションを開発していきます。
その前に、Railsで開発する上で必要な知識を解説していきます。

Webページが表示される仕組み


Webフレームワーク -MVCとは

MVCに関しては後でも説明するので、いまはふわっとした理解で大丈夫です。

Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担う

MVC-02.png

例)具体的に/usersのindexページをブラウザで開くという操作を行う時

  1. ブラウザから /usersへのリクエストをRailsサーバーに送信する
  2. router によって、/usersUsers controllerindexアクションを呼び出す
  3. index アクションから、User Modelが呼び出される
  4. User ModelDataBase からデータを取り出す
  5. 取り出したデータを、Controllerに返す
  6. 受け取ったデータを@usersに保存し、 View (indexアクションなので index.html.erb) に渡す。
  7. ERBを実行し、@usersのデータを含んだ HTMLを生成し、Controllerへ返す
  8. Controllerは、受け取ったHTMLをブラウザにわたす

今後もModel View Controller を構築していくので、適宜図を見返してください。

下準備

1. CSSフレームワークを導入してみよう

単にプログラムを書いても、味気ないデザイン(というかデザインがない状態)なので、CSSフレームワークを導入してそれっぽくしてみましょう。
今回はBulmaというCSSフレームワークを使用します。
CSSとは?
Bulma 公式サイト

erbファイルに追記する

app/views/layouts/application.html.erbのコードをすべて削除して下記のコードを丸々コピー&ペーストしてください。

goorm内左側から
pokemon_zukanフォルダをクリック
appフォルダをクリック
layoutsフォルダをクリック
application.html.erbをクリックすると中央にエディタ(コードを書く場所)が出るので、ここで編集してください。
編集後は必ず保存をしましょう。
スクリーンショット 2022-06-28 13.55.18.png

app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>PokemonZukan</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
     <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
     <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

2.Font Awesomeの導入

無料で使えるwebフォントアイコンを導入しましょう。

webフォントアイコンとは

HTMLのタグや特有のクラス名を付与することで、簡単にWebサイト上にアイコンを表示できるサービス。
フォントとしてアイコンを利用することができるので、CSSで簡単にサイズや色を変更できるため、使い勝手にも優れている。

font-awesome-sassというgemを使用するので、
Gemfileの27行目
# gem 'image_processing', '~> 1.2'の下に
gem 'font-awesome-sass'を追加しましょう。

Gemfile(下記の1行を追記してください)
gem 'font-awesome-sass'

スクリーンショット 2023-04-14 15.56.55.png
追加したらbundle installをします。

terminal
$ bundle install

▶︎ run new ruby on Railsを実行したまま、コマンドを実行したい場合、
新しくターミナルを開く必要があります。
goorm内上部のWINDOW > New Terminal Window(一番上)をクリックすると起動します。
スクリーンショット 2023-04-19 1.11.13.png

Bundle complete! 18 Gemfile dependencies, 76 gems now installed.
Use bundle info [gemname] to see where a bundled gem is installed.

と緑文字で表示されるとインストール完了です。

stylesheetの編集

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f33333039322f63346663623263392d393634302d373533622d336462352d3432613937356430626436312e706e67.png

pokemon_zukanをクリック > appをクリック > assetsをクリック > stylesheetsをクリック > application.cssを右クリックして名前を変更をクリックし
画像の様にapplication.scssに変更してください。
(現時点で、同じ階層にあるpokemons.scssが皆さんは無いと思いますが、気にしないでください。あとで作ります。)

名前変更したapplication.scssを開き、
◯行目に下の1行を追加します。

app/assets/stylesheets/application.scss
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */

@import 'font-awesome'; // これを追加する

3.画像アップロードの準備

アプリケーションにポケモンの画像を投稿する機能を追加したいので、
Rails5.2より追加されたActive Strageという公式で公開されたファイルアップロード機能を使用します。
Active Storageについての説明

ImageMagickを導入

ターミナルで下記のコマンドを1行ずつ実行してください。
(どのコマンドでかを書く)途中でDo you want to continue? [Y/n]と聞かれます。Yを入力してください。

terminal(1行ずつ実行してください)
$ sudo apt-get update
$ sudo apt-get install libmagickwand-dev
$ sudo apt-get install imagemagick --fix-missing

Active Strageのインストール

Active StrageをRailsアプリケーションに追加します。
ターミナルで下記のコマンド1行ずつ実行してください。

terminal(1行ずつ実行してください)
$ rails active_storage:install
$ rails db:migrate

Gemfileの編集

Gemfileの27,28行目あたり(先程追加したgem 'font-awesome-sass'の下)に下記を追加して、bundle installをしてください。

Gemfile(下記の2行を追記してください)
gem 'mini_magick'
gem 'image_processing', '~> 1.2'

スクリーンショット 2023-04-19 1.56.42.png

terminal(ターミナルで実行してください)
$ bundle install

ここでも
Bundle complete! (以下省略)

と表示されていたらOKです

新たにgemを入れたあとはサーバーを起動し直しましょう。
でないと、追加したgemが反映されません。

▶ new run ruby on Railsを実行してるターミナルでCtrl + C でサーバーを止めてから
もう一度▶ new run ruby on Railsを押してください

3. protect_from_forgeryの追加

RailsのCSRF対策について
app/controllers/application_controller.rbの◯行目にprotect_from_forgeryを追記してください。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
 protect_from_forgery # これを追加する
end

これで下準備は完了です。
次にページを作っていきます。

下準備をしたファイルの完成形を折りたたみで書く

ページを作成する方法

ポケモン図鑑一覧ページ

スクリーンショット 2023-04-19 12.41.37.png

ポケモン詳細ページ

スクリーンショット 2023-04-19 12.42.11.png

ポケモン登録ページ

スクリーンショット 2023-04-19 12.42.37.png

ページを作成するにはcotrollerとviewが必要になります。

Controller と View の作成

作成は基本的に generate コマンドを用います。
(gは generateコマンドの短縮形です)
gの後は、controller に続けて、コントローラーの名前(複数形)を書きます。
rails g controller Pokemons index show new
そのうしろ(引数といいます)に書いたもの(index,show,new)は、
同名のviewとアクションが自動生成されます。
(Viewは views/pokemons の中に、アクションは apppokemons_controller.rbの中に生成)

tarminal
$ rails g controller Pokemons index show new
     create    app/controllers/pokemons_controller.rb
     route     get 'pokemons/index'
               get 'pokemons/show'
               get 'pokemons/new'
     create    app/views/pokemons
     create    app/views/pokemons/index.html.erb
     create    app/views/pokemons/show.html.erb
     create    app/views/pokemons/new.html.erb

先程のrails g ...コマンドでルーティングが生成されているので、確認してみましょう。
確認するにはrails routesコマンドを実行します。

terminal
$ rails routes #実行してしばらくすると下記ルーティングが出てきます
  Verb  URI                Pattern
  GET   /pokemons/index    pokemons#index
  GET   /pokemons/show     pokemons#show
  GET   /pokemons/new      pokemons#new

これは具体的には、 http://localhost:3000/pokemons/index
というURLに対するリクエスト1があれば、 pokemons_controllerindex アクションを呼び出すというものでした。
今回indexアクションの中身が空なので、Model は呼び出されず、単に対応するView (index.html.erb) が実行されるだけです。(図の3,4,5の部分が素通りされます)

ルーティングがうまくいってみるか確認するために、試しにアクセスしてみましょう。
(サーバーを起動していない場合は▶new run ruby on Railsをクリックして起動してください)

https://[pokemon_zukan-[id(人によって文字列は異なります)]].run.goorm.site/の続きに
pokemons/indexを追記します。

スクリーンショット 2023-04-19 2.01.34.png

このように表示されていることを確認してください
ここで準備したCSSフレームワークが適用されているか確認してください。
(画像と同じスタイルになっていたら正しく適用されています。)

imagesフォルダ内の画像(10枚)をapp/assets/imagesフォルダ内に移動させてください。
フォルダごとではなく中にある画像10枚を移動させてください。

デザインの変更

pokemons.scssを編集します。

"▶"をクリックしてscssファイルを丸々コピー&ペーストしてください
app/assets/stylesheets/pokemons.scss
// =====  Pokemon/show ===== //
.pokemon-name {
  background-color: #344e67;
  color: #f2f5ec;
  font-size: 25px;
  line-height: 65px;
}

.p-type {
  display:inline;
  font-size: 20px;
  margin: 3em;  
}

.p-description {
  background-color: #fff;
  color: #283b4f;
  font-size: 20px;
  line-height: 1.5;  
  padding: 50px;
}

.pokemon-card {
  background-color: #fff;
  display: table;
  padding: 20px;
}

.p-name {
  display: table-cell;
  vertical-align: middle;
}

.vertical-middle {
  display: inline-block;
  vertical-align: middle;
}

.p-edit {
  margin-top: 110px;
  
  a {
    font-size: 16px;
    display:inline;
    margin-top: 60px;
  }
}

.alert {
  background-color: #ffebe8;
  border: 2px solid #990000;
  color: #262626;
  font-weight: 850;
  text-align: center;
  padding: 12px;
}

Viewの変更

元々あるダミー文を変更してみましょう。
app/views/pokemons/index.html.erbにあるコードをすべて削除し、
下記を追記してください。

app/views/pokemons/index.html.erb
<h1 class="title has-text-centered">ポケモンいちらん</h1>

erb の中身がシンプルすぎて不思議な方もいらっしゃるかもしれません。
【気になって次にすすめない人向けの解説】
app/views/layouts/application.html.erb を開いてください。
コード内の= yieldの部分に、index.html.erbが移植されて HTML を生成しています。 
今はこの程度の理解で問題ありません。
https://railstutorial.jp/ でより深く理解できます

Controllerの変更

コントローラーの中にアクションが本当に作られているかも確認してみましょう。
app/controllers/pokemons_controller.rb を開いてみてください。

app/controllers/pokemons_controller.rb
class PokemonsController < ApplicationController
  def index
  end

  def show
  end

  def new
  end
end

データベース内のデータを取り出すには、Controllerのアクション内で
Model を呼び出すと取りだすことができます。

app/controllers/pokemons_controller.rb
class PokemonsController < ApplicationController
  def index
  end

  def show
    @pokemon = Pokemon.find(1) # これを追記
  end

  def new
  end
end

しかし、このままpokemons/showにアクセスしても
uninitialized constant PokemonsController::Pokemonというエラーがでます。
image.png

(Modelも、ポケモンの情報も作っていないからです)

ですので、次はgenerateコマンドを使用して、Modelを作成していきます。

情報のやりとり(データベース) の使用方法

Modelの作成

pokemonsテーブルには、
ポケモンの名前(name)
図鑑番号(number)
ポケモンのタイプ(zokusei)
ポケモンの説明(description)
ポケモンの画像(image)
を持たせていきます。

g の後は、model に続けて、Model名(単数形)、そして項目(カラムといいます)を書きます。

コマンドプロンプト
> rails g model Pokemon name:string number:integer zokusei:string description:text image:attachment
      invoke  active_record
      create    db/migrate/20220426050238_create_pokemons.rb
      create    app/models/pokemon.rb
      invoke    test_unit
      create      test/models/pokemon_test.rb
      create      test/fixtures/pokemons.yml

作成・編集したマイグレーションファイルはターミナルでrails db:migrateを実行すると読み込まれ、データベースに反映されます。
rails db:migrateを実行しましょう。

terminal
>  rails db:migrate
== 20220426050238 CreatePokemons: migrating ===================================
-- create_table(:pokemons)
   -> 0.0052s
== 20220426050238 CreatePokemons: migrated (0.0058s) ==========================

db/migrate/(作成日時)_create_pokemons.rb というファイルを見てみましょう。
開いてみると、下記のようなコードがあると思います。

[作成日付]_create_pokemons.rb
class CreatePokemons < ActiveRecord
  def change
    create_table :pokemons do |t|
      t.string :name
      t.integer :number
      t.string :zokusei
      t.text :description
      t.timestamps
    end
  end
end

上記は string型であるnameというカラム(他5つ)を持つ pokemons テーブルを作成せよという意味です。 change 意外に up down などもあります。詳細は下記サイトなどを参照ください
【Rails入門】データベースを設定するrails db:migrateを説明!


これでpokemonsテーブルが作成されました。

テーブルは作成したけども、ポケモンの情報はまだ何もいれてませんね。
初期データをいれるにdb:seed.rbファイルを使用します。
( seed = 種 という意味です )
大量のデータを入力するのは手間なのでseed.rbを作成していきます。
(そもそもブラウザからデータをいれる機能もまだ作っていません)

seed.rbを編集しましょう。

`▶`をクリックしてソースコードを開き、 丸々コピー&ペーストしてください
db/seeds.rb
pokemon = Pokemon.create!(name: "フシギダネ",
						 zokusei: "くさ",
						 number: 1,
						 description: "うまれてから しばらくの あいだは せなかの タネから えいようを もらって おおきく そだつ。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/hushigidane.png')),
                  filename: 'hushigidane.png')

pokemon = Pokemon.create!(name: "フシギソウ",
						 zokusei: "くさ",
						 number: 2,
						 description: "せなかの つぼみが ふくらみだすと あまい においが ただよいはじめる。たいりんの はなが さく まえぶれ。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/hushigisou.png')),
                  filename: 'hushigisou.png')

pokemon = Pokemon.create!(name: "フシギバナ",
						 zokusei: "くさ",
						 number: 3,
						 description: "あめの ふった よくじつは せなかの はなの かおりが つよまる。かおりに さそわれ ポケモンが あつまる。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/hushigibana.png')),
                  filename: 'hushigibana.png')


pokemon = Pokemon.create!(name: "ヒトカゲ",
						 zokusei: "ほのお",
						 number: 4,
						 description: "ヒトカゲの ほのおの しっぽは いのちの ともしび。 げんきなときは ほのおも ちからづよく もえあがる。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/hitokage.png')), filename:'hitokage.png')

pokemon = Pokemon.create!(name: "リザード",
						 zokusei: "ほのお",
						 number: 5,
						 description: "リザードが くらす いわやまを よなかに みあげると しっぽの ほのおが ほしのように みえる。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/riza-do.png')), filename:'riza-do.png')

pokemon = Pokemon.create!(name: "リザードン",
						 zokusei: "ほのお",
						 number: 6,
						 description: "くるしい たたかいを けいけんした リザードンほど ほのおの おんどが たかくなると いわれている。
")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/riza-don.png')), filename:'riza-don.png')



pokemon = Pokemon.create!(name: "ゼニガメ",
						 zokusei: "みず",
						 number: 7,
						 description: "こうらに とじこもり みを まもる。 あいての すきを みのがさず みずを ふきだして はんげきする。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/zenigame.png')),
                  filename: 'zenigame.png')

pokemon = Pokemon.create!(name: "カメール",
						 zokusei: "みず",
						 number: 8,
						 description: "いちまんねんの じゅみょうを もつと いわれている。ふさふさの しっぽは ながいきの シンボルとして にんき。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/zenigame.png')),
                  filename: 'kame-ru.png')

pokemon = Pokemon.create!(name: "カメックス",
						 zokusei: "みず",
						 number: 9,
						 description: "こうらの ふんしゃこうの ねらいは せいかく。みずの だんがんを 50メートル はなれた あきかんに めいちゅうさせる ことが できるぞ。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/kamekkusu.png')),
                  filename: 'kamekkusu.png')


pokemon = Pokemon.create!(name: "イーブイ",
						 zokusei: "ノーマル",
						 number: 133,
						 description: "しんかのとき すがたと のうりょくが かわることで きびしい かんきょうに たいおうする めずらしい ポケモン。")
pokemon.image.attach(io: File.open(Rails.root.join('app/assets/images/i-bui.png')),
                  filename: 'i-bui.png')

そしてデータの読み込みをrails db:seedで行います。

コマンドプロンプト
> rails db:seed

データが保存されたかの確認はrails cでコンソールを起動すると確認できます。

コマンドプロンプト
> rails c
unning via Spring preloader in process 6309
Loading development environment (Rails 6.0.3.2)
irb(main):001:0>

このような文字が表示されたらコンソールは起動されています。
irb(main):001:0>に下記のコマンドを入力していきます。

(irb(main):001:0に以下のコマンドを入力して実行してください)
p = Pokemon.find(1)

フシギダネの情報がimage以外表示されていればOKです
スクリーンショット 2023-04-19 12.17.52.png

コンソールから出る場合はexitを入力すると戻る事が出来ます。

フシギダネの情報をページ上で表示させたいので、
app/views/pokemons/show.html.erbを下記のように編集しましょう。

app/views/pokemons/show.html.erb
<div class="pokemon-name">
  <div class="container">
    <p style="display: inline; padding-left: 40px;">
      NO.<%= @pokemon.number %>
      <%= @pokemon.name%>
    </p>
        
    <p class="p-type">
      <%= @pokemon.zokusei %>
    </p>
  </div>
</div>

<div class="columns">
      <div class="column is-4">
        <div class="pokemon-img">
          <%= image_tag @pokemon.image %>
        </div>
     </div>
    
      <div class="column is-8">
        <div class="p-description">
          <%= @pokemon.description %>
        </div>
      </div>
    </div>
  </div>
</div>

https://pokemon-zukan-[ランダムな文字列].run.goorm.site/pokemons/show
にアクセスしてください。
フシギダネの情報が表示されたかと思います。
スクリーンショット 2023-04-19 12.28.06.png

URLからパラメーターの取得

ポケモンのデータを取り出して表示するところまでうまくいきました!
すごい進歩です!

ただ、まだ不満点があります。
それは、 id:1 のポケモンのデータしか表示できていない点です。
理由は、Contoroller の show アクションをみると、
@pokemon = Pokemon.find(1)
となっているためです(id:1 のポケモンの情報しか見つけてきていない)

ここをidパラメーターが1以外も入力できるように変更するにはどうすればよいでしょうか。
@pokemon = Pokemon.find(params[:id])
とすることで、1以外のパラメーターを見つけてこれます。

app/controllers/pokemons_controller.rb
 def show
   @pokemon = Pokemon.find(params[:id]) # 変更する
 end

パラメーター(数値)は、どこで指定すればよいでしょうか。
URLにパラメーターを含めて渡すテクニックがあるので覚えておきましょう。
例)IDが2のポケモンの情報を取得したい場合 
https://pokemon-zukan-[ランダムな文字列].run.goorm.site/pokemons/show/2
  このままではルーティングエラーが表示されます。
  pokemons/show へのリクエストに関しては記述していますが、
  pokemons/show/(数字) へのリクエストについては何も書いていない為です。

config/routes.rb を開いてください。
URLに含まれる数字をパラメーターとして取得するには、下記のように記述します。

config/routes.rb
Rails.application.routes.draw do
  get 'pokemons/index'
  get 'pokemons/show/:id', to:'pokemons#show', as: 'pokemon' # 変更する
  get 'pokemons/new'

end

こうすることで /pokemons/show/2 の 2の部分が、:id パラメーターとして利用可能になります。
( 利用するときは、params[:id] と書きます)

index と new は to: が書かれていませんね。
前章でも説明したとおり、Railsは、アクションが呼び出されると、
自動的に アクション名.html.erbが呼び出されるので、
下記と同じ意味になります。
get 'pokemons/index' to: 'pokemonss#index'
get 'pokemons/new', to: 'pokemons#new'

to: 'pokemons#show' 
pokemonsコントローラーの show アクションを呼び出す指示になります。

これで、任意のidのポケモンの情報を取得できるようになりました。

/pokemons/show/2

スクリーンショット 2023-04-19 12.31.03.png

pokemons/show/3

スクリーンショット 2023-04-19 12.31.53.png

Model 検索

今ポケモンの情報の取り出しに id を利用していますが、
id 以外のカラムを用いて取り出す方法も覚えておくと便利です。

コンソールを起動してください。 ( ターミナルでrails cで起動 )
下記を参考に色々と試してみてください。

railsコンソール
>> Pokemon.all
   #pokemonテーブルのすべてのデータを取得します。
>> Pokemon.find_by(name: "ヒトカゲ")
   #条件に合ったデータを、1件だけ取得します。
>> Pokemon.where(zokusei: "みず")
   #条件に合ったデータを、すべて取得します。
>> Pokemon.where(zokusei: "みず").where(number: 7)
   #AND検索。 みずタイプで ずかん番号番を取得しています。
>> Pokemon.where("(zokusei = ?) OR (number = ?)","みず",7)
   #OR検索。 みずタイプ または ずかん番号7番のポケモンを取得しています。
>> Pokemon.order(create_at: :asc)
   #並び順を指定します。 作成日時の昇順で取得しています。

データ登録フォームの作成

データベースから情報を取り出したり加工したりする方法は覚えました。
しかしこのままではポケモンを登録することができません。

ポケモンを登録するための機能を作成する方法を学んでいきましょう。
form_withを使用します。

form_with

参考↓
【Rails】 form_withの使い方を徹底解説!

データベースに新しいデータを保存したいので、 Model を呼び出します。
app/views/pokemons/new.html.erbに登録フォームを置きたいので、
pokemons_controller.rbのnewアクション内に書きましょう。
新しいデータを登録するときは、 Model名.new とします。下記のコードを追記してください。

app/controllers/pokemons_controller.rb
  # (中略)
  def new
    @pokemon = Pokemon.new # これを追加する
  end

new.html.erbに入力フォームを作成していきましょう。
railsでは、フォームを簡単につくれるform_withヘルパーというものがあります。

app/views/pokemons/new.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: { action: :create }, 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ヘルパーにより、下記のような HTML が生成されます。(少しシンプル化してます)

<form action="/pokemons" accept-charset="UTF-8" data-remote="true" method="post">
  <input type="hidden" name="authenticity_token" value="Nbbcp8B2ekJyks0THuIdAQcyafXQJdj7reyZeAkZbkLreXymKvbIwE6rL9pXcN58G2ZOrdlWFDHz5uXAkMNNqQ==">
        <div class="field">
          <label class="label" for="pokemon_name">なまえ</label>
          <div class="control">
            <input class="input" type="text" name="pokemon[name]" id="pokemon_name">
          </div>
        </div>
        <div class="field">
          <label class="label" for="pokemon_number">ばんごう</label>
          <div class="control">
            <input class="input" type="text" name="pokemon[number]" id="pokemon_number">
          </div>
        </div>
          
        <div class="field">
          <label class="label" for="pokemon_zokusei">タイプ</label>
          <div class="control">
            <input class="input" type="text" name="pokemon[zokusei]" id="pokemon_zokusei">
          </div>
        </div>
        
        <div class="field">
          <label class="label" for="pokemon_description">せつめい</label>
          <div class="control">
            <textarea class="textarea" name="pokemon[description]" id="pokemon_description"></textarea>        
        </div>
        
         <div class="field">
          <div class="file">
            <label class="file-label">
              <%= f.file_field :image, class: 'file-input'%>
              <span class="file-cta">
                <span class="file-label">
                がぞうをえらんでください
                </span>
              </span>
            </label>
          </div>
        </div>
        <input type="submit" name="commit" value="登録" class="button is-link" data-disable-with="登録">
    </div></form>

ここで重要な属性は、
<form action="/pokemons" accept-charset="UTF-8" data-remote="true" method="post">
の中の、 action="/pokemons"method="post" の2つです。

この2つは送信ボタンが押されたら、
/pokemons に対して、 POST リクエストを送信する
という指示をしています。

なので、 /pokemons に対して、 POST リクエストがあった場合の処理を書いていきましょう。
送信したあとは、pokemons_controller の create アクションに飛ばしたいです。
(後ほどデータベースに保存する処理を create アクションに書いていきます)

post 'pokemons', to: 'pokemons#create'
コードはこのようになるので、 routes.rb に追記しましょう。

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'  # 追記する
end

1. 登録ボタンが押される
2. フォームに入力されたデータを、create アクションに飛ばす

という流れで、データが動いているので最後に、
create アクションの中で情報をデータベースに保存する処理を書きます。Modelを呼び出します。

Parameters: {...(中略)... "pokemon"=>{"name"=>"フシギダネ", "number"=>"1", "zokusei"=>"くさ", "description"=>"(中略)"

パラメーターをみると、二重の連想配列になっているのがわかると思います。
( parameters{} の中に pokemon{} が入っている )

通常の連想配列の場合は、params[:title] として取得できていました。
二重の連想配列の場合は、params[:pokemon][:title] とすることで取得できます。
pokemonキー の中のtitleキー のデータを取得しています )
 連想配列について詳しくはこちらを参照してください Array(配列)とHash(連想配列)入門

さて、ここまで理解できていれば create アクションの中身も想像できると思います。
( seed.rb の、ポケモンの情報が書かれていた部分をパラメーターの中身に書き換えるだけです )
def new ~ endの下に下記を追記してください

app/controllers/pokemons_controller.rb
(中略)
def create
    @pokemon = Pokemon.new
    @pokemon.name = params[:pokemon][:name]
    @pokemon.zokusei = params[:pokemon][:zokusei]
    @pokemon.number = params[:pokemon][:number]
    @pokemon.description  = params[:pokemon][:description]
    @pokemon.image = params[:pokemon][:image]
    @pokemon.save
    redirect_to @pokemon
end

最後の、redirect_to '/pokemons/show/1' の部分ですが、
登録ボタンを押したあとに、画面遷移してほしいので、リダイレクト先を指定しました。

https://pokemon-zukan-[ランダムな文字列].run.goorm.site/pokemons/new ここでポケモンの情報を登録
スクリーンショット 2023-04-19 12.32.59.png

https://pokemon-zukan-[ランダムな文字列].run.goorm.site/pokemons/show/[ID]
ここで登録内容を確認

このままでは自由にポケモンを登録できる状態です。
numberは数値を入力してもらいたいので入力制限をかけてみましょう。

Rails では制限(validation)も簡単に設定することができます。

バリデーション

バリデーションとは

データを保存する前に、無効なデータでないことを検証する機能のこと。門番みたいなもの。
空のデータが保存されないようにしたり、数字以外は保存できないようにしたり、文字数に制限を設けたり、保存するデータに制限をかける時に使います。

app/models/pokemon.rb を開き、
下記の2行をclass Pokemon ~~ endの間に入力してください。

numericality: true
属性に数値のみが使われている事を検証する
presence: true
必須項目にする

app/models/pokemon.rb
class Pokemon < ApplicationRecord
  has_one_attached :image
  validates :name, :image,  presence: true # 追記する
  validates :number, numericality: true # 追記する
end

これだけで制限を設けることができます。

次にpokemons_controller.rbcreateメソッドを編集します

app/controllers/pokemons_controller.rb
def create
  @pokemon = Pokemon.new
  @pokemon.name = params[:pokemon][:name]
  @pokemon.zokusei = params[:pokemon][:zokusei]
  @pokemon.number = params[:pokemon][:number]
  @pokemon.description  = params[:pokemon][:description]
  @pokemon.image = params[:pokemon][:image]
  @pokemon.save
  if @pokemon.save
	redirect_to controller: :pokemons, action: :index
  else
    render "new"
  end
end

Pokemon Model に追記しているので、 pokemons テーブルの numberカラムに対して制限をかけます。
実際に試してみると、ポケモンいちらんに登録されていません。

これでポケモンのばんごうを数値以外入力して保存すると
上部にメッセージが出ます。
そして数値を入力して保存するとポケモンいちらんページに遷移先します
スクリーンショット 2022-06-28 16.42.58.png

ポケモン一覧ページの作成

しかし、これだとポケモンを登録しても
遷移先の https://pokemon-zukan-[ランダムな文字列].run.goorm.site/pokemons/index は何も表示されていません
最後に登録したポケモンを一覧するページを作成しましょう。

まずはコントローラーの編集です。
先程コンソールでPokemon.allを実行するとすべてのポケモンが表示されましたね。
それを利用しましょう。

app/controllers/pokemons_controller.rb
class PokemonsController < ApplicationController
  def index
    @pokemons = Pokemon.all # これを追加する
  end
# (省略)

ビューの編集

app/views/pokemons/index.html.erbを編集しましょう。

app/views/pokemons/index.html.erb
<div class="container mt-6">
  <h1 class="title has-text-centered"> ポケモンいちらん </h1>
  <div class="columns is-multiline">
    <% @pokemons.each do |p| %>
      <div class="column is-one-quarter">
        <div class="pokemon-card">
          <%= image_tag p.image.variant(resize_to_limit: [100, 100])%>
          <div class="p-name">
            <p> NO. <%= p.number %> </p>
            <p class="vertical-middle"><%= link_to p.name, pokemon_path(p) %></p>
          </div>
        </div>
      </div>
      <% end %>
  </div>
</div>

スクリーンショット 2023-04-19 12.39.04.png

このようにseed.rbで入れたデータや自分で入力したデータが表示されていれば完成です、お疲れ様でした!

ポケモン図鑑一覧ページ

スクリーンショット 2023-04-19 12.41.37.png

ポケモン詳細ページ

スクリーンショット 2023-04-19 12.42.11.png

ポケモン登録ページ

スクリーンショット 2023-04-19 12.42.37.png

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?