Rails での QR コード生成について調べてみると、RQRCodeという gem を利用して実装していることが多いようです。
こちらを触ってみます。
目次
実行環境
参考
導入
Gemfile にgem 'rqrcode'
を追記して、bundle install
を実行。
実装
今回は Site モデルを作成して、URL を登録。
show 画面で QR コードが作成されるようにしてみます。
とりあえず scaffold で用意
以下コマンドで site を用意。
1 2
| rails generate scaffold site url:string rails db:migrate
|
http://localhost:3000/sites にアクセスすると以下の画面が出るはずです。
一旦ここまでできたら OK です。
適当に URL を登録しておきます。
コントローラの編集
QR コードを取扱いできるように sites コントローラを編集します。
as_svg のパラメータは、RQRCodeのままです。
app/controllers/sites_controller.rb1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class SitesController < ApplicationController require 'rqrcode' before_action :set_site, only: [:show, :edit, :update, :destroy]
def show qrcode = RQRCode::QRCode.new(@site.url) @qr = qrcode.as_svg( offset: 0, color: '000', shape_rendering: 'crispEdges', module_size: 6, standalone: true )
end
private def set_site @site = Site.find(params[:id]) end end
|
ビューの編集(誤り)
app/views/sites/show.html.erb を以下のように編集します。
ただしここでは一度失敗します。
app/views/sites/show.html.erb1 2 3 4 5 6 7 8 9 10 11 12
| <p id="notice"><%= notice %></p>
<p> <strong>Url:</strong> <%= @site.url %> </p> <div> <%= @qr %> </div>
<%= link_to 'Edit', edit_site_path(@site) %> | <%= link_to 'Back', sites_path %>
|
確認
http://localhost:3000/sites/1 にアクセスすると以下のような表示になります。
SVG がエスケープして表示されてしまいました。
修正が必要です。
ビューの編集(訂正)
改めて、app/views/sites/show.html.erb を以下のように編集します。
@qr.html_safe
とするのがポイントでした。
app/views/sites/show.html.erb1 2 3 4 5 6 7 8 9 10 11 12
| <p id="notice"><%= notice %></p>
<p> <strong>Url:</strong> <%= @site.url %> </p> <div> <%= @qr.html_safe %> </div>
<%= link_to 'Edit', edit_site_path(@site) %> | <%= link_to 'Back', sites_path %>
|
確認
改めて http://localhost:3000/sites/1 にアクセスすると以下のような表示になります。
QR コードの表示ができました。
登録した URL の QR コードが正しいのかは、スマートフォンで確認しています。
実装 2 ファイルを作成してリンクで表示する。
ここまでは表示都度 QR コードを作成していたので、今度はいったん画像を保存してリンクで表示することを試みてみます。
画像ファイルの url のカラムをテーブルに拡張
以下のコマンドで、site モデルに保存した画像の URL のカラムを追加します。
1 2
| rails generate migration add_columns_to_sites imgurl:string rails db:migrate
|
コントローラの編集
既に URL が投稿されているので、show アクションが呼び出されたときに imgurl が nil だったら QR コードのファイルを作成をするようにします。
最初からやるなら、create アクションに設定すればいい気がします。
app/controllers/sites_controller.rb1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class SitesController < ApplicationController require 'digest' require 'rqrcode' before_action :set_site, only: [:show, :edit, :update, :destroy]
OUTPUTPATH = "[publicへのフルパス]"
def show if @site.imgurl.nil? create_qr end end
private def set_site @site = Site.find(params[:id]) end
def create_qr qrcode = RQRCode::QRCode.new(@site.url) @qr = qrcode.as_svg( offset: 0, color: '000', shape_rendering: 'crispEdges', module_size: 6, standalone: true ) filename=Digest::MD5.hexdigest(@site.url)
IO.write("#{OUTPUTPATH}\\#{filename}.svg",@qr) @site.imgurl="#{filename}.svg" end end
|
ビューの編集
image_tag を使用して画像を表示します。
app/views/sites/show.html.erb1 2 3 4 5 6 7 8 9 10 11 12
| <p id="notice"><%= notice %></p>
<p> <strong>Url:</strong> <%= @site.url %> </p> <div> <%= image_tag "/#{@site.imgurl}" %> </div>
<%= link_to 'Edit', edit_site_path(@site) %> | <%= link_to 'Back', sites_path %>
|
確認
また http://localhost:3000/sites/1 にアクセスすると以下のような表示になります。
表示はこれまでと大差ありません。
しかし、public の中を見るとファイルが作成されているのが見て取れます。
html もリンクに変わっています。
ファイルを作成し、リンクで QR コード画像を表示することがでいました。
実装 3 とりあえずありそうなエラーを排除したバージョン
作成を進めていたら、以下のエラーがあったので対応しました。
コントローラの編集
app/controllers/sites_controller.rb1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| class SitesController < ApplicationController require 'digest' require 'rqrcode' before_action :set_site, only: [:show, :edit, :update, :destroy]
OUTPUTPATH = "[publicへのフルパス]"
def show if @site.imgurl.nil? && exist_file? create_qr end end
def create @site = Site.new(site_params) @site.url = @site.url.strip
respond_to do |format| if @site.save format.html { redirect_to @site, notice: 'Site was successfully created.' } format.json { render :show, status: :created, location: @site } else format.html { render :new } format.json { render json: @site.errors, status: :unprocessable_entity } end end end
def update respond_to do |format| if @site.update(site_params) @site.url = @site.url.strip format.html { redirect_to @site, notice: 'Site was successfully updated.' } format.json { render :show, status: :ok, location: @site } else format.html { render :edit } format.json { render json: @site.errors, status: :unprocessable_entity } end end end
private def set_site @site = Site.find(params[:id]) end
def create_qr qrcode = RQRCode::QRCode.new(@site.url) @qr = qrcode.as_svg( offset: 0, color: '000', shape_rendering: 'crispEdges', module_size: 6, standalone: true ) filename=Digest::MD5.hexdigest(@site.url)
IO.write("#{OUTPUTPATH}\\#{filename}.svg",@qr) @site.imgurl="#{filename}.svg" end
def exist_file? File.exist?("#{OUTPUTPATH}\\#{@site.imgurl}") end end
|
ビューの編集
app/views/sites/show.html.erb に変更はありません。
app/views/sites/show.html.erb1 2 3 4 5 6 7 8 9 10 11 12
| <p id="notice"><%= notice %></p>
<p> <strong>Url:</strong> <%= @site.url %> </p> <div> <%= image_tag "/#{@site.imgurl}" %> </div>
<%= link_to 'Edit', edit_site_path(@site) %> | <%= link_to 'Back', sites_path %>
|
モデルの編集
バリデーションを追加しました。
app/models/site.rb1 2 3
| class Site < ApplicationRecord validates :url,presence: true,format: /\A end
|
確認
バリデーションに引っかかれば、以下のように警告出せるようになりました。
空白削除を行ったので、QR コードを読んだときにただのテキストとして処理されなくなりましたが、
バリデーションと重複している要素とも感じます。
ただ、「空白が含まれています」って探すのも面倒な入力ミスなので、いいかなぐらいの感じです。
ファイルが削除されても、再度作成されるようにもなりました。
Rails での QR コード作成について確認できました。
これらを使って何か作りたいところです。
ではでは。