LoginSignup
0
0

More than 3 years have passed since last update.

Railsのフォームの送信がうまく反映されない

Last updated at Posted at 2021-01-26

経緯

Railsアプリケーションで画像を投稿するフォームのプレビューを実装したいと思い、ググったjqueryのサンプルを少しいじって利用させてもらったところ、フォームを送信しても正常に反映されなくてハマったのでメモ

原因

name属性を書き換えてしまっていたため。


やったこと

実際関係あったのは一行だけですが一応、修正前のコード全体は

<%= form_with model: @post, local: true do |f| %>
<div class="mt-3">
  <div class="form-group">
    <label for="file">画像</label>
    <div id="file" class="input-group">
      <div class="custom-file">
        <%= f.file_field :image, id: 'cutomfile',
                            class: 'custom-file-input', name: 'cutomfile[]' %>
        <label class="custom-file-label" for="cutomfile" data-browse="参照">ファイル選択...</label>
      </div>
      <div class="input-group-append">
        <button type="button" class="btn btn-outline-secondary reset">取消</button>
      </div>
    </div>
  </div>
  <div class="form-group">
    <%= f.label :body, 'ひとこと' %>
    <%= f.text_area :body, class: 'form-control' %>
  </div>
  <div class="nav justify-content-end mt-3">
    <%= f.submit '送信', id: 'post-form', class: 'btn btn-primary' %>
  </div>
</div>
<% end %>
$(document).on('turbolinks:load', function(){
  $('.custom-file-input').on('change', handleFileSelect);
  function handleFileSelect(evt) {
    // 繰り返し実行時の処理
    $('#preview').remove();
    $(this).parents('.input-group').before('<div id="preview"></div>');

    var file = evt.target.files[0];
    var reader = new FileReader();

    reader.onload = (function(theFile) {
      return function(e) {
        if (theFile.type.match('image.*')) {
          // 画像のプレビューとファイル名の表示
          var $html = [
            '<div class="d-inline-block mr-1 mt-1"><img class="img-thumbnail" src="', e.target.result,'" title="', escape(theFile.name), '" style="height:400px;" /><div class="small text-muted text-center">', escape(theFile.name),'</div></div>'
            ].join('');
        }
        $('#preview').append($html);
      };
    })(file);
    reader.readAsDataURL(file);
    $(this).next('.custom-file-label').html(+ evt.target.files.length + '個のファイルを選択しました');
  }

  //ファイルの取消
  $('.reset').click(function(){
    $(this).parent().prev().children('.custom-file-label').html('ファイル選択...');
    $('#preview').remove();
    $('.custom-file-input').val('');
  })
});



最初はJqueryの問題かと思い、queryやtarbolinkについて調べてみるが治らない...

デベロッパーツールやターミナルのログで送信を見てみるとImage以外は正常に送られているので、一度余分な属性をすべて消して出力を見比べてみると

デフォルト

<%= f.file_field :image %>

<!-- 出力 -->
<input type="file" name="post[image]" id="post_image" />



自身で変更したコード


<%= f.file_field :image, id: 'cutomfile', class: 'custom-file-input', name: 'cutomfile[]' %>

<!-- 出力 -->
<input id="cutomfile" class="custom-file-input" name="cutomfile[]" type="file" />

どうやらrailsのフォームヘルパーは

name=モデル名[属性(カラム)名]
id=モデル名_属性(カラム)名

で出力して送信の際にはnameを使って処理するらしい。

ターミナルのログを見ると


Started POST "/posts" for ::1 at 2021-01-26 12:11:25 +0900
Processing by PostsController#create as HTML
Parameters: {
  "authenticity_token"=>"", 
  "post"=>{"image"=>#<
  ActionDispatch::Http::UploadedFile:0x000055659a002788 
  @tempfile=#<Tempfile:/tmp/RackMultipart20210126-9817-k74a92.jpg>, 
  @original_filename="0e47c4bb12896adb102c93237bbe9554.jpg",
  @content_type="image/jpeg", 
  @headers="Content-Disposition: form-data; 

  #これ
  name=\"post[image]\"; 

  filename=\"0e47c4bb12896adb102c93237bbe9554.jpg\"\r\nContent-Type: 
  image/jpeg\r\n"
>, 
"body"=>""}, "commit"=>"送信"}

参考:Understanding Parameter Naming Conventions


railsガイドには

どのフォームinputを使う場合でも、id属性はinputのnameから生成されます。
これらのidは、cssでのスタイル追加やJavaScriptによるフォーム制御で使うのに便利です。

とあるように生成されたidのほうは変更しても影響しないみたいです(自分でidを指定した場合そちらが優先して使われる)

参考:
CodePen Bootstrap4 custom-file mutiple
Action View フォームヘルパー

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