【10分でできる】Railsに画像の動的生成機能をサクッと追加する

さて、昨今、Twitterのぶり返しもあり、OGP画像の需要が増しています。（そ、そうですよね・・・）

自社サービスにおいて、OGP画像をコンテンツごとに動的に生成したいんだけど・・・という技術的ニーズも生まれていることでしょう。

当アカウントが運営するIT系フリーランス案件/求人検索サービス「[OKWorks](https://www.okworks.me/)」では、案件詳細ページのOGP画像に、案件のタイトルを入れたいな・・・というアイデアがありましたが、しばらく放置されておりました。

![ogp.png](https://qiita-image-store.s3.amazonaws.com/0/304536/4927da4c-6237-4273-c214-b0073c2500fb.png)
↑こういう画像です

重い腰を上げ、いざ実装してみたところ、意外と汎用性が高く、普及できるな・・・と思いましたので、ここでRailsに画像の動的生成機能をサクッと追加する方法をまとめて、共有します。

この記事を参考にすれば、OGP画像の動的生成機能をさくっとRailsに組み込むことができる・・・はずです😋

## 作るもの
・テキストを引数にして、画像を動的に生成する機能。特に今回はOGP画像

## 開発方針
・画像の保存はしない。アクセスしたときに都度生成する
・URLでアクセスできるようにする

この「画像の保存はしない」というのはHerokuを使っているので、ファイルの書き込みができず、S3をつかわないといけないため、めんどくさいな・・・と思ったからです。基本的に、OGP画像はSNSにキャッシュされるので、そこまでスケーリングが求められません。なので、画像の保存はしないことにしました。とはいえ、この方針のほうが、サクッと導入できるので、更に良いと思います😋

## できたもの
https://www.okworks.me/images/ogp.png?text=hogehoge
https://www.okworks.me/images/ogp.png?text=あいうえおかきくけこさしすせそ

## 開発環境
・Ruby 2.5.1p57
・Rails 5.2.1

# やっていきます！

※すでにRailsアプリはあることを前提にしています。

### 1. GemfileにMiniMagickを追加

```ruby:Gemfile
gem 'mini_magick'
```

MiniMagickは、ImageMagickを使いますので、入っていない方は下記などを参考に入れておいてください。

[mac にImageMagickをインストールし、convertコマンドで画像を縮小する。](https://qiita.com/sowd/items/832594dd22d99aebc8a2)

### 2. bundle install
```
bundle install
```

### 3. 背景画像を作成

OGP画像なので、1500*500の画像を推奨します。

OKWorksでは、　
https://www.okworks.me/assets/ogp_base_okworks.jpg
を使っています。

背景画像を作成し、assets/images以下に配置してください。（お好みの場所で）

### 4. 日本語フォントを配置する

お好みの日本語フォントなどを、assets/fonts以下に配置します。
フォントファイルは、ttfファイルやttfファイルなどです。

### 5. OgpCreatorクラスを作成

app/controllers/concerns以下にogp_creator.rbを下記コードにて、作成してください。これは、画像を作成するクラスとなります。

その後で、下記
{ 背景画像ファイルのパスを記載　}
{ フォントファイル名を記載　}
の2箇所を実際のファイル名で置き換えてください。

```ruby:app/controllers/concerns/ogp_creator.rb
class OgpCreator
  require 'mini_magick'  
  BASE_IMAGE_PATH = './app/assets/images/{ 背景画像ファイル名を記載　}'
  GRAVITY = 'center'
  TEXT_POSITION = '0,0'
  FONT = './app/assets/fonts/{ フォントファイル名を記載　}'
  FONT_SIZE = 65
  INDENTION_COUNT = 16
  ROW_LIMIT = 8

  def self.build(text)
    text = prepare_text(text)
    image = MiniMagick::Image.open(BASE_IMAGE_PATH)
    image.combine_options do |config|        
      config.font FONT
      config.fill 'white'
      config.gravity GRAVITY
      config.pointsize FONT_SIZE
      config.draw "text #{TEXT_POSITION} '#{text}'"
    end
  end

  private
  def self.prepare_text(text)
    text.to_s.scan(/.{1,#{INDENTION_COUNT}}/)[0...ROW_LIMIT].join("\n")
  end
end
```

### 6. OGP用のコントローラーを追加

```
rails g controller images ogp --skip-template-engine
```

viewファイルはいらないので、`--skip-template-engine`を使っておきます

### 7. Routeファイルを修正

```ruby:config/route.rb
get 'images/ogp.png', to: 'images#ogp', as: 'images_ogp'
```
.pngと明示的にしておきましょう。

### 8. ImagesControllerファイルを修正

```ruby:app/controllers/images_controller.rb
class ImagesController < ApplicationController
  def ogp
    text = ogp_params[:text]
    image = OgpCreator.build(text).tempfile.open.read
    send_data image, :type => 'image/png',:disposition => 'inline'
  end

  def ogp_params
    params.permit(:text)
  end
end
```

ImagesControllerを上記のように置き換えてください。
説明しておきます。

```
text = ogp_params[:text]
```
画像に表示させたいテキストを取得します

```
image = OgpCreator.build(text).tempfile.open.read
```
OgpCreatorが表示させたいテキストを追加した画像を作成します。それをblobという形式で取得します。

```
send_data image, :type => 'image/png',:disposition => 'inline'
```
blob形式の画像をpngファイルとして、レンダリングします。

### 9. 試してみる

さあ、これで実装は終了です。

/images/ogp.pngにアクセスしてみてください。

textパラメーターを追加して・・・

/images/ogp.png?text=hoge
/images/ogp.png?text=こんにちわ

などなど、いろいろと画像が表示されるのではないでしょうか？

# まとめ

いかがでしたでしょうか？サクッと動的な画像生成は実装できましたか？
ogp_creator.rbファイルを修正することでいろいろカスタマイズできますので是非試してみてくださいね！

本記事の内容については

https://twitter.com/codeq_official

からサポートしておりますので、ぜひお気軽にご連絡ください！


# お知らせ

[OKWorks](https://www.okworks.me)というIT向けのフリーランス案件の検索サービスを運営しています。ぜひこちらもご利用いただけると幸いです。