83
0
0
私の Rails アプリケーション開発環境
私の Rails アプケーション開発環境
東京Emacs勉強会 オクトーバーフェスティバル2024 (2024/10/27 13:00〜)
# EmacsJP オクトーバーフェスティバル 2024 ## ポジションペーパー 東京Emacs勉強会では短い時間で最大限に交流するため、参加者の自己紹介に「ポジションペーパー」を利用しています。 イベント開始前に記入しておいてください。 ※ 共有される前提の資料なので、公開されて困る個人情報は書かないでください ## トーク 東京Emacs勉強会では参加者による発表を歓迎しています。目安は15分前後ですが、長くても短くても構いません。(30分程度話しても構いません) * 使ってみて便利だった機能/パッケージの紹介 * 自分で作っているパッケージや取り組みの紹介 ...
tokyo-emacs.connpass.com/event/330572
自己紹介
- Twitter(現X): @mugijiru
- GitHub: @mugijiru
- 所属企業: ビットジャーニー
- 好きな Emacs 拡張: major-mode-hydra
少し宣伝
お仕事
- ビットジャーニーという会社で 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分割で利用しています。
メジャーモード
- enh-ruby-mode を利用しています
- ちょっと古いパッケージだけどインデントの取り扱いが一番自分に合っている
- Ruby の Ripper クラスを使って処理をしているのでいい感じにできるらしい
ruby-ts-mode | enh-ruby-mode |
---|---|
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-c
でrspec-verify-single
が動くようにしています - 他は覚えられないので major-mode-hydra を使って Hydra を定義しています
-
major-mode-hydra
はM-x major-mode-hydra
でmajor-mode
に応じた Hydra を定義/起動できるので便利
-
複数バージョンの Ruby の切り替え
- 時々違うバージョンの Ruby を使うこともあるので rbenv.el を使ってます
-
M-x rbenv-use
とかで Emacs から呼び出すバージョンを切り替えられるので便利 - 今時だと chruby.el や asdf.el を使うかもしれないけど未検証
- asdf.el は今後試したい
プロジェクト操作
projectile-rails
- projectile の Rails 向け拡張機能
-
M-x projectile-rails-find-model
で Model ファイルを find できたりして便利 - ただし Rails 標準ではないファイルの検索コマンドは提供されてない
-
rails console
やrails 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 を使っています- ちなみに hydra の定義には pretty-hydra というのを使っています
projectile
- Rails 限定じゃない操作に利用しています。プロジェクト内の検索とか
- 大体 counsel-projectileの機能を使っています。
- これもキーバインドを覚えられないので Hydra を定義しています
- よく使うのは
find-file
,recentf
,ripgrep
,switch project
かな
- よく使うのは
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_GEMFILE
をbuffer-local
にして指定している程度ですが
-
- 今は
ruby-ts-mode
だと Solargraph が動くようにして動作比較しています
Gemfile.local の中身
- シンプルに
solargraph
とsolagraph-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 |
---|---|
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))
キーバインド
- やはり覚えられないので Hydra を自前で定義している
- Keybindings - LSP Mode - LSP support for Emacsの内容は網羅してないけど十分かな
補完
-
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))
リファレンス検索
- engine-mode を使ってるりまサーチや APIDockを検索できるようにしています
- 基本的には emacs-w3m で検索結果を見られるようにしています。
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)))))
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年ぐらい前にうまく動かせなかったのでそれから苦手意識がある
最後に
- 以上が私の今の Rails アプリ開発環境です。
- 「今時ならこれも良いぞ!」みたいな情報があれば教えてもらえると嬉しいです 🙏
- ちなみに
.dir-locals.el
以外の設定は大体 https://mugijiru.github.io/.emacs.d/ で公開しているので気になる方はそちらも是非