LoginSignup
0

More than 1 year has passed since last update.

rials6.1でmarkdownを使用したミニブログアプリを作ってみる

Last updated at Posted at 2021-11-15

1. 開発環境

  • M1 Mac Monterey 12.0.1
  • ruby3.0
  • rails6.1.4.1

githubはこちらです。

オリジナルアプリにActionTextかMarkdownかで迷ったのでミニアプリを作って比べてみることにしました。

2. 実装開始

2.1 アプリ作成、初期設定

まずは新しいアプリの作成をしていきます。
rails _6.1.4.1_ new markdown-blog -d mysql

database.ymlの編集をします。

config/database.yml
default: &default
  adapter: mysql2
  # encoding: utf8mb4
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

2.2 turbolinksの無効化

以下の2つのファイルを編集、修正していきます。

app/javascript/packs/application.js
import Rails from "@rails/ujs"
// import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"

Rails.start()
Turbolinks.start()
ActiveStorage.start()
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>MarkdownBlog</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <!-- 'data-turbolinks-track': 'reload'を削除 -->
    <%= stylesheet_link_tag 'application', media: 'all' %>
    <%= javascript_pack_tag 'application' %>
    <!-- ここまで -->

  </head>

  <body>
    <%= yield %>
  </body>
</html>

2.3 必要なもののインストール

まずは追記をします。

gemfile
gem 'image_processing', '~> 1.2'

続いてターミナルで以下を実行していきます。

bundle install
rails db:create
rails active_storage:install
rails db:migrate
yarn add simplemde
yarn add inline-attachment

ここでは

  • ActiveStorage(ファイルアップロードの機能)
  • SimpleMDE(ブラウザ上のtextareaタグをMarkdownエディタを変換するOSS)
  • Inline Attachment(ブラウザ上からドラッグ&ドロップでのAjaxでのファイル送信を簡単に実装)

を導入しています。

2.4 model, controller, viewの編集

scaffoldでサクッと作成していきます。
rails g scaffold post content:text
rails db:migrate

続いて以下のファイルを編集します。

app/views/posts/_form.html.erb
<!-- 追記(画面で読み込むjsを読み込む) -->
<%= javascript_pack_tag 'post' %>

<%= form_with(model: post) do |form| %>
  <% if post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
        <% post.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :content %>
    <!-- 編集 -->
    <%= form.text_area :content, { id: "markdown-editar"} %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

続いてapp/javascript/packs配下にpost.jsを作成します。
そして以下のように記述していきます。ここではSimpleMDEの導入と、ドラッグ&ドロップの処理を記述しています。

app/javascript/packs/post.js
//インストールした機能をimportする
import "inline-attachment/src/inline-attachment";
import "inline-attachment/src/codemirror-4.inline-attachment";
import 'simplemde/dist/simplemde.min.css'
import SimpleMDE from "simplemde";
import Rails from '@rails/ujs'

window.onload = function () {
  // textareaをMarkdownエディタにする
  const simplemde = new SimpleMDE({
    element: document.getElementById("markdown-editar"),
  });
  // エディタに画像がドラッグ&ドロップされた際の処理
  inlineAttachment.editors.codemirror4.attach(simplemde.codemirror, {
    uploadUrl: "/posts/attach", // POSTする宛先Url
    uploadFieldName: "image", // ファイルのフィールド名(paramsで取り出す時のkey)
    allowedTypes: ['image/jpeg', 'image/png', 'image/jpg', 'image/gif'],
    extraHeaders: { "X-CSRF-Token": Rails.csrfToken() }, // セキュリティ対策
  });
};

2.5 ajaxの処理

rails g model attachment
で以下のように編集します。

app/model/attachment.rb
class Attachment < ApplicationRecord
  has_one_attached :image
end

続いてはコントローラーの処理です。ここでjson形式にして値を返します。

app/controller/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_post, only: %i[ show edit update destroy ]

  # GET /posts or /posts.json
  def index
    @posts = Post.all
  end

  # 略

  # Ajax通信の記述を追記
  def attach
    attachment = Attachment.create! image: params[:image]
    render json: { filename: url_for(attachment.image) }
  end
    # ここまで

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def post_params
      params.require(:post).permit(:content)
    end
end

最後に以下を追記してください。

config/route.rb
post 'posts/attach', to: 'posts#attach'

これで画像の処理ができました。しかし、これではmarkdownがhtmlに変換されずに出力されてしまいますので直していきます。
まずは現状確認からしていきましょう。

2.6 redcarpetの導入

現状確認

ドラッグ&ドロップしてみてください。
スクリーンショット 2021-11-15 0.36.50.png

うまくアップロードできていますが、create postをクリックすると...
スクリーンショット 2021-11-15 0.38.48.png

これはまずいですね。そのまま表示されています。
これからmarkdownがhtmlに変換していきます。gemで解決します。

以下を追記してください。

gemfile
gem 'redcarpet'

bundle install

これでひとまず導入が完了です。
続いてapp/helpermarkdown_helper.rbファイルを作成します。さらに以下のように記述していきます。

app/helper/markdown_helper.rb
module MarkdownHelper
  def markdown(text)
    unless @markdown
      options = {
        filter_html: true,
        autolink: true,
        space_after_headers: true,
        no_intra_emphasis: true,
        fenced_code_blocks: true,
        tables: true,
        hard_wrap: true,
        xhtml: true,
        lax_html_blocks: true,
        strikethrough: true
      }
      renderer = Redcarpet::Render::HTML.new(options)
      @markdown = Redcarpet::Markdown.new(renderer)
    end

    @markdown.render(text).html_safe
  end
end

さらに詳細ページを編集していきます。

app/views/posts/show.html.erb
<p id="notice"><%= notice %></p>

<p>
  <strong>Content:</strong>
  <!-- ここを編集 -->
  <%= markdown(@post.content) %>
</p>

<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>

これでアップした画像が表示されるはずです。
スクリーンショット 2021-11-15 0.50.26.png

これで完了です!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0