はじめに
こんにちは!
DMM WEBCAMP Advent Calendar 2023 24日目も、同じく @Keichan_15 が担当させて頂きます!
今回はやはり普段Railsをお教えしている身として、ちゃんとRailsに関する記事を書こうかなと…
ところで、皆さんは Action Text と呼ばれるRails6から追加された新機能についてご存じでしょうか。
Action Textはリッチテキストを編集するための便利なエディター で、通常よりもモダンなフォームを作成することができるエディターです。
こんな感じのヤツ ↓
とても便利な機能なのですが、実はWebpacker側でBootstrapを管理している状態で共存させると… ↓
モダン云々のレベルを超えてる こんな感じで酷過ぎる画面にダウングレードします。おいAction Text!仕事せえ!
そこで本記事では、
- この現象が発生するパターンってどんな時?
- BootstrapをWebpacker側で管理する場合でも、共存して表示できるようにするには?
上記2つに絞ってご紹介していきたいと思います!
早速リッチテキストエディタを復活させる旅の出発です!!
環境
- Ruby(3.1.2)
- Rails(6.1.7.6)
- Node.js(16.18.0)
- Bootstrap(4.6.2)
- WSL2(Ubuntu 20.04.5 LTS)
- Visual Studio Code
事前準備
今回はAction Textを動作させるために、シンプルなタスク管理アプリケーションを作成しました。
今回、Rails6からデフォルトで入っている Webpackerを用いてBootstrapを管理する手法を取っていた としましょう。
要するに以下のような形で app/javascript
配下でCSS
, JS
周りを管理しているパターンですね。
導入方法について細かく知りたい場合は、以下にて紹介されています!
今回はこちらの記事を参考に、若干アレンジを加えて導入しています。
$ yarn add jquery bootstrap@4.6.2 popper.js
const webpack = require('webpack')
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery',
Popper: 'popper.js'
})
)
application.scss
については別途、新規作成が必要です。
@import '~bootstrap/scss/bootstrap';
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import "jquery";
import "popper.js";
import "bootstrap";
import "../stylesheets/application";
Rails.start()
Turbolinks.start()
ActiveStorage.start()
<!DOCTYPE html>
<html>
<head>
<title>TestApp</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
resources :tasks
end
これで最低限、Bootstrapを使用する準備が整いました!
Model & Controller & View 作成
では早速Action Text
を使用してみましょう!
導入手順はRailsガイドを参考にしながら進めていきます!
まずAction Text
をインストールします。
$ rails action_text:install
インストールが完了すると同時に、application.js
に以下の記述が追加されていることを確認します。
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import "jquery";
import "popper.js";
import "bootstrap";
import "../stylesheets/application";
Rails.start()
Turbolinks.start()
ActiveStorage.start()
// この2行が自動で追加されていることを確認!
+ require("trix")
+ require("@rails/actiontext")
次にModel
を作成します。
今回はシンプルなタスク管理のアプリケーションのため、Task
という命名のModel
を作成しました。
$ rails g model Task
カラムは以下を用意しました。
-
title
: タスクのタイトル
class CreateTasks < ActiveRecord::Migration[6.1]
def change
create_table :tasks do |t|
t.string :title
t.timestamps
end
end
end
$ rails db:migrate
今回はこのTask
というモデルに、リッチテキストエディタのフィールドを追加します。
task.rb
に以下の1行を追加します。
class Task < ApplicationRecord
+ has_rich_text :content
end
次にView
を作成します。
<div class="container">
<div class="row">
<div class="col-md-12">
<% @tasks.each do |task| %>
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr>
<td><%= task.title %></td>
<td><%= task.body %></td>
<td><%= task.content %></td>
</tr>
</tbody>
</table>
<% end %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h2>New Task</h2>
<%= form_with model: @task do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :content %>
<%= f.rich_text_area :content, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit 'Create Task', class: "btn btn-success" %>
</div>
<% end %>
</div>
</div>
</div>
最後にController
を作成し、タスク投稿機能を実装していきましょう!
$ rails g controller tasks
class TasksController < ApplicationController
def index
@tasks = Task.all
@task = Task.new
end
def create
@task = Task.new(task_params)
@task.save
redirect_to tasks_path
end
private
def task_params
params.require(:task).permit(:title, :content)
end
end
実装内容に問題が無ければ/tasks
に遷移してみましょう。
一旦以下のような表示になっていればOKです!
リッチテキストエディタ… どこ?を解決する
実を言うと、この画面は本来以下のような表示になります。
では何故今こんなにも醜い表示になっているのでしょう…?
類似の条件を漁ってみると、以下のissueで似たような挙動を起こしている方を発見しました。
どうやらAction Text
とWebpacker
はあまり相性が良くない(?)らしく、今回のようにWebpackerでCSS類を管理している場合に、競合してリッチテキストエディタの表示が崩れるという現象が起きるみたいです。
ちなみにTailwind CSS
を採用した場合にも起きる模様…。ヒデエな(笑)
解決方法
同issue内で解決方法を提示している神がいました。
まず app/views/layouts/application.html.erb
の<head>
内に以下の1行を追加します。
<%= stylesheet_link_tag "actiontext", "data-turbo-track": "reload" %>
次に app/assets/config/manifest.js
に以下の1行を追加します。
//= link actiontext.css
それぞれ記述を追加した完成版は以下になります!
<!DOCTYPE html>
<html>
<head>
<title>TestApp</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "actiontext", "data-turbo-track": "reload" %>
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link actiontext.css
上記修正した所、以下のように画面が正しく表示されるようになりました!
参考
おわりに
いかがでしたでしょうか。
今回はAction Text
とBootstrap
があまりにも相性が悪すぎる問題と、その解決方法についてご紹介しました。
Action Text
は色々な箇所で使い道がありそうですので、今回の内容を元に更なるカスタマイズを施してみるのも良いかもしれませんね!
さて今年のAdvent Calendarもラスト1日になりました…
ラストはお馴染みGitHubのREADMEをアレンジしてみた!をまとめます!お楽しみに!