学生向けプログラミング入門

学生向けにプログラミングを解説。Java、C++、Ruby、PHP、データベース

Ruby on RailsでWebアプリケーション開発その10 登録フォームの変更

<<前  [TOP]  次>>


商品の登録フォームも編集します。
「商品登録」ボタンをクリックすると、URLは以下のようになっています。
f:id:MrRadiology:20180131141100p:plain
このURL「http://localhost:3000/goods/new」は重要な意味を持っています。
URLの最後は「/goods/new」となっています。
詳しく内容を書くと「:controller/:action」です。
これは、goodsコントローラのnewアクションを開きなさいという命令です。


newアクションを開きなさいと命令を受けたRailsは、「app/views/goods」フォルダにある「new.rhtml.erb」ファイルを見ます。
URLとviewsには必ずこの関係が成り立ちますので、表示内容を編集したいときは、まずURLを見て対象のファイルを探し編集を行うという流れとなります。


では、「app/views/goods/new.html.erb」ファイルの中身を見てみましょう。
【app/views/goods/new.html.erb】

<h1>New Good</h1>

<%= render 'form', good: @good %>

<%= link_to 'Back', goods_path %>

以下のように編集しました。

<h1>商品の登録</h1>

<%= render 'form', good: @good %>

<%= link_to 'トップページに戻る', goods_path, class: 'btn' %>

最後に<%= link_to 'トップページに戻る', goods_path, class: 'btn' %>という記述があります。
この「goods_path」というのは「index」を指しています。
<%= link_to 'トップページに戻る', {:action => 'index'}, class: 'btn' %>」のように書き換えても同じように動作します。


他にも「 render」メソッドがあります。
これは部分テンプレートを表示するために使います。
部分テンプレートの名前が「form」であると書いてあるので、「_form.html.erb」という名前のファイルが読み込まれることになります。
good: @goodの記述は部分テンプレートに「@good」というオブジェクトを渡すという意味です。
「_form.html.erb」でオブジェクトを利用する時は「good」という名前で利用できます。
@goodはインスタンス変数といいます。
インスタンス変数は、クラス内のすべてのインスタンスメソッドで使用できます。
Railsの場合、この@goodの定義はcontrollerに記述します。
「controllers/goods_controller.rb」ファイルの中には、newメソッドが存在します。

  # GET /goods/new
  def new
    @good = Good.new
  end

これはscaffoldによって自動生成されたものです。
この中に、「@good = Good.new」という記述があり、ここで@goodにオブジェクトが格納されています。
「Good.new」という命令によって、Goodオブジェクトを新しく取得し、@goodに格納しています。


では「_form.html.erb」を見てみましょう。
【app/views/goods/_form.html.erb】

<%= form_with(model: good, local: true) do |form| %>
  <% if good.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(good.errors.count, "error") %> prohibited this good from being saved:</h2>

      <ul>
      <% good.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :goods_id %>
    <%= form.number_field :goods_id, id: :good_goods_id %>
  </div>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_area :title, id: :good_title %>
  </div>

  <div class="field">
    <%= form.label :description %>
    <%= form.text_area :description, id: :good_description %>
  </div>

  <div class="field">
    <%= form.label :image_url %>
    <%= form.text_area :image_url, id: :good_image_url %>
  </div>

  <div class="field">
    <%= form.label :price %>
    <%= form.number_field :price, id: :good_price %>
  </div>

  <div class="field">
    <%= form.label :date %>
    <%= form.text_area :date, id: :good_date %>
  </div>

  <div class="field">
    <%= form.label :maker %>
    <%= form.text_area :maker, id: :good_maker %>
  </div>

  <div class="field">
    <%= form.label :category %>
    <%= form.text_area :category, id: :good_category %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

これを以下のように編集します。

<%= form_with(model: good, local: true) do |form| %>
  <% if good.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(good.errors.count, "error") %> 商品を登録することが出来ません。</h2>

      <ul>
      <% good.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
