やりたいこと
form_tag hoge_path(format: :csv)
の遷移先でvalidationして、エラーの場合は他の画面にredirectする
参考
Railsのcsv出力については以下のページをご覧ください。
環境
※後ほど修正します
ruby TODO
Rails TODO
centos TODO
前提
以下のテーブルHogesに対して、遷移元(foo)で指定したidの情報をcsv出力する遷移先(hoge)を作成します。
(テーブルの中身はテキトーです)
id | name | date |
---|---|---|
3 | fizz | 2000-01-01 |
5 | bazz | 2010-01-01 |
15 | fizzbazz | 2020-01-01 |
application.html.erbは以下の通り。
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>
<% if @form != nil && @form.errors.any? %>
<ul>
<% @form.errors.full_messages.each do |msg| %>
<li><%=msg%></li>
<% end %>
</ul>
<% end %>
</div>
<div class="container">
<%= yield %>
</div>
</body>
</html>
遷移元画面
get 'foo' => 'foo#index', as: :foo
class FooController < ApplicationController
def index
end
end
<%= form_tag hoge_path(format: :csv), method: 'post', enforce_utf8: false do %>
<%= hidden_field_tag :id, 3 %>
<%= submit_tag 'ダウンロード' %>
<% end %>
遷移先
get 'hoge' => 'hoge#index', as: :foo
class Hoge < ActiveRecord::Base
end
class HogeController < ApplicationController
def index
@hoge = Hoge.find(id: params[:id])
end
end
require 'csv'
columns_header = ["id", "name"]
columns = [:id, :name]
CSV.generate do |csv|
csv << columns_header
@hoge.pluck(*columns).each do |row|
csv << row
end
end
このままだと
idが指定されていれば問題なく動作しますが、遷移元が以下のように変更されると、「選択してください」のプルダウンが選択された状態で「ダウンロード」ボタンを押された場合にエラーが発生します。
<%= form_tag hoge_path(format: :csv), method: 'post', enforce_utf8: false do %>
<%= select_tag 'page[name]', options_from_collection_for_select(Hoge.all, :id, :name), :prompt => '選択してください' %>
<%= submit_tag 'ダウンロード' %>
<% end %>
対処法
もちろん、javascriptでゴニョゴニョして制御することもできるのですが、選択されたidでDBからselectしてその値が...なんてことを考えると、controller側でvalidationをかけるのが良いでしょう。
例えば、選択されたidでselectしたレコードの「date」カラムの値が現在時刻より前の場合には、元の画面にredirectしてエラーメッセージを表示することを考えます。
@hogesをselectするときにwhereで条件指定しろよって意見は聞かない。いい例が出なかった
class HogeController < ApplicationController
def index
@hoge = Hoge.find(id: params[:id])
if @hoge.date < Time.current then
respond_to do |format|
format.any
format.html
redirect_to(foo_url, {notice: '現在時刻以降なので選択できません。'}) and return
end
end
end
end
ポイントはformat.html
の部分。
これをやらないと、エラーメッセージが記述されたcsvがダウンロードされてしまいます。
結論
Railsの基本知識が抜けているので、こんなことを調べるのに2時間ぐらいかかりました。
ドキュメント読みましょう。
respond_to - リファレンス - - Railsドキュメント