Posted at

rails4 + bootstrap + summernote(WYSIWYG Editor) とasync画像アップロードで快適なブログ記事編集フォームを実現

More than 5 years have passed since last update.

rails4で記事編集フォームを作ったので、その中でのtipsです。

以下の流れを実現しました。


  1. 記事編集中に画像を選択。

  2. 非同期で画像がサーバー側にアップロードされる。

  3. paperclipでサムネイルが作られてamazon-s3に転送される。

  4. 成功したら280x210サイズのURLを返す。

  5. 記事中に画像が埋め込まれるので、本文の編集を継続する。

bootstrap導入の説明は省きます。

rails側では、aws-sdkとpaperclipを使っています。

Summernote

http://hackerwins.github.io/summernote/

Summernoteについてはサンプルやgithub上で活発なやりとりがされているので、この辺りを見るとほとんどの問題は解決すると思います。

http://hackerwins.github.io/summernote/example.html

https://github.com/HackerWins/summernote/issues

Summernote本体は以下のcssとjsです。

<link href="/stylesheets/summernote.css" rel="stylesheet">

<script src="/javascripts/summernote.js"></script>

画像uploadのダイアログを開くとスクロールバーが消える現象が起こった場合、

masterでは同現象は解決されているので、masterから取得しなおして下さい。

みんな大好きfont-awesomeが必要になります。

 <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css">

あと日本語対応もしています。以下URLの内容を確認して問題なければそのまま利用するのが良いと思います。

https://github.com/HackerWins/summernote/blob/master/lang/summernote-ja-JP.js

ここまでが導入で、ここからが本題です。

erbのコードはこんな感じです。bodyが記事の本文で、本文中に画像が含まれます。

<%= f.text_field :title %>

<%= f.text_area :body, rows: 15 %>
<%= f.datetime_select :published_datetime, :use_month_numbers => true, :date_separator => '/', minute_step: 30, :include_blank => true, :default => nil %>

javascriptはこんな感じです。routesでresources :blog_imagesしているので、postメソッドを指定するとblog_images#createが呼ばれます。

$(document).ready(function() {

function sendFile(file, editor,welEditable) {
data = new FormData();
data.append("blog_image[image]", file);
$.ajax({
url: '/blog_images',
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
editor.insertImage(welEditable, data.url);
}
});
}

$('#blog_article_body').summernote({
height: 300, /*高さを指定*/
lang: 'ja-JP', /*日本語対応*/
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['fontsize', ['fontsize']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['height', ['height']],
['insert', ['picture', 'video']],
],
onImageUpload: function(files, editor, welEditable) {
sendFile(files[0], editor,welEditable);
}
});
});

モデルはpaperclipを使ってこんな感じです。


class BlogImage < ActiveRecord::Base

belongs_to :blog

has_attached_file :image, Proc.new {
options = {
:storage => :s3,
:s3_credentials => "#{Rails.root.to_s}/config/s3.yml",
:s3_permissions => "public-read",
:s3_headers => {'Expires' => 10.year.from_now.httpdate},
:styles => {
:"70x52" => ["70x52#", :jpg], # 4:3
:"280x210" => ["280x210#", :jpg], # 4:3
},
#:convert_options => { :thumb => "-quality 85"},
:default_url => "/images/:style/missing.png",
:size => { :in => 0..(4.megabytes) }
}
}.call

validates_attachment_content_type :image, :content_type =>/^image\/(.*)/

def file
Paperclip.io_adapters.for(image)
end

def url(style = "")
"https://s3-ap-northeast-1.amazonaws.com/webcreation.co.jp.samlet.resources/" + image.path(style)
end

end

controllerはこんな感じです。成功したらjsonでURLを返します。そのURLがブログ側でそのまま埋め込まれます。

  def create

@blog_image = BlogImage.new(params.require(:blog_image).permit(:image))
@blog_image.blog_id = current_user.venue.blog.id
if @blog_image.save
render json: {url: @blog_image.url("280x210")}, status: 200
else
render nothing: true, status: 500
end
end

記事編集中に画像が自然にUPLOADされて、本文に埋め込まれるので快適です。