LoginSignup
1
1

More than 1 year has passed since last update.

Railsのみで日付からデータを表示する方法

Posted at

記事の概要

Webサービス上で日付を入力して「送信」のようなボタンを押すと、その日付に応じた結果が表示されることはよくあるものと思います。これをRailsで実装する手順について解説していきたいと思います。

バージョン

・ruby 2.6.5
・rails 6.0.3.4
・mysql 14.14

体重や体脂肪をデータベースに保存してそれを表示するアプリケーションを例にとって考えてみます。
前提として、事前にデータベースに日付・体重・体脂肪・体調の情報が保存されているものとします。

まず、記録を保存する機能として、Body_Record というモデルを用意しています。

app>models>body_record.rb
class BodyRecord < ApplicationRecord
  belongs_to :user, optional: true

  with_options presence: true do
    validates :date #日付必須
    validates :body_weight #体重必須
    validates :fat #体脂肪率必須
  end

続いてビューは以下の通りです。
d08d26d2016cac3ec710873c7a79c171.png

ビューファイルの中身は以下のようになっています(CSSは割愛します)

app>views>body_records>index.html.erb
<h3 class="input-nav">体重・体脂肪記録を確認する</h1>
<% unless @body_record.empty? %>
  <div class="action-box">
    <%= form_tag(search_body_records_path, method: :post) do %>
      <p>見たい日付を選択してください<input type="date" name="body_record[date]" id="body_record_date">
      <input type="submit" value="確認する", class="btn btn-success"></p>
    <% end %>
  </div>
#テーブル形式で表示するための記述ここから   
<div class="item-box">  
<% @body_record.each do |latest_bodyrecord| %>
  <div class="latest-box">
    <table class="latest-body-data">
      <tbody>
          <tr>
            <th class="latest-data">日付</th>
            <td class="latest-value"><%= latest_bodyrecord.date %></td>
          </tr>
          <tr>
            <th class="latest-data">体重</th>
            <td class="latest-value"><%= latest_bodyrecord.body_weight %>kg</td>
          </tr>
          <tr>
            <th class="latest-data">体脂肪率</th>
            <td class="latest-value"><%= latest_bodyrecord.fat %>%</td>
          </tr>
          <tr>
            <th class="latest-data">体調</th>
            <td class="latest-value"><%= latest_bodyrecord.todays_condition %></td>
          </tr>
      </tbody>
    </table>
  </div>
#編集・削除ボタンここから
  <div class="edit-delete-box">
    <li class="edit-box">
      <%= link_to "編集する", edit_body_record_path(latest_bodyrecord.id), method: :get, class: "btn btn-info" %>
    </li>
    <li class="delete-box">
      <%= link_to "削除する", "/body_records/#{latest_bodyrecord.id}", method: :delete, class: "btn btn-danger" %>
    </li>
  </div>
#編集・削除ボタンここまで
<% end %>
</div>
#テーブル形式で表示するための記述ここまで
#データが入っていない際の条件分岐
<% else %>
  <div class="empty">
    <p>記録されたデータはありません</p>
  </div>
<% end %>

コントローラー側の処理は以下の通りです。

app>controllers>body_records_controller.rb
#〜省略
  def index
    @body_records = BodyRecord.all
    @body_record = BodyRecord.order(date: :desc).limit(1)
  end

  def search
    @body_records = BodyRecord.all
    @body_record = BodyRecord.new(body_params)
    if @body_record.date.present?
      @body_record = BodyRecord.where('date = ?', "#{@body_record.date}}")
    else
      @body_record = BodyRecord.none
    end
      render :index
  end
#省略〜

ルーティングは以下の通りです。

config>route.rb
  resources :body_records do
    collection do
      post :search
    end

処理の流れ

まず、コントローラー側のindexアクション内の@body_record = BodyRecord.order(date: :desc).limit(1)の記述により、index.html.erbにアクセスした際は、最新の日付のデータが表示されます。

その後、日付を選択して確認するボタンを押すと、searchアクションが動き、データベースの中から選択された日付のデータを取得して、render :indexの記述によりindex.html.erbを再表示する仕組みになっています。
test2.gif

さらに、もし選択された日付にデータが保存されていなかった場合、

<% unless @body_record.empty? %>
省略
<% else %>
  <div class="empty">
    <p>記録されたデータはありません</p>
  </div>
<% end %>

の記述により、「記録されたデータはありません」という表示が出るように条件分岐をしています。
test.gif

終わりに

今回ご紹介した内容は、Railsで実装しましたが、Ajaxで非同期通信を用いて実装するほうが望ましいのではないかな?と考えています。これからアプリケーションをアップデートする中で、より良い方法や手法をどんどん試していこうと考えます。
間違っていたり、おかしなところがありましたら修正いたしますので、遠慮なくコメントいただければと思います。
最後までお読みいただき、ありがとうございました。

参考記事

【Rails入門】form_tagの使い方まとめ | 侍エンジニアブログhttps://www.sejuku.net/blog/29083

Railsで検索機能を実装する方法を現役エンジニアが解説【初心者向け】https://techacademy.jp/magazine/22330

【Rails】パラメーター値の取得(paramsメソッドの使い方https://qiita.com/yuki_0920/items/9f450a51c74407645a3b

1
1
0

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
1
1