こんにちは! フリーエンジニアの長瀬です。
みなさんはform_tag、form_forを使っていますか?
form_tagやform_forを使えば、簡単に入力フォーム実装できて、便利です。
この記事では、form_tagやform_forの使い方について
・form_tagとは
・form_tagの基本構文
・form_forの基本構文
という基本的な内容から、
・form_tagに関連するビューヘルパー
・form_tagとform_forの使い分け
といった応用的な内容についても解説していきます。
form_tagの基本的な使い方
form_tagとは
form_tagはActionView::Helpersを継承したヘルパーの1つです。
Ruby on RailsはMVC(Model、View、Controller)に基づいていますが、form系のヘルパーはそのうちのViewを担当しています。
form_tagを使えば、入力フォームに必要なHTMLを簡潔に作成できます。
なので、Railsで基本的な入力フォームで値を送信する場合は、form_tagを使いましょう。
form_tagの基本構文
form_tagの書き方にはいくつかありますが,基本的に指定しているものはURL(リソース)とHTTPメソッドの2つです。
URLはapp/config/routesで指定されたリソースを指定し、HTTPメソッドでput、post、patchを指定します。
それではいくつか書き方を見て見ましょう。
例えば、今回Orangeというモデルがあり、以下のように
oranges GET /oranges(.:format) oranges#index
POST /oranges(.:format) oranges#create
リソース(URL)が振り分けられているとします。
[form_tagの書き方1]
<%= form_tag('/oranges', method: :post) do %> (中身) <% end %>
こちらは相対パスで、リソースを指定し、method: :postでHTTPメソッドを指定しています。
[form_tagの書き方2]
<%= form_tag(oranges_path, method: :post) do %> (中身) <% end %>
このように名前付きルートでも同じように振り分けられます。
[form_tagの書き方3]
<%= form_tag({ :controller => 'oranges', :action => 'create' }, { :method => :post}) do %> (中身) <% end %>
このように、コントローラーとアクションで指定することもできます。
またはシンボルを使って書き直すと
[form_tagの書き方4]
<%= form_tag({controller: :oranges, action: :create}, { method: :post}) do %> (中身) <% end %>
のようになります。
いずれの場合もpostメソッドを記述しなくても、Railsが自動的にpostと判断してくれるので省略することもできます。
上記のform_tagはすべて同じ挙動です。
また、form_tagにはオプションもあります。
画像投稿用のmultipartの指定は
[form_tagの書き方5]
<%= form_tag('/oranges', method: :post,multipart: true) do %> (中身) <% end %>
で、ajax化するためのremoteの指定は
[form_tagの書き方6]
<%= form_tag('/oranges', method: :post,remote: true) do %> (中身) <% end %>
です。
また、classやidを指定したい場合は
[form_tagの書き方7]
<%= form_tag('/oranges', method: :post,class: "exmaple_class",id:"example_id") do %> (中身) <% end %>
このように、class: “クラス名”やid: “id名”で設定できます。
form_tagに関連するビューヘルパー
それでは実際にform_tagを使った入力フォームを作成してみましょう。
まず、今回使用するコントローラーとモデルを作成するために以下のコードをコマンドプロンプトに入力してください。
[コントローラー(oranges)とモデル(orage)を作成し、マイグレーションファイルを実行する]
rails g controller Oranges index new create rails g model Orange name:string content:text rails db:migrate
[実行結果]
create app/controllers/oranges_controller.rb route get 'oranges/create' route get 'oranges/new' route get 'oranges/index' invoke erb create app/views/oranges create app/views/oranges/index.html.erb create app/views/oranges/new.html.erb create app/views/oranges/create.html.erb invoke test_unit create test/controllers/oranges_controller_test.rb invoke helper create app/helpers/oranges_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/oranges.coffee invoke scss create app/assets/stylesheets/oranges.scss create db/migrate/20170808004640_create_oranges.rb create app/models/orange.rb invoke test_unit create test/models/orange_test.rb create test/fixtures/oranges.yml == 20170808004640 CreateOranges: migrating ==================================== -- create_table(:oranges) -> 0.0073s == 20170808004640 CreateOranges: migrated (0.0075s) ===========================
これで、コントローラーとモデルが作成できました。
次にapp/config/routes.rbを開いて、入力フォーム用にパスを割り当てていきましょう。
以下のようにコードを修正してください。
[削除するコード]
get 'oranges/create' get 'oranges/new' get 'oranges/index'
↓
[修正後のコード]
resources :oranges
これで自動的にRESTfulにリソースを割り当てられます。
RESTfulでルート構成についてわからない人は、こちらの記事を参考にしてください。
これで、準備は完了です。
それでは、まず初めにoragesコントローラーにコードを加えていきましょう。以下のコードをapp/controller/orages_controller.rbに入力してください。
[app/controller/orages_controller.rbの内容]
class OrangesController < ApplicationController def index @oranges = Orange.all end def new @orange = Orange.new end def create @orange = Orange.new(orange_params) if @orange.save redirect_to :action => "index" else render :action => "new" end end def orange_params params.permit(:name, :content) end end
これで基本的な新規データを入力する準備ができました。
続いては作成されたapp/views/index.html.erbの内容を以下のように修正してください。
<table> <thead> <tr> <th>名前</th> <th>内容</th> </tr> </thead> <tbody> <% @oranges.each do |orange| %> <tr> <td><%= orange.name %></td> <td><%= orange.content %></td> </tr> <% end %> </tbody> </table> <%= link_to 'データを追加する', new_orange_path %>
先ほど、コントローラーのindexアクションで定義した@orangesの内容を出力しています。
また、link_toでは作成したnewアクションを指定しています。
new_orage_pathはnewアクションの名前付きルートです。
app/views/index.html.erbはこのように、表示されます。
それでは”データを追加する”を押した後のapp/veiws/orages/new.html.erbにform_tagを使用した入力フォームを実装してみましょう。
[app/veiws/orages/new.html.erbの内容]
<%= form_tag(oranges_path, method: :post) do %> <%= label_tag :名前 %> <%= text_field_tag :name %> <%= label_tag :内容 %> <%= text_area_tag :content %> <%= submit_tag "追加" %> <% end %>
new.html.erbはこのように表示されます。
form_tagの部分は基本構文で説明したとおりです。
label_tagヘルバーでは、入力する値の名前を指定してします。
たとえば、今回は名前、内容が指定してあり、ユーザーが何を入力するのかわかるようにしています。
また、text_field_tagヘルパーは名前の入力のための入力フィールドを作成し、text_area_tagではtext_field_tagヘルパーよりも広い入力ボックスを作成できます。
今回のように:nameや:contentと指定すると
<input type=”text” name=”name” id=”name”>
<textarea name=”content” id=”content”></textarea>
のようなHTMLに変換されます。
name=”name” 、name=”content”と指定されていることから、コントローラーではparam[:name]またはparam[:content]で値を受け取ることができます。
それでは実際に値を入力してみましょう。
追加ボタンを押すと
このように、form_tagがしっかりと機能していることを確認できます。
実際に自分で動作を実際に確かめるためにはコマンドプロンプトにrails sでサーバーを起動した後、以下のURLにアクセスして、index.html.erbを開いてください。
http://localhost:3000/oranges(補足http://localhost:3000の箇所は各自の開発環境により読み替えてください。)
form_tagとform_forの違い
form_forの基本構文
form_tagとは別にRailsではform_forがあります。
form_forではURLやHTTPメソッドの指定を省略することができますが、基本は同じでURLとHTTPメソッドの2つを指定しています。
[form_for書き方1]
<%= form_for(@orange) do |f| %> (中身) <% end %>
@orangeと指定するだけで、@orangeがすでに存在しているかどうかを判別し、createやupdateのアクションを指定することができます。
アクションの指定を指定する方法
[form_for書き方2]
<%= form_for(@orange,action: 'example') do |f| %> (中身) <% end %>
画像投稿用のmutipartの指定
[form_for書き方3]
<%= form_for(@orange,multipart: true) do |f| %> (中身) <% end %>
form_tagとform_forの使い分け
特定のモデルとの結びつきかある場合はform_forを使えば、自動的にURLやHTTPメソッドの種類を推測してくれるのでとても簡潔にコードを書くことができます。
一方、form_tagの場合は特定のモデルを気にする必要がないので、モデルとは切り離した汎用的なフォーム(検索フォームなど)を作成する場合には有用です。
また通常form_tagとform_forではポストされる値がネスト化されるかされないかという違いがあります。
例えば、以下のようにform_tagでフォーム作成した場合
[form_tagの使用例]
<%= form_tag(oranges_path, method: :post) do %> <%= label_tag :名前 %> <%= text_field_tag :name %> <%= label_tag :内容 %> <%= text_area_tag :content %> <%= submit_tag "追加" %> <% end %>
text_field_tag、text_area_tagは以下のようなHTMLに変換されます。
<input type=”text” name=”name” id=”name”>
<textarea name=”content” id=”content”></textarea>
前述したとおり、コントローラーでは
・param[:name]
・param[:content]
で値を受け取ることができます。
一方、form_forでは
[form_forの使用例]
<%= form_for(@orange) do |f| %> <%= f.label :名前 %> <%= f.text_field :name %> <%= f.label :内容 %> <%= f.text_area :content %> <%= f.submit "追加" %> <% end %>
f.text_fieldとf.text_areaの部分はそれぞれ以下のHTMLに変換されます。
<input type=”text” name=”orange[name]” id=”orange_name”>
<textarea name=”orange[content]” id=”orange_content”></textarea>
f.text_fieldとf.text_areaでは値が特定のモデル用にネスト化されるので、コントローラーでは
・param[:orange][:name]
・param[:orange][:content]
で値が受け取れるようになります。
なので、コントローラーで受け取る際にはネスト化されているのか、されていないのかを意識して値を受け取る必要があります。
コントローラーでストロングパラメーターを使って受け取っている部分を
(ストロングパラメーターとはRailsにおいて値を安全に受け取るための仕組みのことです。)
[ネスト化されていない場合]
def orange_params params.permit(:name,:content) end
[ネスト化されている場合]
def orange_params params.require(:orange).permit(:name,:content) end
と値を保存する際には使い分ける必要があります。
違いはrequire(:orange)の部分です。
こう指定することで
・param[:orange][:name]
・param[:orange][:content]
のように受け取けとれます。
また、実はform_tagでもネスト化されたパラメーターを作成することができます。
<%= form_tag(oranges_path, method: :post) do %> <%= label_tag :名前 %> <%= text_field_tag 'orange[name]' %> <%= label_tag :内容 %> <%= text_area_tag 'orange[content]' %> <%= submit_tag "作成" %> <% end %>
このように’orange[name]’などと指定してあげるとネスト化されたパラメーターを送ることができます。
変換されたHTMLは以下の通りです。
<input type=”text” name=”orange[name]” id=”orange_name”>
<textarea name=”orange[content]” id=”orange_content”></textarea>
このようにform_forはform_tagよりもモデルを扱う場合にはURL、HTTPメソッドまた、値のネスト化など自動的に処理してくれるので便利です。
Railsを独学で頑張っているけど先が見えない方のために
そんな方、実はいらっしゃるのではないでしょうか?
そんな方であれば、これから先の話は必要ないでしょう。そっとページの閉じるボタンを押しましょう。
しかし、「先が見えない」と心の底では勘付いているそこの奥さん。この先を読み進めて、一緒に課題を深堀りしていきましょう。
なぜ「先が見えない」という不安や悩みを抱えてしまうのか
さて、「一寸先は闇だ・・・」とお悩みを抱えている方に、なぜ独学でRailsを勉強しているにもかかわらず、そのような現状を抱えてしまうのか、一緒に考えていきましょう。
先が見えない現状を踏まえ、課題として考えられるものは以下のどれかに該当するでしょう。
- プログラミングの上達が見えない
- プログラミングを継続できない気がする
- プログラミングスキルを習得した姿がイメージできない
- プログラミングスキルを活かした仕事を獲得するイメージができない
これらのどれかに該当することによって、「なんとなくプログラミング学習をしている」という状態になってしまいます。
これらの要因は、三日坊主になる理論と同じなんですが、「プログラミング学習をしなきゃ」とプログラミング学習を頑張ってしまっている状態になってしまっています。
受験勉強をやった経験のある方なら頭がもげるほどに首を縦に振ってしまう方も多いのですが、「今日も5時間勉強するぞ」や「今日はこの章を終わらすぞ」というように、学習を進めることに意識が行き過ぎてしまうと、ある程度学習を継続した後に「先が見えない・・・」となってしまいます。
未来に光を当て、プログラミング学習を「成果が出るもの」にするために
先ほど、「なぜ先が見えないという悩みや不安を抱えてしまうのか」という疑問に対しての答えを示していきました。
これらの課題というのは、独学をしていれば9割の方がぶつかってしまう壁だそうで、いわば、あるあるの現象なのです。
独学をしていて、「なんか前に進めていないぞ」と感じるのはこのせいなんですね。甘く見がちですが、非常にやっかい。
これがさらにやっかいさを極めているのは、上記に挙げた課題のほとんどが、1人で解決できないものばかりだからです。
実は、これらのほとんどが経験者に助けてもらいながら解決しないと、すぐに違う方向へと流れてしまいます。
そう言い切れるのは、以前の私もそうだったからです。
エンジニアやプログラマー関連のキャリアに詳しい方や現役のエンジニアに相談しながら修正を加え、学習を実践して今があります。
という方もいるでしょう。そういう時にこそ、プログラミングスクールの無料カウンセリングを利用するのです。
という考えに辿りついてしまいますよね。結論から言うと弊社では、そういった強引な営業等を行うことはありませんので、安心して受講できます。
「プログラミング学習の先ある未来」を光で明るく照らすには、弊社の無料カウンセリングがぴったりだと断言できます。それくらい無料カウンセリングに自信を持っているのです。
さらに、無料カウンセリングには以下の3大特典もついてきます!
- 「最短1ヶ月で開発ができる学習方法」電子書籍(非売品)
- 効率的なオリジナル学習カリキュラム
- 未経験の転職(フリーランス)を可能にするキャリアサポート
上記の特典だけでも他のスクールにはないポイントだと自信を持っている無料カウンセリング特典です。
ただプログラミング学習をする毎日から、ワクワクしながらプログラミング学習できる毎日に変える体験を一度でいいのでしてみませんか?
まとめ
いかがでしたでしょうか?
この記事では、form_tagやform_forの使い方を解説しました。
form_tagは特定のモデルとの結びつきのないときには便利で、form_forは特定のモデルとの結びつきを自動的に解釈してアクションの選択やネスト化をしてくれるので少ないコードで入力フォームを実装できます。
もしform_tagやform_forの使い方について忘れてしまったらこの記事を確認してくださいね!