Rails: 保存期間設定画面の習作
外観
Basecampの新機能 Limit chat history のような画面を作ったことがなかったのでRailsで習作アプリを作りました。モデルは想像になります。本物は設定画面にラジオボタングループが2つありCSSで角丸ボタンにしていますが、今回の習作ではスタイリングは対象外にします。
環境
ruby 3.1.2p20
rails 7.0.4
リポジトリ
https://github.com/usutani/try_retention
画面
仕様
ラベル: ['Forever', '30 days', '90 days', '1 year', '2 years']
ラジオボタンの値: ['', '30', '90', '365', '730']
モデル: [nil, 30, 90, 365, 730]
Retentionモデルのcycleとprojectに日数を保存する。
ビューのForever(空文字列)はモデルではnilにします。
画面遷移: ホーム画面←→設定画面←→確認画面→ホーム画面
前の画面に戻れる。
保存時に確認画面でCONFIRMと入力させる。
フォームオブジェクトは使わない。
設定画面と確認画面のURLは同じ。
モデル: Retention
データは1件だけ用意する。Retention.first!で取得する。
コントローラー: HomesController, RetentionsController
HomesController
show: ホーム画面を表示する。
RetentionsController
show: 設定画面を表示する。
update: 確認画面を表示する。
実装
準備
モデルとコントローラーを作成します。
ホーム画面から設定画面までのリンクを用意する。
rails new try_retention && cd $_
rails g model Retention cycle:integer project:integer
rails db:migrate
test/fixtures/retentions.yml
one:
cycle: nil
project: nil
rails db:fixtures:load
rails g controller Homes show
rails g controller Retentions show
config/routes.rb
Rails.application.routes.draw do
resource :home, only: :show
resource :retention, only: %i[ show update ]
root "retentions#show"
end
app/views/homes/show.html.erb
<h1>Home#show</h1>
<p>Find me in app/views/home/show.html.erb</p>
<p style="color: green"><%= notice %></p>
<%= link_to 'Retentions', retention_path %>
rails s
open http://localhost:3000/home
設定画面
編集対象のファイル
app/controllers/retentions_controller.rb
app/views/retentions/show.html.erb
app/views/retentions/_radio_buttons.html.erb
app/views/retentions/update.html.erb
app/helpers/retentions_helper.rb
touch app/views/retentions/_radio_buttons.html.erb
touch app/views/retentions/update.html.erb
app/controllers/retentions_controller.rb
show: 設定画面を表示する。
update: 確認画面を表示する。
class RetentionsController < ApplicationController
before_action :set_retention, only: %i[ show update ]
def show
@items = [nil, 30, 90, 365, 730]
end
def update
if confirmed? && @retention.update(retention_params)
redirect_to home_url, notice: 'Retentions successfully saved.'
else
@retention = Retention.new(retention_params)
render status: :unprocessable_entity
end
end
private
def set_retention
@retention = Retention.first!
end
def retention_params
# params.permit(:cycle, :project).to_h { |k, v| [k, v.presence] }
{
cycle: params[:cycle].presence,
project: params[:project].presence,
}
end
def confirmed?
params[:confirmation] == 'CONFIRM'
end
end
app/views/retentions/show.html.erb
<h1>Retentions#show</h1>
<p>Find me in app/views/retentions/show.html.erb</p>
<%= form_with url: retention_path, method: :put do %>
<h2>Cycle</h2>
<%= render 'radio_buttons', items: @items, name: 'cycle', value: @retention.cycle %>
<h2>Project</h2>
<%= render 'radio_buttons', items: @items, name: 'project', value: @retention.project %>
<%= submit_tag 'Review chnges...' %>
<%= link_to 'Never mind', home_path %>
<% end %>
app/views/retentions/_radio_buttons.html.erb
itemがnilなら空文字列。
item == valueならチェックを付ける。
<% items.each do |item| %>
<%= label_tag do %>
<%= radio_button_tag name, item || '', item == value %>
<%= tag.span days_to_human(item) %>
<% end %>
<br>
<% end %>
app/views/retentions/update.html.erb
<h2>Cycle</h2>
<%= days_to_human(@retention.cycle) %>
<h2>Project</h2>
<%= days_to_human(@retention.project) %>
<%= form_with url: retention_path, method: :put do %>
<%= hidden_field_tag 'cycle', @retention.cycle %>
<%= hidden_field_tag 'project', @retention.project %>
<%= text_field_tag 'confirmation', nil, placeholder: 'Type CONFIRM', required: true %>
<br>
<%= submit_tag 'Yes, confirm and apply changes' %>
<%= link_to 'Never mind, go back', retention_path %>
<% end %>
app/helpers/retentions_helper.rb
module RetentionsHelper
def days_to_human(days)
return 'Forever' if days.blank?
years = days.to_i / 365
return "#{days} days" if years == 0
return "#{years} year" if years == 1
"#{years} years"
end
end
以上です。
この記事が気に入ったらサポートをしてみませんか?