##環境
####・開発環境
Rails 5.2.3
Ruby 2.5.7
windows
vagrant
bootstrap,jquery導入済み
####・本番環境
EC2
RDS
Mysql
##summernote
・summernoteのgithub
https://github.com/summernote/summernote-rails
リッチテキストエディタが簡単に実装できる便利なgemです。
rails6からはaction textというデフォルトの機能で実装できますが、自分はrails5なのでsummernoteをつかいました。
rails5での実装方法はほかにもあります。
##他の実装方法
####①action textを導入する。
rails6標準の機能ですが、rails5にも導入できます。
rails5.2での導入デモ(英語です)
デモ通りやってもyarnなどに関するエラーが出ますが、僕は、yarnやwebsocketの導入がわからず断念しました。
rails6の環境構築ができている人は、こちらがいいと思います。
####②gem froalaを使う
こちらは比較的簡単に導入できますが、画像の保存まで下の記事でできたかは覚えてないです。。。
課金しないと余計なテキストが表示されます。
frola実装記事
####③gem trixをつかう
rails 6のaction textと同じ記述のものがgemとして切り出されたものらしいです。
こちらはまだ試してません。
##実装!
summernoteのgit hub通り実装していきます。
####①gemの導入
gem 'simple_form'
gem 'summernote-rails', '~> 0.8.10.0'
READMEでは、summernote-railsを '0.8.16.0'とありますがbundel installでそんなバージョンはないよと言われてしまったので、とりあえずこのバージョンで実装しました。
bundle install
####②application.scssを編集
以下を追加します。
@import "summernote-bs4";
####③application.jsを編集
以下を追加します。
//= require summernote/summernote-bs4.min
//= require summernote-init
####④summernote-init.cofeeファイルを作成する。
手動で作成しました。
READMEのコードをそのまま書きましょう。
$(document).on 'turbolinks:load', ->
$('[data-provider="summernote"]').each ->
$(this).summernote
height: 300
####⑤viewを編集
#####form_forの場合
フォームの中に5行目の1行を設置するだけでリッチテキストエディタになります。
<%= form_for(post) do |form| %>
・・・
<div class="field">
<%= form.label :text %>
<%= form.text_area :text, 'data-provider': :summernote %> #この行
</div>
・・・
<% end %>
# =を2つ付ける
<%== post.text %>
以上でローカルサーバーを起動すると、テキストエディタが使えるようになっています!(超簡単!)

と、思いきや、、、、
deploy環境ではこのままだとうまくいきませんでした。。。
##本番環境でのエラー
deploy環境用に改善していきます。
###①summernoteが適用されない
原因 : rails_ujsとjquery_ujsが共存できない!(僕はもともとrails_ujsを記述してあったのにreadmeの内容をそのまま書いたのでうまくいきませんでした)
解決:summernoteのgit hubではjquery_ujsを入れてますが、rails_ujsとぶつかってしまうのでrequire jquery_ujsを消しました。
rails_ujsの記述があればjquery_ujsは消して大丈夫です。
ローカルではエラーにならなかったので気付きませんでした。
###②画像を貼り付けると投稿後エラーになる。
僕の場合、開発環境ではsqlite3、本番環境ではmysqlを使用していましたが、mysqlではbodyの文字列が長過ぎる!と怒られてしまいました。。。
本番環境で同じようなエラーが起きた場合は以下の方法で解決できると思います。
bodyにtextとして含んでいた画像部分を他modelのカラムとして切り離します!
####carrierwaveを導入
gem 'carrierwave'
####uploadモデルとuploaderを作成
$ rails g model Upload image
$ rails g uploader Image
class Upload < ApplicationRecord
mount_uploader :image, ImageUploader
end
コントローラを作成
$ rails g controller uploads create destroy
class UploadsController < ApplicationController
def create
@upload = Upload.new(upload_params)
@upload.save
respond_to do |format|
format.json { render :json => { url: @upload.image.url, upload_id: @upload.id } }
end
end
def destroy
@upload = Upload.find(params[:id])
@remember_id = @upload.id
@upload.destroy
FileUtils.remove_dir("#{Rails.root}/public/uploads/upload/image/#{@remember_id}")
respond_to do |format|
format.json { render :json => { status: :ok } }
end
end
private
def upload_params
params.require(:upload).permit(:image)
end
end
####summernote-init.cofeeを編集する。
元の記述を消して以下で置き換えます。
sendFile = (file, toSummernote) ->
data = new FormData
data.append 'upload[image]', file
$.ajax
data: data
type: 'POST'
url: '/uploads'
cache: false
contentType: false
processData: false
success: (data) ->
img = document.createElement('IMG')
img.src = data.url
console.log data
img.setAttribute('id', "sn-image-#{data.upload_id}")
toSummernote.summernote 'insertNode', img
deleteFile = (file_id) ->
$.ajax
type: 'DELETE'
url: "/uploads/#{file_id}"
cache: false
contentType: false
processData: false
$(document).on 'turbolinks:load', ->
$('[data-provider="summernote"]').each ->
$(this).summernote
lang: 'ko-KR'
height: 400
callbacks:
onImageUpload: (files) ->
sendFile files[0], $(this)
onMediaDelete: (target, editor, editable) ->
upload_id = target[0].id.split('-').slice(-1)[0]
console.log upload_id
if !!upload_id
deleteFile upload_id
target.remove()
####ルーティングを設定
resources :uploads, only: [:create, :destroy]
これで、画像は別modelとして保存されます。
####③画像が表示されない。
本番環境で画像が表示されなかったので僕の場合config/environment/production.rbに追記しました。
config.public_file_server.enabled = true
この行を追加します。
####④S3へのアップロード
記事の画像のS3へのアップロードを設定したところ投稿後しばらく経つと画像が表示されなくなるよになってしまいました。
summernoteの性質上、最初に与えられたトークンごと文字列として保存してしまうので表示のたびにトークンが更新されず10分で表示されなくなります。
config.fog_publicをtrueにすることでトークンをなくせるので10分たっても消えません。(今回作ったのはブログのようなもので、他人にみてもらうことが前提なのでセキュリティ的な問題はないと判断しました。)
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'
CarrierWave.configure do |config|
if Rails.env.production? # 本番環境の場合
:
:
config.fog_public = true
:
:
end
end