LoginSignup
10
13

More than 5 years have passed since last update.

【Rails】form_forメソッドを用いたザコアプリ作成

Last updated at Posted at 2017-05-11

ザコアプリを作ってform_forを学んでみた

railsをはじめて1ヶ月。作るアプリは徐々に複雑になってきはじめ、曖昧な知識達を複数組み合わせる機会が増えました。

私の理解は既に空中分解しかけており、原点を見失いそうになりつつある状況です。
そこで、原点に立ち返ろうと思い「ザコアプリ」を作ることで曖昧な知識のひとつ「form_for」やその周辺知識を整理して理解しようじゃないかと思ったのが本記事を書いた動機です。

今回作るザコアプリ

この記事内容をまんま真似していくことで、下のザコアプリを生成することができます。

スクリーンショット 2017-05-11 20.33.43.png

フォームに入力して投稿するボタンを押すと

スクリーンショット 2017-05-11 20.33.52.png

投稿内容が反映されます。

rails のファイル一式を作る

サクサク作っていきます。まずはターミナルを開きrailsのファイル一式を作ります。
使用したコマンドはこちらです。

$ mkdir zako_app
$ cd zako_app
$ rails new zako

mkdirコマンドで新規フォルダ「zako_app」を作成し、rails newコマンドで新規rails アプリ「zako」を作成しています。これでzakoのrailsファイル一式が生成されました。
スクリーンショット 2017-05-11 12.51.51.png
テキストエディタの「sublime_text」でフォルダ一式開きました。今回はこのエディタで作っていきます。
スクリーンショット 2017-05-11 12.52.55.png

ルーティングを設定する

今回は「articles」と自分で名付けて、resourcesを用いてルーティングを自動設定しました。また、ルートは現状articlesのnewアクションとして設定しておきました。

config/routes.rb
Rails.application.routes.draw do
  root 'articles#new'
  resources :articles
end

一応、このタイミングで生成されたルーティングを$rake routesで確認しておきます。
下記のようにルーティングが設定されたことを確認します。

$rake routes
$ bundle exec rake routes
      Prefix Verb   URI Pattern                  Controller#Action
    articles GET    /articles(.:format)          articles#index
             POST   /articles(.:format)          articles#create
 new_article GET    /articles/new(.:format)      articles#new
edit_article GET    /articles/:id/edit(.:format) articles#edit
     article GET    /articles/:id(.:format)      articles#show
             PATCH  /articles/:id(.:format)      articles#update
             PUT    /articles/:id(.:format)      articles#update
             DELETE /articles/:id(.:format)      articles#destroy

コントローラーを生成し、newアクションを定義する

これに対応するarticlesコントローラーを下記コマンドで生成します。

$ rails g controller articles

これでarticlesコントローラーが生成されました。
スクリーンショット 2017-05-11 13.17.45.png

コントローラーの中にアクションを定義します。今回は「newアクション」を取り急ぎ、空で配置しておきました。
スクリーンショット 2017-05-11 13.29.31.png

newアクションに対応するnewビューを生成する

newアクションを定義したので、そのnewアクションに対応するビューを生成します。ここは単純にviews/articles内に右クリックで生成→保存します。
スクリーンショット 2017-05-11 13.33.16.pngスクリーンショット 2017-05-11 13.35.10.png
new.html.erbと名付け保存しました。この中に「私はnewのビューです。」と書き、$rails sコマンドでサーバーを立ち上げ、実際に表示されるかを開いてみます。
スクリーンショット 2017-05-11 13.36.13.png
ターミナルで$rails sコマンドを叩き、サーバーを立ち上げます。

$rails s

ローカルホストhttp://localhost:3000/を開いたときに「私はnewのビューです。」と表示されれば、とりあえずルーティング→コントローラー→ビューへの表示という基本の流れの設定は成功です。

スクリーンショット 2017-05-11 13.47.49.png

new.html.erbにform_forを用いてフォーム画面を書いていきますが、ユーザーがフォームに入力した内容を保存する「データベース」を用意しなければフォームは機能しないので、先にデータベースを用意します。

Articleモデルとそれに対応するデータベースを生成する

フォームを機能させるにはコントローラーとデータベース間でやりとりができるようにしなければなりません。
ここまでで生成した「articlesビュー」と「articlesコントローラー」に紐づく「Articleモデル」を生成することで、コントローラーとデータベース間でのやりとりが可能になります。

