MarkdownをPDFにする

PandocでMarkdownをPDF化しようとすると、テーブルのレイアウトが崩れやすく、調整に高度なTeXの知識を求められるのが難点でした。 代わりに md-to-pdf を試したところ、設定も簡単で綺麗に仕上がりました。

% npm i -g md-to-pdf
% npx md-to-pdf "hoge.md" --pdf-options '{"format": "A4", "margin": {"top": "20mm", "bottom": "20mm", "left": "20mm", "right": "20mm"}}';

Omeka S の全文検索で1〜2文字の語がヒットしない問題と対処法

Omeka S の管理画面左サイドバーで検索を行うと、1〜2文字の語では検索にヒットしないことがあります。 これは、MySQL の MATCH ... AGAINST を用いたフルテキスト検索では、短い語(1〜2文字)が検索対象にならないことが多いためです。

日本語のように単語の区切りが明確でない言語を検索対象とする場合は、ngramパーサを使った全文検索に切り替えることで、この問題を解決できます。

ngramパーサを使う設定手順

まず、既存の全文検索インデックスを削除し、WITH PARSER ngram を指定して作り直します。

DROP INDEX `IDX_AA31FE4A2B36786B3B8BA7C7` ON `fulltext_search`;
ALTER TABLE `fulltext_search`
  ADD FULLTEXT `IDX_AA31FE4A2B36786B3B8BA7C7` (`title`, `text`) WITH PARSER ngram;

このSQLを実行することで、Omeka S が使用する全文検索用のインデックスが ngram 対応になります。

ngram の最小文字数を確認・変更する

次に、現在の ngram の最小トークンサイズを確認します。

SHOW VARIABLES LIKE 'ngram_token_size';

私の環境では 2 になっていたため、2文字以上の単語で検索ヒットする状態でした。

もし 1文字でも検索ヒットさせたい場合は、MySQL の設定ファイル(my.cnf)に以下を追加します:

ngram_token_size=1

その後、MySQL を再起動し、FULLTEXT インデックスを WITH PARSER ngram で再作成することで、設定変更が反映されます。

作業ログからの工数推定(git logと生成AI)

やったこと

  • Gitログをもとに、プログラミング作業に要した時間を日別に推定しました。
  • 一部の作業には AI(ChatGPT)による支援を活用しています。

git logの取得

以下のコマンドで、コミットの日時と修正行数を含むログを取得しました。

git log --pretty=format:"%H %ad" --date=iso --shortstat > git_log_stats.txt

この中から対象日以外のログを削除し、例えば次のような形式になっています:

fc6b0bf0080c5596e54070945f9765b097c2f18d 2025-06-06 00:31:33 +0900
 2 files changed, 13 insertions(+), 8 deletions(-)

0d6a8a99265d4e3cafdea85a6980beafc4b9f504 2025-06-06 00:11:45 +0900
 1 file changed, 8 insertions(+), 1 deletion(-)
...

作業時間の推定方法

ChatGPT に対して、取得した git_log_stats.txt を入力し、以下のプロンプトを使用して作業時間を算出しました。

- RailsやVue.jsを利用して新規の機能を実装しました。
- git logの結果から日毎の工数を算出して、Markdown形式にしてください。
- 合計時間も表示してください。

日別の工数推定結果

日付 推定工数 (時間)
2025-05-20 2.6
2025-06-03 5.2
2025-06-04 1.0
2025-06-05 4.4
2025-06-06 2.8
2025-06-07 5.9
合計 21.9

行数に基づく工数の目安

推定工数は以下の基準に基づいています。

変更行数(追加 + 削除) 工数(目安) 備考
1–20 行 0.2 時間 軽微な修正:変数名変更、コメント追加、1ファイル内で完結
21–50 行 0.5 時間 中程度の修正:バグ修正、簡単なUI改修など
51–150 行 1.0 時間 1画面のVueコンポーネント更新や、Railsコントローラ+ビューのセット更新など
151–300 行 2.0 時間 複数ファイルにまたがる画面改修、API追加など
301 行以上 3.0 時間 or 日単位 新機能追加、ページ追加、重いデータ結合、DB変更込みなど

