はじめに
本投稿は講義資料であり、Rubyの基礎は理解しているが、rails tutorialで躓く読者を対象としています。
今回作るものの完成図
ポケモン図鑑一覧ページ
ポケモン詳細ページ
ポケモン登録ページ
今回はポケモンずかんの開発を進める中で、webサービス開発の基礎知識を学んでいきます。
講義は基本的にテキスト通りに進めますが、
講師が実際に現場で使われている経験や知識を交えながら進行していきます。
区切りの良いところで止めて、教室を見回るので詰まっている方は気軽に呼び止めてください。
目次
1章: 環境構築
2章: ポケモン図鑑をつくろう ◀ いまここ
3章: ポケモン図鑑 課題
本テキストに沿ってRailsアプリケーションを開発していきます。
その前に、Railsで開発する上で必要な知識を解説していきます。
Webページが表示される仕組み
Webフレームワーク -MVCとは
MVCに関しては後でも説明するので、いまはふわっとした理解で大丈夫です。
Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担う
例)具体的に/usersのindexページをブラウザで開くという操作を行う時
- ブラウザから
/users
へのリクエストをRailsサーバーに送信する -
router
によって、/users
はUsers controller
のindex
アクションを呼び出す -
index
アクションから、User Model
が呼び出される -
User Model
はDataBase
からデータを取り出す - 取り出したデータを、
Controller
に返す - 受け取ったデータを
@users
に保存し、 View (indexアクションなので index.html.erb) に渡す。 - ERBを実行し、
@users
のデータを含んだ HTMLを生成し、Controller
へ返す -
Controller
は、受け取ったHTMLをブラウザにわたす
今後もModel View Controller を構築していくので、適宜図を見返してください。
下準備
1. CSSフレームワークを導入してみよう
単にプログラムを書いても、味気ないデザイン(というかデザインがない状態)なので、CSSフレームワークを導入してそれっぽくしてみましょう。
今回はBulmaというCSSフレームワークを使用します。
CSSとは?
Bulma 公式サイト
erbファイルに追記する
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'
を追加しましょう。
gem 'font-awesome-sass'
$ bundle install
Bundle complete! 18 Gemfile dependencies, 76 gems now installed.
Use bundle info [gemname]
to see where a bundled gem is installed.
と緑文字で表示されるとインストール完了です。
stylesheetの編集
pokemon_zukanをクリック > appをクリック > assetsをクリック > stylesheetsをクリック > application.css
を右クリックして名前を変更
をクリックし
画像の様にapplication.scss
に変更してください。
(現時点で、同じ階層にあるpokemons.scssが皆さんは無いと思いますが、気にしないでください。あとで作ります。)
名前変更したapplication.scss
を開き、
◯行目に下の1行を追加します。
/*
* 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を入力してください。
$ sudo apt-get update
$ sudo apt-get install libmagickwand-dev
$ sudo apt-get install imagemagick --fix-missing
Active Strageのインストール
Active StrageをRailsアプリケーションに追加します。
ターミナルで下記のコマンド1行ずつ実行してください。
$ rails active_storage:install
$ rails db:migrate
Gemfileの編集
Gemfileの27,28行目あたり(先程追加したgem 'font-awesome-sass'
の下)に下記を追加して、bundle install
をしてください。
gem 'mini_magick'
gem 'image_processing', '~> 1.2'
$ 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を追記してください。
class ApplicationController < ActionController::Base
protect_from_forgery # これを追加する
end
これで下準備は完了です。
次にページを作っていきます。
下準備をしたファイルの完成形を折りたたみで書く
ページを作成する方法
ポケモン図鑑一覧ページ
ポケモン詳細ページ
ポケモン登録ページ
ページを作成するには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の中に生成)
$ 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
コマンドを実行します。
$ 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_controller のindex アクションを呼び出すというものでした。
今回indexアクションの中身が空なので、Model は呼び出されず、単に対応するView (index.html.erb) が実行されるだけです。(図の3,4,5の部分が素通りされます)
ルーティングがうまくいってみるか確認するために、試しにアクセスしてみましょう。
(サーバーを起動していない場合は▶new run ruby on Railsをクリックして起動してください)
https://[pokemon_zukan-[id(人によって文字列は異なります)]].run.goorm.site/の続きに
pokemons/index
を追記します。
このように表示されていることを確認してください
ここで準備したCSSフレームワークが適用されているか確認してください。
(画像と同じスタイルになっていたら正しく適用されています。)
imagesフォルダ内の画像(10枚)をapp/assets/imagesフォルダ内に移動させてください。
フォルダごとではなく中にある画像10枚を移動させてください。
デザインの変更
pokemons.scss
を編集します。
"▶"をクリックして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
にあるコードをすべて削除し、
下記を追記してください。
<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 を開いてみてください。
class PokemonsController < ApplicationController
def index
end
def show
end
def new
end
end
データベース内のデータを取り出すには、Controllerのアクション内で
Model を呼び出すと取りだすことができます。
class PokemonsController < ApplicationController
def index
end
def show
@pokemon = Pokemon.find(1) # これを追記
end
def new
end
end
しかし、このままpokemons/show
にアクセスしても
uninitialized constant PokemonsController::Pokemonというエラーがでます。
(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
を実行しましょう。
> rails db:migrate
== 20220426050238 CreatePokemons: migrating ===================================
-- create_table(:pokemons)
-> 0.0052s
== 20220426050238 CreatePokemons: migrated (0.0058s) ==========================
db/migrate/(作成日時)_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を編集しましょう。
`▶`をクリックしてソースコードを開き、 丸々コピー&ペーストしてください
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>
に下記のコマンドを入力していきます。
p = Pokemon.find(1)
コンソールから出る場合はexitを入力すると戻る事が出来ます。
フシギダネの情報をページ上で表示させたいので、
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
にアクセスしてください。
フシギダネの情報が表示されたかと思います。
URLからパラメーターの取得
ポケモンのデータを取り出して表示するところまでうまくいきました!
すごい進歩です!
ただ、まだ不満点があります。
それは、 id:1 のポケモンのデータしか表示できていない点です。
理由は、Contoroller の show アクションをみると、
@pokemon = Pokemon.find(1)
となっているためです(id:1 のポケモンの情報しか見つけてきていない)
ここをidパラメーターが1以外も入力できるように変更するにはどうすればよいでしょうか。
@pokemon = Pokemon.find(params[:id])
とすることで、1以外のパラメーターを見つけてこれます。
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に含まれる数字をパラメーターとして取得するには、下記のように記述します。
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
pokemons/show/3
Model 検索
今ポケモンの情報の取り出しに id を利用していますが、
id 以外のカラムを用いて取り出す方法も覚えておくと便利です。
コンソールを起動してください。 ( ターミナルでrails c
で起動 )
下記を参考に色々と試してみてください。
>> 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 とします。下記のコードを追記してください。
# (中略)
def new
@pokemon = Pokemon.new # これを追加する
end
new.html.erb
に入力フォームを作成していきましょう。
railsでは、フォームを簡単につくれるform_with
ヘルパーというものがあります。
<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 に追記しましょう。
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
の下に下記を追記してください
(中略)
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 ここでポケモンの情報を登録
https://pokemon-zukan-[ランダムな文字列].run.goorm.site/pokemons/show/[ID]
ここで登録内容を確認
このままでは自由にポケモンを登録できる状態です。
numberは数値を入力してもらいたいので入力制限をかけてみましょう。
Rails では制限(validation)も簡単に設定することができます。
バリデーション
バリデーションとは
データを保存する前に、無効なデータでないことを検証する機能のこと。門番みたいなもの。
空のデータが保存されないようにしたり、数字以外は保存できないようにしたり、文字数に制限を設けたり、保存するデータに制限をかける時に使います。
app/models/pokemon.rb を開き、
下記の2行をclass Pokemon ~~ end
の間に入力してください。
numericality: true
属性に数値のみが使われている事を検証する
presence: true
必須項目にする
class Pokemon < ApplicationRecord
has_one_attached :image
validates :name, :image, presence: true # 追記する
validates :number, numericality: true # 追記する
end
これだけで制限を設けることができます。
次にpokemons_controller.rb
のcreate
メソッドを編集します
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カラムに対して制限をかけます。
実際に試してみると、ポケモンいちらんに登録されていません。
これでポケモンのばんごうを数値以外入力して保存すると
上部にメッセージが出ます。
そして数値を入力して保存するとポケモンいちらんページに遷移先します
ポケモン一覧ページの作成
しかし、これだとポケモンを登録しても
遷移先の https://pokemon-zukan-[ランダムな文字列].run.goorm.site/pokemons/index は何も表示されていません
最後に登録したポケモンを一覧するページを作成しましょう。
まずはコントローラーの編集です。
先程コンソールでPokemon.all
を実行するとすべてのポケモンが表示されましたね。
それを利用しましょう。
class PokemonsController < ApplicationController
def index
@pokemons = Pokemon.all # これを追加する
end
# (省略)
ビューの編集
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>
このようにseed.rb
で入れたデータや自分で入力したデータが表示されていれば完成です、お疲れ様でした!