記事の概要
Webサービス上で日付を入力して「送信」のようなボタンを押すと、その日付に応じた結果が表示されることはよくあるものと思います。これをRailsで実装する手順について解説していきたいと思います。
バージョン
・ruby 2.6.5
・rails 6.0.3.4
・mysql 14.14
体重や体脂肪をデータベースに保存してそれを表示するアプリケーションを例にとって考えてみます。
前提として、事前にデータベースに日付・体重・体脂肪・体調の情報が保存されているものとします。
まず、記録を保存する機能として、Body_Record というモデルを用意しています。
class BodyRecord < ApplicationRecord
belongs_to :user, optional: true
with_options presence: true do
validates :date #日付必須
validates :body_weight #体重必須
validates :fat #体脂肪率必須
end
ビューファイルの中身は以下のようになっています(CSSは割愛します)
<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 %>
コントローラー側の処理は以下の通りです。
# 〜省略
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
# 省略〜
ルーティングは以下の通りです。
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を再表示する仕組みになっています。
さらに、もし選択された日付にデータが保存されていなかった場合、
<% unless @body_record.empty? %>
省略
<% else %>
<div class="empty">
<p>記録されたデータはありません</p>
</div>
<% end %>
の記述により、「記録されたデータはありません」という表示が出るように条件分岐をしています。
終わりに
今回ご紹介した内容は、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