【Rails】ユーザーの入力値を画像表示に反映させる
実装したいこと
記事投稿アプリで、記事のアイキャッチ画像を設定できます。
前提
記事投稿の機能は実装済です。
今回は画像の表示を変更する部分のみの実装です。
ファイルのアップデートはActive Storage
を使用しています。
どう実装していけばいいか
どうやって実装するか全く思いつかず、数時間悩んでしまいました。。シンプルにデータの流れと入出力を順を追って考えたら何とか実装できました。
- ユーザーが入力フォームに値を入力する
- 入力値を受け取って、保存する。
- 画像を表示するときに、保存した値を反映させる。
実装の流れ
- ユーザーの入力値を保存するためのカラムを追加する。
- 入力フォームを追加する。
- 画像表示部分の
class
を動的に変更する。
カラム追加
ユーザーの入力した「画像幅」・「画像位置」を受け取るカラムをそれぞれ作成します。
それぞれ、eyecatch_width
とeyecatch_position
としました。
ターミナルで、rails db:migrate
します。
enum設定
画像位置については、左寄せ・中央寄せ・右寄せの3択で設定できるようにします。
enum eyecatch_position: { left: 0, center: 1, right: 2 }
gem 'enum_help'
を使用しているので、翻訳ファイルを設定しておきます。
ja: enums: article: eyecatch_position: left: '左寄せ' center: '中央寄せ' right: '右寄せ'
Validation設定
ユーザーの入力値は、100~700px
に限定します。
空欄を許可しておかないと、アイキャッチ画像を設定せずに更新したいときにもバリデーションエラーになるので必須の設定です。
私は最初2行で設定してしまったのですが、1行で設定できるんですね。スマート
# BAD validates :eyecatch_width, allow_nil: true, numericality: { greater_than_or_equal_to: 100, message: 'は100以上の値にしてください' } validates :eyecatch_width, allow_nil: true, numericality: { less_than_or_equal_to: 700, message: 'は700以下の値にしてください' } # GOOD validates :eyecatch_width, numericality: { less_than_or_equal_to: 700, greater_than_or_equal_to: 100 }, allow_blank: true
入力フォーム作成
画像幅を入力するフォームと、画像位置を選択するラジオボタンを設置していきます。
= simple_form_for @article, url: article_path(@article) do |f| .box-body - if @article.eye_catch.attached? = image_tag @article.eye_catch_url(:thumb), class: 'img-thumbnail' br br = f.input :eyecatch_width = f.input_field :eyecatch_position, as: :radio_buttons # 以下NG ラジオボタンが重なってしまった = f.input :eyecatch_width = f.input :eyecatch_position, as: :radio_buttons
gem 'simple_form'
以上のコードのように、簡単にフォームを作れるgem
です。
画像表示部分のclass
を動的に変更する。
これが難しかったです。
Boot Strap
を使用しているので、class
名を変えれば、画像の位置を変えられそうです。
最初、article.eyecatch_position
の値をApplicationHelper
で判定して、class="float-right"
class="mx-auto d-block"
class="float-left"
を返す…と実装したのですが、それよりも、class="text-right"
class="text-center"
class="text-left"
を使用すれば、enumの値をそのまま使用できます。
画像幅は、保存した値をarticle.eyecatch_width
でそのまま取ってこれます。
# BAD - if article.eye_catch.attached? section.eye_catch class="#{eyecatch_position_class(article)}" #eyecatch_position_classというApplicationHelperメソッドを呼んでいた = image_tag article.eye_catch_url(:lg), style: "width: #{article.eyecatch_width}px;" # GOOD - if article.eye_catch.attached? section class="eye_catch text-#{eyecatch_position}" = image_tag article.eye_catch_url(:lg), class: 'img-fluid', width: article.eyecatch_width
Controller
Strong Parameterで入力できる値を追加します。
def article_params params.require(:article).permit(:eye_catch, :eyecatch_width, :eyecatch_position)#ここ end
参考
『パーフェクト Ruby on Rails』P225
『現場Rails』P306