LoginSignup
1
0

More than 5 years have passed since last update.

【Ruby on Rails】format: :csvのform遷移先でvalidationする

Last updated at Posted at 2018-03-01

やりたいこと

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は以下の通り。

views/layouts/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>

遷移元画面

routs.rb
  get 'foo' => 'foo#index', as: :foo
controllers/foo_controller.rb
class FooController < ApplicationController
  def index
  end
end
views/foo/index.html.erb
<%= form_tag hoge_path(format: :csv), method: 'post', enforce_utf8: false do %>
  <%= hidden_field_tag :id, 3 %>
  <%= submit_tag 'ダウンロード' %>
<% end %>

遷移先

routs.rb
get 'hoge' => 'hoge#index', as: :foo
models/hoge.rb
class Hoge < ActiveRecord::Base
end
controllers/hoge_controller.rb
class HogeController < ApplicationController
  def index
    @hoge = Hoge.find(id: params[:id])
  end
end
views/hoge/index.csv.ruby
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が指定されていれば問題なく動作しますが、遷移元が以下のように変更されると、「選択してください」のプルダウンが選択された状態で「ダウンロード」ボタンを押された場合にエラーが発生します。

views/foo/index.html.erb
<%= 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で条件指定しろよって意見は聞かない。いい例が出なかった

controllers/hoge_controller.rb
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ドキュメント

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