はじめに
現在、記事にアイキャッチ画像を設定することはできますが、表示する際に画像の大きさと表示位置が選べません。 入力フォームによってアイキャッチ画像の横幅を設定できるようにし、ラジオボタンで選択した位置に画像が表示されるように変更しましょう。
今回、画像アップロード機能はActive Storageというgemを使っています。
まずはActive Storageについて抑えておきましょう。
Active Storage
Rails5.2からActive Storageというファイル管理gemが導入され、Amazon S3などのクラウドストレージサービスへファイルをアップロードして、DB上でActiveRecordモデルに添付することが簡単になりました。添付はどんな種類でもできますが、画像はサイズや形式の変換、ビデオ・PDFはプレビュー機能を提供してくれます。
デコレーターをコードリーディング
画像がどのように実装されているのか見る中で、eye_catch_url
メソッドがデコレータの中で改造されている事に気が付きました。 こちらのデコレータはDraperではなく、ActiveDecorator
というgemを使っています。
module ArticleDecorator
def eye_catch_url(version = :origin) # 引数を渡す。 デフォルト値は origin
if !eye_catch.attached? || eye_catch.metadata.blank? # 画像がない場合、もしくは画像のメタデータがからの場合
return '/images/eye_catch.jpg' # '/images/eye_catch.jpg' を返す
end
command = case version # version が、
when :thumb # :thumb の場合
{ resize: '640x480' }
when :lg # :lg の場合
{ resize: '1024x768' }
when :ogp # :ogp の場合
{ resize: '120x630' }
else
false
end
command ? eye_catch.variant(command).processed : eye_catch # command がtrue の場合、条件分岐された結果に画像がリサイズされる。 falseの場合、リサイズされず、eye_catch が返される
end
end
attached?
: レシーバのオブジェクトに指定のファイルが紐付いていればtrue
を返す。紐付いていなければ、false
を戻り値として返すメソッド。variant
: 画像を変換する際に使われるメソッド。このメソッドを使うためには、image_processing gem
をGemfile
に追加する必要がある。processed
: これを付けることで、すでにそのサイズで保存されて画像があれば、変換処理は行われず、即時にURLが返される。
Active Storageの導入
gemのインストールはRailsインストール時に行われているので不要です。
$ rails active_storage:install
コマンド実行時に、active_storage_blobs
とactive_storage_attachments
という2つのテーブルを作成するマイグレーションファイルが生成されます。
$ rails db:migrate #migrationファイルをDBに反映させる。
active_storage_blobs
: 実際にアップロードしたファイルが保存されるテーブル(実際はファイル名、ファイルの種類、バイト数、誤り検出符号などのファイルデータを保持するテーブル)
active_storage_attachments
: 実際に操作を行うモデルとactive_storage_blobs
を紐づける中間テーブル
ファイルの保存先の設定
ファイルの保存先は、各環境の設定ファイルに記載します。 config/environments/development.rb
の中身を見てみます。
#デフォルトではdevelopment環境のファイルの管理場所はlocalとなっている
config.active_storage.service = :local # この local とは、config/storage.yml で定義された保存先の名前
設定はconfig.active_storage.service
にファイルを保存する場所を名前で指定し、そのファイルの保存場所の名前に対応する設定をconfig/storage.yml
に定義することで行います。 例えば、:local
のところを :amazon
, :google
, :microsoft
などに置き換え、config/storage.yml
の方に、必要な認証情報などの値を入力します。
config/storage.yml
の中身を見てみます。
local: #localにおいてあるファイルの設定方法(デフォルト)。ここで、localを定義している。
service: Disk #localの時は使用するサービスをローカルディスクに設定
root: <%= Rails.root.join('tmp', 'storage') %> #ファイルを格納する場所
test: #testにおいてあるファイルの設定方法。ここで、testを定義している。
service: Disk #testの時は使用するサービスをローカルディスクに設定
root: <%= Rails.root.join('tmp', 'storage') %> #ファイルを格納する場所
ここのファイルに書いてある情報(ルート、サービスなど)をもとに、モデルが実際のファイルを取得しに行きます。
カラム追加
class AddColumnToArticles < ActiveRecord::Migration[5.2]
def change
add_column :articles, :eyecatch_width, :integer
add_column :articles, :eyecatch_align, :integer, default: 0, null: false
end
end
defalt: 0
: デフォルト値が設定されない場合、0になるよう設定します。
null: false
: NULLを許可しないよう設定します。
enumの設定
enum align: { left: 0, center: 1, right: 2 }
バリデーションの設定
validates :eyecatch_width, numericality: { less_than_or_equal_to: 700, greater_than_or_equal_to: 100 }, allow_blank: true
numericality
: このヘルパーは、属性に数値のみ使われていることを検証します。デフォルトでは、整数または浮動小数点にマッチします。
オプション
less_than_or_equal_to
: 指定された値と等しいか、それよりも小さくなければならないことを指定します。greater_than_or_equal_to
: 指定された値と等しいか、それよりも大きくなければならないことを指定します。
コントローラ設定
追加した2つのカラムがストロングパラメータで受け取れる値として追加しましょう。
def article_params
params.require(:article).permit(
:title, :description, :slug, :state, :published_at, :eye_catch, :eyecatch_width, :eyecatch_align, :category_id, :author_id, tag_ids: []
)
end
入力フォームの作成
= simple_form_for @article, url: admin_article_path(@article.uuid) 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, placeholder: '100' # 追加 プレースホルダーを100に設定
= f.input_field :eyecatch_align, as: :radio_buttons # 追加 f.input だと正しく出力されない。ラジオボタンを使うときはf.input_fieldを使う
= f.input :description, input_html: { class: 'js-autosize' }

simple_formについて
今回の使っている入力フォームは、最低限の記述で簡単に入力フォームを生成できるsimple_formというgemを使っています。 Railsでフォームを作成するにはform_withを使えば実装できますが、simple_formを使えばより簡単にフォームを作成することができ、カスタマイズも容易です。
ビューファイル
画像表示部分のclassを動的に出力する
- if article.eye_catch.attached?
section.eye_catch class="text-#{article.eyecatch_align}"
= image_tag article.eye_catch_url(:lg), class: 'img-fluid', width: article.eyecatch_width
難しく考えて判定ロジックなどをヘルパーメソッドとして作らなくても、eyecatch_align
のenumを利用して class="text-right"
, class="text-center"
, class="text-left"
を出力するようにすれば、簡単に画像の位置を変更することができます。
enum eyecatch_align: { left: 0, center: 1, right: 2 }
[2] pry(main)> article.eyecatch_align
=> "center"
widthの値も同じ要領で設定します。
参考記事


コメント