<br>
  <div class="field">
    <%= form.label :goods_id, :商品ID %>
    <%= form.number_field :goods_id, id: :good_goods_id %>
  </div>

  <div class="field">
    <%= form.label :title, :商品名 %>
    <%= form.text_area :title, id: :good_title %>
  </div>

  <div class="field">
    <%= form.label :description, :詳細 %>
    <%= form.text_area :description, id: :good_description %>
  </div>

  <div class="field">
    <%= form.label :image_url, :画像URL %>
    <%= form.text_area :image_url, id: :good_image_url %>
  </div>

  <div class="field">
    <%= form.label :price, :価格 %>
    <%= form.number_field :price, id: :good_price %><span></span>
  </div>

  <div class="field">
    <%= form.label :date, :登録日 %>
    <%= form.text_area :date, id: :good_date %>
  </div>

  <div class="field">
    <%= form.label :maker, :メーカー %>
    <%= form.text_area :maker, id: :good_maker %>
  </div>

  <div class="field">
    <%= form.label :category, :カテゴリー %>
    <%= form.select(:category, [['選択して下さい', ''],['本', '本'],['家電', '家電'],['おもちゃ', 'おもちゃ'], ['生活用品', '生活用品']]) %>
  </div>

  <div class="actions">
    <%= form.submit('登録', :class=> 'fbtn') %>
  </div>
<% end %>

登録フォームはこのようになりました。
f:id:MrRadiology:20180201120045p:plain


入力した値にエラーがある場合は以下の部分が実行されます。

  <% if good.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(good.errors.count, "error") %> 商品を登録することが出来ません。</h2>

      <ul>
      <% good.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

pluralizeメソッドは単数形と複数形を変換するメソッドです。


各メソッドを見てみます。


【form_withメソッド】
「<%= form_with %>から<%= end %>」で囲まれた部分にフォームの情報を記述します。
Rails5.1から新たに導入されたメソッドです。
<%= form_with(model: good, local: true) do |form| %>
「new.html.erb」から渡された「good」オブジェクトを「form」に渡し、<%= end %>まで処理をします。


このform_withメソッドには、もう一つの流れがあります。
それは、フォームに入力されたデータを登録するときの記述を必ずしなければならないということです。
<%= form.submit('登録', :class=> 'fbtn') %>
フォームに入力された後、createメソッドに入力データが渡されます。
これにより、コントローラのcreateメソッドに入力データを渡しています。
では、createメソッドを見てみましょう。
【app/controllers/goods_controller.rb】

  # POST /goods
  # POST /goods.json
  def create
    @good = Good.new(good_params)

    respond_to do |format|
      if @good.save
        format.html { redirect_to @good, notice: 'Good was successfully created.' }
        format.json { render :show, status: :created, location: @good }
      else
        format.html { render :new }
        format.json { render json: @good.errors, status: :unprocessable_entity }
      end
    end
  end

このcreateメソッドでは、「@good = Good.new(good_params)」としています。
フォームに入力したパラメータ「good_params」を新しく@goodに追加しています。
次の部分も日本語に直しておきます。

format.html { redirect_to @good, notice: '商品が登録されました' }

form_with(model: good, local: true) の「local: true」というのはフォームのリモート 送信を無効にするという意味があります。


【number_fieldメソッド】
<%= form.number_field :goods_id, id: :good_goods_id %>
数値入力ボックスを生成します。


【text_fieldメソッド】
<%= form.text_area :title, id: :good_title %>
textタイプの<input>タグを作成します。


【selectメソッド】
<%= form.select(:category, [['選択して下さい', ''],['本', '本'],['家電', '家電'],['おもちゃ', 'おもちゃ'], ['生活用品', '生活用品']]) %>
選択リストを作成することが出来ます。
最後に選択リストの項目を配列で与えます。
最初に表示される文字を「分類を選択して下さい」として、その後に空パラメータ「''」を指定することで、valueがnilであることを指定しています。


【date_selectメソッド】
選択リストを使用して、日付を設定できるようにするボタンを作成します。
オプションで「:use_month_numbers => true」と指定することで、月の英語表示を数字に変えることが出来ます。
SQLiteではカラムのデータ型にDate型がないため、date_selectメソッドを使用するとデータを渡した時にエラーが出ます。


<<前  [TOP]  次>>