83
0
0

私の Rails アプリケーション開発環境

Published at October 20, 2024 5:00 p.m.
Edited at October 27, 2024 2:53 p.m.

私の Rails アプケーション開発環境

東京Emacs勉強会 オクトーバーフェスティバル2024 (2024/10/27 13:00〜)
# EmacsJP オクトーバーフェスティバル 2024 ## ポジションペーパー 東京Emacs勉強会では短い時間で最大限に交流するため、参加者の自己紹介に「ポジションペーパー」を利用しています。 イベント開始前に記入しておいてください。 ※ 共有される前提の資料なので、公開されて困る個人情報は書かないでください ## トーク 東京Emacs勉強会では参加者による発表を歓迎しています。目安は15分前後ですが、長くても短くても構いません。(30分程度話しても構いません) * 使ってみて便利だった機能/パッケージの紹介 * 自分で作っているパッケージや取り組みの紹介 ...
tokyo-emacs.connpass.com/event/330572

自己紹介

少し宣伝

お仕事

  • ビットジャーニーという会社で Kibela というサービスを作っています
Kibela キベラ|自律的な組織になるナレッジ共有ツール
Kibela(キベラ)は、中小企業から大企業まで、業界や職種、ITリテラシーを問わず、誰にでも簡単に活用できる持続可能なナレッジ共有サービスです。業務効率化によりチームが自律化することで、情報資産の価値が高まり、ビジネスに還元。テレワーク、在宅勤務など場所や時間も問わず、情報を蓄積して活用するサイクルを実現します。
kibe.la

プライベート

  • プライベートでは ivy-kibela, emacs-kibela というのを作っています
    • Emacs から Kibela に記事を書きたいので作りました
    • 面倒なので melpa とかには登録していません。GitHub から直接どうぞ
    • とはいえ、たまにしか更新していませんが

今日の話

  • 今日は Rails アプリケーションの開発の際に
    Emacs を使ってどんな感じで開発しているかを話します
  • フロントエンド(React)も書いてるけどその話は時間が足らないので割愛します
  • Docker も使っているので一部 Docker 連携の話もします

利用環境

  • Manjaro Linux
  • Emacs 29.4

開発スタイル

  • ディスプレイの左側に Emacs, 右側にブラウザを表示するスタイルを取ってます
  • 表示が縦長になるので IDE っぽい感じには使っていません。
  • 基本的には上下2分割で利用しています。

image

メジャーモード

  • enh-ruby-mode を利用しています
  • ちょっと古いパッケージだけどインデントの取り扱いが一番自分に合っている
    • Ruby の Ripper クラスを使って処理をしているのでいい感じにできるらしい
ruby-ts-mode enh-ruby-mode
image image

enh-ruby-mode の設定

  • 以下の設定だけ入れています
    • エンコード指定のマジックコメントを自動挿入しない
    • インデント周りの調整
emacs-lisp
(setopt enh-ruby-add-encoding-comment-on-save nil)
(setopt enh-ruby-deep-indent-paren nil)
(setopt enh-ruby-deep-indent-construct nil)
(setopt enh-ruby-bounce-deep-indent nil)

テスト

  • RSpec を使っているので rspec-mode を利用しています。

グローバル設定

  • デバッグ実行ができるように inf-ruby と接続できるようにしている
    • デバッガで止まった時は C-x C-q で inf-ruby に
  • C-c C-c でカーソル下の spec を実行できるようにしている
