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

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です。

```html
<link href="/stylesheets/summernote.css" rel="stylesheet">
<script src="/javascripts/summernote.js"></script>
```

画像uploadのダイアログを開くとスクロールバーが消える現象が起こった場合、
masterでは同現象は解決されているので、masterから取得しなおして下さい。

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

```html
 <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が記事の本文で、本文中に画像が含まれます。

```erb
<%= 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が呼ばれます。

```js
$(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を使ってこんな感じです。

```rb

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がブログ側でそのまま埋め込まれます。

```rb
  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されて、本文に埋め込まれるので快適です。