Articleモデルを生成する

ターミナルで下記コマンドを入力し、Articleモデルを生成します。このとき、Articlesと複数形にならないように注意します。

  • コントローラ名:→複数形
  • モデル名   :→単数形

とすることで、自動的に対応関係が築かれるようにrailsではなっています。

$ rails g model Article

これにより下記のようなmodels/article.rbというモデルが生成されました。
スクリーンショット 2017-05-11 14.28.02.png
中の記述を読んでみると、application_record.rb内の「AplicationRecord」クラス内にある「ActiveRecord::Base」がArticleクラスに継承されていることがわかります。これによりデータベースと連携されるようになります。

articlesテーブルを生成する

Articleモデルを生成した後にdb/migrate/内を見てみると下図のような「日時_create_articles.rb」というマイグレーションファイルが生成されます。
スクリーンショット 2017-05-11 15.07.52.png
これは「どのようなarticlesテーブルを作るか?」の設計書的な存在のもので、ターミナルでrake db:migrateのコマンドを実行することで、この内容に基づいたテーブルが生成されます。

今回は、フォームの中で「タイトル」と「テキスト」という枠を設けたいので、それぞれに対応したテーブルのカラム(列)が作られるようこの中に項目を追加で書いていきます。

db/migrate/20170511052306_create_articles.rb
class CreateArticles < ActiveRecord::Migration[5.0]
  def change
    create_table :articles do |t|
      t.string :title
      t.text :text
      t.timestamps
    end
  end

書き終えたら、ターミナル内で下記コマンドを実行します。

$ rake db:migrate

これにより「db/migrate/development.sqlite3」内に「articlesテーブル」が生成されています。
スクリーンショット 2017-05-11 15.30.00.png

※データベースの中身はDB Browser for SQLiteというアプリケーションを用いることで、視覚的に確認することもできます。スクリーンショット 2017-05-11 15.40.21.png
上部の「Open Data Base」から「db/migrate/development.sqlite3」を指定し、「articles」テーブルを選択すると確認できます。

「form_for」を使ってフォームを作成する

ここまででデータベースの用意もできたので、form_forメソッドを用いてnew.html.erbにフォームを書いていきます。
まず、form_forメソッドをnewビュー内で用いるためのモデルオブジェクト(@article)をコントローラー内で設定しておきます。

articles_controller.rb
  def new
    @article = Article.new
  end

つぎに、newビュー内にform_forメソッドを用いたフォームの基本形を作ります。rubyコードをhtmlに反映させるのでerb記法で書いていきます。

new.html.erb
<%= form_for @article do |f| %>
  <%= f.text_field :title %><br>
  <%= f.text_area :text %><br>
  <%= f.submit %>
<% end %>
  • f.text_field 一行のテキストを入力するためのフォームを作ります。
  • f.text_area 複数行のテキストを入力するためのフォームを作ります。
  • f.text_submit submitボタンを作ります。

これで、このようなフォームが作成できます。

スクリーンショット 2017-05-11 17.30.22.png

また、form_forのsubmitを押した時の挙動ですが

  • @articleが新規作成された時はarticlesコントローラーのcreateアクション
  • @articleが既存で存在している場合はarticlesコントローラーのupdateアクション

と自動でform_forメソッドがアクションを振り分けてくれます。よって、「create」「update」のアクションを使用するにはそれぞれコントローラ内で定義する必要があります。

これをベースに少し変更します。具体的には、submitを押したときのアクションを指定したり、フォームのラベルを付けたり、submitボタンの表示文言を変更したりします。

new.html.erb
<h1>投稿フォーム</h1>
<%= form_for @article, url: articles_path do |f| %>
  <p>
    <%= f.label :title, "タイトル" %><br>
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :text, "内容" %><br>
    <%= f.text_area :text %>
  </p>
  <p>
    <%= f.submit "投稿する"%>
  </p>
<% end %>
  • url: articles_path submitを押した時の飛び先を指定することができます。
  • f.label :title, "タイトル" 「タイトル」というラベルを作ります。

これで下図のようなフォームが作れます。

スクリーンショット 2017-05-11 18.04.55.png

現時点では、submitを押したときに実行されるcreateアクションが設定されていないので、入力してもエラーになります。

createアクションを設定する

フォームに入力した内容をarticlesテーブルに保存するための「createアクション」をarticlesコントローラー内で設定します。