emacs-lisp
(add-hook 'after-init-hook 'inf-ruby-switch-setup)
(define-key rspec-mode-map (kbd "C-c C-c") 'rspec-verify-single)

プロジェクト用の設定

  • Docker 内で実行されるように指定しています
emacs-lisp
((enh-ruby-mode
  .
  ((rspec-use-docker-when-possible . t)
   (rspec-spec-command . "bin/rspec")
   (rspec-docker-container . "kibela-app")
   (rspec-docker-command . "docker exec -it"))))

enh-ruby-mode のキーバインド

  • 上記の通り C-c C-crspec-verify-single が動くようにしています
  • 他は覚えられないので major-mode-hydra を使って Hydra を定義しています
    • major-mode-hydraM-x major-mode-hydramajor-mode に応じた Hydra を定義/起動できるので便利

image

複数バージョンの Ruby の切り替え

  • 時々違うバージョンの Ruby を使うこともあるので rbenv.el を使ってます
  • M-x rbenv-use とかで Emacs から呼び出すバージョンを切り替えられるので便利
  • 今時だと chruby.elasdf.el を使うかもしれないけど未検証
    • asdf.el は今後試したい

プロジェクト操作

projectile-rails

  • projectile の Rails 向け拡張機能
  • M-x projectile-rails-find-model で Model ファイルを find できたりして便利
  • ただし Rails 標準ではないファイルの検索コマンドは提供されてない
  • rails consolerails dbconsole なども動かせる

Docker 連携

  • rails console などは Docker の中で動かしたい
  • というわけで .dir-locals.el に以下のような設定を入れています
    • アプリ固有の事情なのでグルーバルな設定にはしていません
    • Rake コマンドは rake.el を弄らないといけないので Docker 内で動かせてません 😢
emacs-lisp
((enh-ruby-mode
  .
  ((projectile-rails-custom-console-command . "docker compose exec app rails console")
   (projectile-rails-custom-dbconsole-command . "docker compose exec app rails dbconsole")
   (projectile-rails-custom-generate-command . "docker compose exec app rails generate"))))

キーバインド

  • パッケージから提供されるキーバインドを覚えるのはしんどい
  • 自作コマンドのキーバインドも入れ込みたい
  • というわけで projectile-rails 用に Hydra を使っています

image

projectile

  • Rails 限定じゃない操作に利用しています。プロジェクト内の検索とか
  • 大体 counsel-projectileの機能を使っています。
  • これもキーバインドを覚えられないので Hydra を定義しています
    • よく使うのは find-file, recentf, ripgrep, switch project かな

image

LSP

  • lsp-mode を使っています
    • Eglot も興味あるけど乗り換えが面倒でそのまま
  • LSP サーバは今は ruby-lsp を試しています。良い感じなので定着しそう

ruby-lsp を使う設定

  • このあたりはプロジェクト毎の設定なので .dir-locals.el で設定しています
emacs-lisp
((enh-ruby-mode
  .
  ((lsp-enabled-clients . (ruby-lsp-ls))
   (eval . (progn
             (add-hook 'before-save-hook #'lsp-format-buffer nil 'local)
             (lsp)
             (lsp-ui-mode 1))))))
  • Solargraph や rubocop-lsp の方が優先度が高いので有効な LSP クライアントを指定
  • 保存時に自動的に整形して欲しいので before-save-hook で自動整形をさせる
  • という設定を反映した上で lsp & lsp-ui を起動

その他 LSP 関係の設定

Solargraph の設定

  • まだ ruby-lsp と動作の比較をしているので Solargraph の設定も残しています
emacs-lisp
 (ruby-ts-mode . ((lsp-solargraph-use-bundler . t)
                  (eval . (progn
                            (add-hook 'before-save-hook #'lsp-format-buffer nil 'local)
                            (setq-local process-environment
                                        (copy-sequence process-environment))
                            (setenv "BUNDLE_GEMFILE" "Gemfile.local")
                            (lsp)
                            (lsp-ui-mode 1)))))
  • こちらは自動的に Gemfile を用意したりしないので自前で対応しています
    • BUNDLE_GEMFILEbuffer-local にして指定している程度ですが
  • 今は ruby-ts-mode だと Solargraph が動くようにして動作比較しています

Gemfile.local の中身

  • シンプルに solargraphsolagraph-rails を入れてます
  • solargraph-rspec も入れても良いかも
ruby
eval_gemfile "Gemfile"

gem "solargraph"
gem "solargraph-rails"

lsp-mode & lsp-ui の設定

  • コードチェックのバックエンドに flycheck を指定
  • カーソルを載せると lsp-ui-doc を表示
  • lsp-ui-doc の表示位置基準を window に変更
    • デフォルトの frame だと左右に画面分割した時の表示位置が遠くなるので
emacs-lisp
(setopt lsp-diagnostics-provider :flycheck)
(setopt lsp-ui-doc-show-with-cursor t)
(setopt lsp-ui-doc-alignment 'window)
flame window
image image

lsp-ui-sideline 用のパッチ

  • lsp-ui-sideline の表示位置調整のパッチを当ててます
  • text-scale-increase とかしているとズレるのでその対応
emacs-lisp
(with-eval-after-load 'lsp-ui-sideline
  (defun lsp-ui-sideline--align (&rest lengths)
    "Align sideline string by LENGTHS from the right of the window."
    (cons (+ (apply '+ lengths)
             (if (display-graphic-p) 1 2))
          'width))
  (defun lsp-ui-sideline--compute-height () nil))

キーバインド

image

補完

  • company-mode を使っています
    • corfu とかは組み合わせるパッケージが多くて面倒なので見てません 🙈
  • copilot.el も使っています。
    • あんまり設定はしていない

company-mode の Ruby 用設定

  • enh-ruby-mode-hook で backends を指定しています。
    • デフォルトのままだと company-bbdb とか company-clang とか関係なさそうなのが入って来るので
  • company-capf は LSP Mode と連携する backend なので必須かな
emacs-lisp
(setq-local company-backends
              '(company-capf (company-keywords company-dabbrev-code) company-yasnippet company-files company-dabbrev))

リファレンス検索

emacs-lisp
(setopt engine/browser-function 'w3m-browse-url)

るりまサーチの検索

engine-mode の定義はこんな感じ

emacs-lisp
(defengine rurema-3.3
  "https://rurema.clear-code.com/version:3.3/query:%s/")

emacs-w3m で見るとページ上部の表示が邪魔なので一部要素を削除

emacs-lisp
(defun w3m-filter-rurema (url)
  (goto-char (point-min))
  (let ((deletions '(("<div class=\"description\">" . "</div>")
                     ("<div class=\"version-select\">" . "</div>")
                     ("<div class=\"topic-path\">" . "</div>")
                     ("<div class=\"drilldown list-box\">" . "</div>"))))
    (dolist (deletion deletions)
      (let ((begin-regex (car deletion))
            (end-regex (cdr deletion)))
        (w3m-filter-delete-regions url begin-regex end-regex)))))

image

Rails API の検索

こちらは APIDock を参照しています

emacs-lisp
(defengine rails
  "https://apidock.com/rails/search?query=%s")

RSpec API の検索

こちらも APIDock を参照しています

emacs-lisp
(defengine rspec
  "https://apidock.com/rspec/search?query=%s")

その他

  • inf-ruby :: rspec-mode や projectile-rails の依存関係で入って来る irb/pry を動かすやつ
  • yard-mode :: YARD コメントのハイライトとかをしてくれる
  • bundler.el :: Gemfile のソース見たい時に bundler-open が便利
  • dumb-jump :: lsp-mode で飛んで来れないシンボル間ジャンプに利用
  • etc...

使ってないけど気になるもの

  • ruby-refactor :: メソッド切り出しとかが手軽にできるやつ
  • ruby-tools :: '" に変更したりが簡単になるやつ
  • robe :: ドキュメント見たりするのに便利っぽい
    • けど10年ぐらい前にうまく動かせなかったのでそれから苦手意識がある :trollface:

最後に

  • 以上が私の今の Rails アプリ開発環境です。
  • 「今時ならこれも良いぞ!」みたいな情報があれば教えてもらえると嬉しいです 🙏
  • ちなみに .dir-locals.el 以外の設定は大体 https://mugijiru.github.io/.emacs.d/ で公開しているので気になる方はそちらも是非