Railsチュートリアルで作ったサンプルアプリの「ファイルを選択」ボタンをかっこよくしてみた

##環境
* Windows10 Home ver.2004
* ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x64-mingw32]
* Rails 6.1.0

##はじめに
　[Railsチュートリアルの13.4.1章](https://railstutorial.jp/chapters/user_microposts?version=6.0#sec-basic_image_upload)では、サンプルアプリに画像付きマイクロポスト投稿機能を追加するのだが、デフォルトだと画像を選ぶ際にクリックする「ファイルを選択」ボタンが~~ダサい~~他のボタンとの統一感のなさのせいで目立ってしまう。
![スクリーンショット 2021-01-09 155648.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987065/2c116bde-6af8-a2c4-b1ea-cfeb2b0d6120.png)
　この状況をなんとかしたいと思い、色々試してみた。

##結果
　デフォルトのボタンを非表示にした上で別のボタン「Choose an image」を用意し、そのボタン経由でデフォルトのボタンを押させることによって、機能を損なわずに見た目に統一感を出すことができた。
![スクリーンショット 2021-01-09 174852.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987065/29c202f2-664c-011e-9dfe-6fc1cc2e9cc7.png)
　マウスオーバー処理も含め、下の「Post」ボタンのデザインをできる限り忠実に再現した。
![スクリーンショット 2021-01-09 174923.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987065/415008c4-86e2-b2d4-6cbb-33c9dc06f6bb.png)
　もちろん、デフォルトの動作と同様に、画像を選択した場合はそのファイル名が表示される。
![スクリーンショット 2021-01-09 174947.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987065/89b0e5f9-05d7-d68c-ac08-867a243bab2f.png)

　変更・追加したコードは次の通り。なお、今回は勉強のためにBootstrap用のクラスはあえて使わずに実装してみた。

```erb:app\views\shared\_micropost_form.html.erb
・
・
・
  <button type="button" class="general_button" onclick="document.getElementById('micropost_image').click()">
    Choose an image
  </button>
  <div id="image_name">No image is chosen...</div>
・
・
・
<script type="text/javascript">
  $("#micropost_image").bind("change", function() {
    let chosen_image = this.files[0];
    if (chosen_image.size/1024/1024 > 5) {
      alert("Maximum file size is 5MB. Please choose a smaller file.");
      $("#micropost_image").val("");
      document.getElementById('image_name').innerHTML = "No image is chosen...";
    }
    else {
      document.getElementById('image_name').innerHTML = "Chosen image: " + chosen_image.name;
    }
  });
</script>
```

```scss:app\assets\stylesheets\custom.scss
.general_button{
    color: white;
    background-color: $blue-for-button; // #337ab7
    border: 0.5px solid $blue-for-button-border; // #2e6da4
    border-radius: 3.5px;
    padding-top: 6.5px; padding-bottom: 6.5px;
    padding-right: 10px; padding-left: 10px;
    &:hover {
        background-color: $dark-blue-for-button; // #285f90
        border-color: $dark-blue-for-button-border; // #204d74
    }
}

#image_name {
    margin-top: 1px;
    margin-left: 1px;
    margin-bottom: 9px;
}

#micropost_image{
    visibility: hidden;
}
```

##結果までの流れ
####1.
　適当なキーワードで検索したらいくつか参考にできそうな記事[^1][^2]がヒットしたが、それらをそのまま自分の状況に適用するのは難しそうなので、具体的なコードの書き方は自分で考えてみることにした。

####2.
　あるオブジェクトがクリックされたことをトリガーとして別のオブジェクトのイベントを作動させるという処理を実現するコードの書き方を調べるため、「javascript html ボタン 押させる」などのキーワードで検索したら、[「JavaScriptでボタンを押すアクションを起こす | forWEB屋」](https://www.4web8.com/226.html)がヒットした。
　このサイトを基に、デフォルトの「ファイルを選択」ボタンのクリックイベントを作動させるための別のボタン「Choose an image」を作った（`_micropost_form.html.erb`内参照）。

####3.
　続いて、ユーザーが選択した画像ファイル名をどうやって表示しようかと考えた結果、[Railsチュートリアル内のリスト13.67](https://railstutorial.jp/chapters/user_microposts?version=6.0#code-jquery_file_test)に書かれていた、選択された画像のファイルサイズが5MBより大きかった場合にアラートを出すJavaScriptコードを改造することにした（`_micropost_form.html.erb`内参照）。
　途中で`f.file_field`に独自の`id`を追加したらアラートを出すJavaScriptが動作しなくなるトラブルが起こったが、JavaScriptコードを読んで既に`id`として`micropost_image`が設定されていることに気付き、独自の`id`を削除したら再び動作するようになった。

####4.
　これまでで動作に関する部分の実装は概ね終わっていたので、[「CSSリファレンス - とほほのWWW入門」](http://www.tohoho-web.com/css/index.htm)を参考に、時には画像編集ソフトのスポイト機能を使ってスクリーンショットから色の情報を取ったりしつつ`custom.scss`を編集した。

以上

[^1]: [Rails][file_field]画像のアップロードのボタンデザインを変更する - Qiita(https://qiita.com/Yukina_28/items/4a8332354f6cb7c7a6f6)
[^2]: railsのfile_fieldで画像クリックによりアップロード - Qiita(https://qiita.com/zukakosan/items/41ed95fea2323cf458a9)