軽く自己紹介
はじめましての方は初めまして。伊東と申します。
大卒後未経験でプログラマーになりまして、気づけば7,8年くらい働いています。
2020年3月からDMM WebCampのメンターをしています。
対象読者
- Ruby on Railsで初めてMVCフレームワークを触った
- 検証ツールでHTML要素をあまり見ない
- 初学者の方
前提
$ rails -v
Rails 5.2.4.3
$ ruby -v
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-linux]
$
Rubyのバージョン、Rails5系だよってだけです。バージョン互換などは考慮しておりませんが、書く内容はそんなに影響するような話じゃないのでは??って思っています。 authenticity_tokenの箇所でデフォルトの挙動が違うぽいです...本題というわけではないので各バージョンで調べてくださいmm
伝えたいこと
検証ツール見ていきましょうって話です。
普段からinput nameとかの属性をちゃんと見てる人は読む必要がない記事になってます。
本当に基本的なことしか書かないので悪しからず
そもそもActionView::Helpersってなに??
よく使うのはform系ではないかな?と思います。
結局htmlで出来ることをRailsがメソッドを用意してくれていて変数を使用しやすくしてくれています。
- form_with
<form></form>
- text_field_tag
<input type="text" ...>
- text_area_tag
<textarea ...></textarea>
- submit_tagなど
<input type="submit" ...>
詳しくは以下リンクから見てみてください。
https://api.rubyonrails.org/classes/ActionView/Helpers.html
事前準備
細かい説明は割愛して作っていきます。
プロジェクト作成
$: 基本的に使用するログインユーザー
#: rootユーザー(OSの管理者権限で実行している)
↑仕事し始めた頃は $
やら #
やら区別ついていなくって闇雲にsudoつけてた時代もありました...本当に止めたほうが良いです
$ rails new without_action-view-helpers # プロジェクト作成
# 省略
$ cd without_action-view-helpers/
$ rails g controller books index new # コントローラー(アクション含)作成
# 省略
$ rails g model Book title:string price:integer description:text # モデル作成
# 省略
$ rails db:migrate # DB反映
# 省略
$
ルーティングの設定
Rails.application.routes.draw do
resources :books, only: [:index, :new, :create, :show, :edit, :update]
end
$ rails routes | grep book # grepは文字列検索しています
books GET /books(.:format) books#index
POST /books(.:format) books#create
new_book GET /books/new(.:format) books#new
edit_book GET /books/:id/edit(.:format) books#edit
book GET /books/:id(.:format) books#show
PATCH /books/:id(.:format) books#update
PUT /books/:id(.:format) books#update
$
controller
めーっちゃシンプルな形。
class BooksController < ApplicationController
def index
@books = Book.all
end
def new
@book = Book.new
end
def create
book = Book.new(book_params)
book.save
redirect_to books_path
end
def show
@book = Book.find(params[:id])
end
def edit
@book = Book.find(params[:id])
end
def update
book = Book.find(params[:id])
book.update(book_params)
redirect_to books_path
end
private
def book_params
params.require(:book).permit(:title, :price, :description)
end
end
view
<h1>Books#new</h1>
<div>
<%= render 'books/form', book: @book %>
</div>
部分テンプレート化しています。
<%= form_with model: book, local: true do |f| %>
<div>
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div>
<%= f.label :price %>
<%= f.number_field :price %>
</div>
<div>
<%= f.label :description %>
<%= f.text_area :description %>
</div>
<div>
<%= f.submit :submit %>
</div>
<% end %>
ブラウザの検証ツールを使用して掘り下げて見ていきます
new
<form action="/books" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="authenticity_token" value="cgX+LsxfzE7A7F5Tm8GAlF2KdaifSdqdrWd6cOgazlcbZx8OQ4c6LazJtdRYIdPjzmfmPUGHkuBoxSQhdSqiIA==">
</form>
action?accept-charset?method?hidden?指定していない項目がいくつもでてきました。
method
methodはsubmitされた時のhttpメソッドです。
よく使われるのだと、get/post/put/patch/delete/options 辺りですね。細かい説明は割愛します。
action
actionはformタグ内のsubmitボタンがポチッとなされた時に実行されるURI(パス)を指定します。
/books
で methodがpost
になっているので、books_controllerのcreateアクションに飛ぶという仕組みです。
form_withでaction指定してなくない?
form_withを使用するときにurlの指定が無い場合はmodelからactionのpathを勝手に作ってくれています。モデル名とコントローラー名が一致している場合は 省略可能です。 model: book
と書くだけでいいので簡単ですね。
ちなみに admin
というnamespaceを使用している場合は model: [:admin, book]
としてあげれば、/admin/books
というURIを作ってくれます。便利便利
hidden
name="utf8" については調べてないです!割愛します
name="authenticity_token" についてはCSRFの対策として自動発行されているものです。他のサイトから不正なリクエストを受けないように発行してるものです。
今回は5.2系で試しているのでデフォルトで有効になっているようですがそれ以外のバージョンであれば必要に応じて設定すれば有効になります。
inputタグ
<div>
<label for="book_title">Title</label>
<input type="text" name="book[title]" id="book_title">
</div>
inputタグを見てみると
<input type="text" name="book[title]" id="book_title">
となっています。
type="text"
は単純にテキストを入力出来るという意味です。text以外にもあるのでこれ見ればわかると思います。 (詳しくはこれ: http://www.htmq.com/html5/input.shtml )
name="book[title]"
これが多分一番大事になってくると思います。Rails的にはコントローラー側で params[:book][:title]
で入力された値が取得出来るという意味になります。これを理解していれば、入力された値がDBに保存できない?みたいなことは少なくなると思います。
ちなむと、form_withではmodelが必須ではありません。なので form_with model: nil
という記載も出来てしまいます。
その場合input>nameがどうなるかというと name="title"
のようにbookが消えてしまいます。そうするとストロングパラメータと辻褄が合わなくなりバリデーションエラーなどに引っかかりrollbackというログが出るでしょう。。。
edit
<form action="/books/1" accept-charset="UTF-8" method="post">
<input type="hidden" name="_method" value="patch">
<div>
<label for="book_title">Title</label>
<input type="text" value="たーいとる" name="book[title]" id="book_title">
</div>
<div>
<input type="submit" name="commit" value="submit" data-disable-with="submit">
</div>
</form>
formタグ, hiddenタグ
action部分は action="/books/1"
になっています。model: book
で指定している変数bookが保存済みの場合URIを自動的にbook.idを設定してくれています。
hiddenタグで新規の時には無かったものが存在しています。 <input type="hidden" name="_method" value="patch">
これでhttpメソッドをpatchにしています。
なんでformタグで指定しないの??ってなると思うんですけど、多分ですがform>methodではpost/getしか指定できないからだと思います(間違ってたら指摘してもらえると )。 http://www.htmq.com/html5/form.shtml
inputタグ
<input type="text" value="たーいとる" name="book[title]" id="book_title">
value="たーいとる" という項目が増えています。これで入力部分の値を指定しています。それ以外は同じなので割愛します。
検証ツールを使うとhtmlの中身書き換えられるんですけど、valueの中身を書き換えたり遊ぶと知識の幅が増えるので常に遊び心は大事だと思います。(攻撃にならない程度に)
まとめ
HTMLも単純に画面に表示されたものを見るのではなく、どのようにHTMLが生成されているかを確認したり意識することで、HTMLであったりRailsの仕組みを少しずつ理解出来るようになっていくと思います。
閉じタグがない等でもシンタックスエラーが発生しないのがなんとも初見殺しな気もしますが、エディタにリンター入れて対策すれば問題無いですね
あまり長い文章書くの得意じゃないんですが、役に立てると嬉しく思います。。。
またお声掛け頂いたメンターの方ありがとうございます。