サーバー側のエクスポートとエディター(クライアント)の表示を揃えたい
RubyとRailsを使ってみたかったのと、カレンダー印刷系のウェブアプリが個人的に欲しかったので現在取り組んでいます。
用意すべきパラメータが多いことを把握してER図等予め組んでいたのですが、作っている途中で足りないことに気づきあたふた中です。
Ruby(on Rails)使ってみた
言語としても使うのは初めてでしたが、一言で書きやすくて楽しいです♪
プロジェクト内のappやcontrollers、testフォルダなどが予め配置されており、決まった命名規則で対応付けがなされていくのですよね
外部データの取得などをコントローラー側で書いて、html.erbで渡す形が基本なのかなと感じています。
あと、modelsで必要なデータの保存と読み出し。
(ちなみにファイル名のルールが多くて困ってます ← Next.jsもいうてでは)
viewsに今回はindex.html.erbを配置していますが、React+TypeScriptを導入していつも通りに状態管理やコンポーネント設計できるように整えました。
↓ 作りかけのリポジトリ
LINKGitHub - isirmt/rail...Contribute to i...https://github.com/isirmt/rails_cale...
カレンダーの表示法
編集中は勿論インタラクティブなアプリケーションを目指しているので、サーバー側からの表示をそのまま使うのは違う状態ですが、出力はどのデバイス・クライアントからも同じものが返ってきてほしいのでサーバー側で処理して返します。
ただ、クライアントもCSSを自分でできるだけ制御すれば差異は埋まるはずなんです。
共通のCSSファイルを使おう!
実装
ルーティング
config/routes.rbにて、エディターのページは
get "calendars/:id/editor", to: "home#editor", as: :calendar_editor⇒ /calendars/:id/editor
にしました。また、PDFをレスポンスするエンドポイントは、
namespace :api do
resources :calendars do
member do
get :pdf
end
end
end⇒ /api/calendars/:id/pdf
でいきます。
React側はhomeコントローラーに渡すようにして、
class HomeController < ApplicationController
def index
@page = "home"
@calendar_id = nil
end
def editor
@page = "editor"
@calendar_id = params[:id]
render :index
end
end<div id="root" data-page="<%= @page || "home" %>" data-calendar-id="<%= @calendar_id %>"></div>createRoot(el).render(<App page={pageData} calendarId={calendarId} />);function App({ page, calendarId }: AppProps) {
if (page === "editor") {
return <EditorPage calendarId={calendarId} onBackHome={() => window.location.assign("/")} />;
}
return <HomePage onGoEditor={(nextCalendarId) => window.location.assign(`/calendars/${nextCalendarId}/editor`)} />;
}でエディターとトップページを振り分けるようにしました。(今回はページが少ないけど、増えた場合は考えるべきかも)
共通CSSの作成
app/assets/stylesheets/配下にCSSを配置します。
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap");
@page {
size: A4 landscape;
margin: 0;
}
.calendar-pdf-root,
.calendar-pdf-root * {
box-sizing: border-box;
font-family: "Noto Sans JP", sans-serif;
}
.calendar-pdf-canvas {
width: 297mm;
min-height: 210mm;
padding: 10mm;
background: #fff;
border: 1px solid #d4d4d8;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.14);
}
.pdf-render .calendar-pdf-canvas {
border: 0;
box-shadow: none;
}React側は影を付けておき、render側は無しという形に分けています。また、フォントはNoto Sans JPで統一しました。
React側の読み込み
まず、application.html.erbの<head>内でcssファイルの読み込み記述を追加します。
<%= stylesheet_link_tag "calendar_pdf", "data-turbo-track": "reload" %>PDF出力側の読み込み
アプリケーション側のCSSなどが無闇に反映されないように、独立したrenderが必要となります。
app/controllers/api/calendars_controller.rbのpdfアクション内で次のように書きました。
html = ApplicationController.render(
template: "api/calendars/pdf",
layout: false,
# 略
)LINKLayouts and Renderin...This guide cove...https://guides.rubyonrails.org/layou...
そして、app/views/api/calendars/pdf.html.erbにて、直接ファイルを展開すれば、なるべく自己完結した構成が実現できます。
<style>
<%= Rails.root.join("app/assets/stylesheets/calendar_pdf.css").read.html_safe %>
</style>枠線やタイトルは無事配置できましたが、日付の外に書く要素などのロジックは決定していないので、しっかり考えていこうかと思います。