paramsの内容を確認する

createアクションが実行されたタイミングでどのようなパラメータが飛んできているのかを確認するために、raise.params.inspectをcreateアクションに設定して実行し、意図的にエラーを起こします。

articles_controller.rb
  def create
    raise.params.inspect
  end

スクリーンショット 2017-05-11 18.22.26.png
下のparameters:のところで、createアクションが実行されたタイミングで飛んできているパラメータを確認することができます。

 "article"=>{"title"=>"これはテストです。", "text"=>"ここに内容を入力します。"},

この中のtitleとtextに対応するバリューがフォームで入力した内容です。

コントローラーにcreateを設定する

上記の2つをそれぞれテーブルに安全に保存したいので、下記のように書きました。

articles_controller.rb
  def create
    @article = Article.create(article_params)
  end

  private
  def article_params
    params.require(:article).permit(:title, :text)
  end

article_paramsについて
requireメソッドを使ってキーがarticleのバリューの{"title"=>"これはテストです。", "text"=>"ここに内容を入力します。"}を取得しています。
そしてpermitメソッドを使いtitleとtextをキーとするハッシュ(フォームで入力した内容)を取得しています。private以下に記載することで安全面も考慮しています。

上記のようにコントローラを設定して、投稿するとデータベースにしっかり保存されていることが確認できました。
スクリーンショット 2017-05-11 19.05.18.png

スクリーンショット 2017-05-11 19.05.30.png

showアクションとshowビューを設定して入力内容を表示されるようにする

今のままだと、createされたあとに微動だにしません。
入力した内容が表示されるように、showアクションとそれに対応するshowビューを設定し、createアクションが実行された後にはshowアクションが実行されるようにします。

showアクションの設定

articles_controller.rb
  def show
    @article = Article.find(params[:id])
  end

articlesテーブル内からcreateアクションで生成したレコードを取得し、それをビュー内で使えるインスタンス変数(@article)に入れました。
@に入れることでビュー(show.html.erb)内でもこの変数を使えるようになります。

showビューの作成

newビューと同様に右クリックで作成し、保存することでshowビュー(show.html.erb)を生成します。
スクリーンショット 2017-05-11 19.11.42.png

ビュー内には下記のように書くことで@article内のフォームで入力した内容をそれぞれ表示します。

show.html.erb
<h1><%= @article.title %></h1>
<p><%= @article.text %></h1><br>
<%= link_to "入力フォームに戻る", new_article_path %>

また、入力フォームに戻れるようにlink_toメソッドを用いてnewアクションへのリンクも生成します。

createアクションの遷移設定

createアクションが実行された後にはcreateビューを表示するのではなく、showアクションが実行されるようにredirect_toメソッドを用いて設定します。

articles_controller.rb
  def create
    @article = Article.create(article_params)
    redirect_to article_path(@article)
  end

redirect_toメソッドによってshowアクション(=article_path)が実行されるようにしています。
その際に_pathメソッドの引数に@articleを渡すことで、URLに生成したarticleのidをパラメータ付与することができます。

例)初めての投稿の場合
http://localhost:3000/articles/1
というようなURLになります。

完成

本当は編集機能も付けたいですが、長くなったのでこちらでザコアプリ完成ということで区切りたいと思います。

スクリーンショット 2017-05-11 20.33.43.png

フォームに入力して投稿するボタンを押すと

スクリーンショット 2017-05-11 20.33.52.png

投稿内容が反映されます。

完成ソースコード

articles_controller.rb
class ArticlesController < ApplicationController

  def new
    @article = Article.new
  end

  def show
    @article = Article.find(params[:id])
  end

  def create
    @article = Article.create(article_params)
    redirect_to article_path(@article)
  end

  private
  def article_params
    params.require(:article).permit(:title, :text)
  end
end
new.html.erb
<h1>投稿フォーム</h1>
<%= form_for @article, url: articles_path do |f| %>
  <p>
    <%= f.label :title, "タイトル" %><br>
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :text, "内容" %><br>
    <%= f.text_area :text %>
  </p>
  <p>
    <%= f.submit "投稿する"%>
  </p>
<% end %>
show.html.erb
<h1><%= @article.title %></h1>
<p><%= @article.text %></h1><br>
<%= link_to "入力フォームに戻る", new_article_path %>
10
13
2

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
10
13