所感

精度に確信があるわけではないものの、作業の見える化の手段として有用であり、今後も参考にしていきたい。

LightsailのオブジェクトストレージはCORS設定が出来ない

Railsのダイレクトアップロード機能を使用する場合には、Rails Guideにに記載されている通り、CORS(Cross-Origin Resource Sharing)の設定が必要です。

しかしながら、LightsailのオブジェクトストレージはCORS設定が出来ないので注意です。

エラー概要

Lightsailのオブジェクトストレージ( https://<bucket-name>.s3.ap-northeast-1.amazonaws.com )に対してダイレクトアップロードした際に次のようなエラーが出ていた。

LightsailのオブジェクトストレージにCORS設定を試みる

  • Lightsailの管理画面からは該当項目なし。
  • aws-cliから下記のようなコマンドを実行したが、権限がないと言われる。AMIを見てもそのような権限がない
aws s3api put-bucket-cors --bucket <bucket-name> --cors-configuration file://cors.json

An error occurred (AccessDenied) when calling the PutBucketCors operation: User: arn:aws:sts::XXXXXXXXX:assumed-role/<bucket-name>.obj-mgmt/i-xxxxxxx is not authorized to perform: s3:PutBucketCORS on resource: "arn:aws:s3:::<bucket-name>" because no identity-based policy allows the s3:PutBucketCORS action
  • s3にLightsailのbucketが表示されていない

StackOverflowでも対応していないからs3使えとの回答。

stackoverflow.com

ということで、Lightsailのオブジェクトストレージはシンプルで安価で使いやすいのですが、ダイレクトアップロード機能は利用できないので注意してください!

RailsとVuejsでファイルアップロードする(ActiveStorageのダイレクトアップロード機能)

RailsとVuejsの組み合わせでファイルアップロードをどうやってやればいいか悩んでいたが、ActiveStorageのダイレクトアップロード機能が簡単に使えたのでメモしておく。

class Foobar < ApplicationRecord
  has_one_attached :report_file
end

rails側のモデルは上記のとおりとする。

<template>
  <div>
      <b-field label="ファイルアップロード">
        <input
          type="file"
          @change="handleFileUpload"
          ref="fileInput"
        />
      </b-field>
  </div>
</template>

<script>
// Active Storageのdirect upload機能をインポート
import { DirectUpload } from '@rails/activestorage'

export default {
  data() {
    return {
      report_file: null,
    };
  },
  methods: {
    // ファイルが選択された時に呼び出される
    handleFileUpload(event) {
      const files = event.target.files;
      if (files.length > 0) {
        Array.from(files).forEach(file => this.uploadFile(file));
      }
    },

    // ファイルアップロードの処理
    uploadFile(file) {
      const upload = new DirectUpload(file, '/rails/active_storage/direct_uploads');

      upload.create((error, blob) => {
        if (error) {
          console.error('File upload failed:', error);
          alert('ファイルのアップロードに失敗しました');
        } else {
          console.log('File uploaded successfully:', blob);
          // この値をControllerへ送ってあげればOK
     this.report_file = blob.signed_id;
        }
      });
    }
  }
};
</script>

Active Storageのdirect upload機能を使うのがポイント。 アップロードすると、ハッシュ値(署名)が返ってくるので、モデルとの紐づけるために別途保存が必要になります。

出張の際の必需ガジェット

たまに出張する際に、必要なものを忘れがちなのでメモしておきます。私はMacBook Airを使用しています。

USB-Cの変換アダプタ

MacBookを使っていると、出張先でプロジェクターなどに接続するためにHDMIが必要になることが多いです。そのため、常にガジェットポーチにUSB-CからHDMIに変換できるアダプタを入れておくと便利です。MacBookはとても使いやすいですが、インターフェースの少なさは本当に頂けません。

充電用ACアダプター

ACアダプターは、大は小を兼ねるといいますが、大きいものは高価になりがちです。そのため、60W程度のPD対応のものがおすすめです。これならスマホだけでなく、MacBook Proの充電も可能です。ケーブルもPD対応のType-Cのものを準備しておくと良いでしょう。

私はDigiforce社製のものを愛用しています。値段も安価でデザインも良いのでオススメです。

なお、数多くのUSB-C充電器を見てきた方は、次のようにも言及しています。

これまで数多くの USB-C 充電器を見てきた筆者としては、Belkin、Satechi、エレコムの3社をオススメします。 これらのメーカーにも非の打ちどころはあり、常に完璧な製品やサポートなのかと言われると、そうではありません。しかし、平均的に70点以上の製品を出し続けており、製品品質は高いところで安定している印象です。

xn--p9j1ayd.net

私はあまりこの分野は詳しくないのですが、予算のある方は上記メーカーも検討してみてください。

イヤフォン

Web会議用には、ずっとこのイヤフォンを愛用しています。入手しやすく、価格も手頃でありながら、品質も高いためです。ワイヤレスイヤフォンだと充電切れの心配や接続の問題があるので、私はまだ有線イヤフォンを使い続けたいと思っています。これまでは3.5mmのヘッドフォンプラグを使っていましたが、そろそろUSB-C対応のものを検討しても良いかもしれません。

3coinsのガジェットポーチ

300円という手頃な価格ながら、質感が高く、サイズ感も絶妙です。普段使いにぴったりで、ガジェット収納以外にも利用できるので、とてもおすすめです。

www.palcloset.jp

湿布

旅先だと歩くことが多いので、湿布を持っていくと良い。

海外旅行で持って行って良かったもの

空港・飛行機編

のどぬーる ぬれマスク

飛行機の中は乾燥するため、このマスクがあると快適に過ごせるし、喉を乾燥させると体調を崩す原因なので必須。

空気で入れるタイプのネックピロー

飛行機の中で快適に寝るために必須のネックピロー。空気で膨らませるタイプとクッションタイプがあるが、使わないときにコンパクトになる空気で膨らませるタイプ一択。私が使っているのは、アウトドアブランドのSEA TO SUMMITのもの。軽いし、小さくなるし、質感も高いのでオススメ。夜行バスや新幹線などでも利用できるため、意外に利用範囲も広い。

使い捨てのスリッパ

飛行機の中は足が浮腫むし、スニーカーといえどもずっと履いているのは辛いので、使い捨てのスリッパがあるとお手洗いに行くのも楽。100均のものを利用。お気に入りのビーサンでも良いかも。

Type-Aの充電ケーブル

高速充電するならType-C一択だが、飛行機の中やラウンジだとType-Aが残っている場合が多いのでケーブルは持っていくべき。

現地編

Visaタッチの可能なクレカ

ヨーロッパだとVISAタッチさえあれば両替は不要なくらい。

パタゴニアのバギーズ ショーツ

パタゴニアのド定番商品。

  • 水陸両用のため、サウナにビーチに水着代わりに利用できる
  • ポケットに詰めて収納できるパッカブル仕様
  • 丈夫で履きやすいので、暑い国ならこれだけで良いかも

湿布

歩くと脚が痛くなるのでリカバリー用のグッズは必須。

カトラリー

サラダとかカップ麺とか購入してもカトラリーが無く、現地で購入したことがあるので、キャンプ用のものを持っていくと良い。

変換プラグ

スマホの充電に必須。

こういうタイプのものを購入したいところ。 性能がいいものを購入したいがたまにしか行かない海外旅行だと2000円くらいが出せる値段の上限か…。

このタイプは組み立てがだるいので買わないこと。

不要なもの

チケットの入る大きいパスポートケース

こういう飛行機のチケットが入るサイズのパスポートケースはもう要らない。 今はチケットがQRコードになったので、チケットは折り畳めるし、スマホで事足りるので小さいパスポートケースで問題ない。