Lum’s

勉強中の技術をまとめるブログ。たまに趣味も。

Railsエンジンを使ってシンプルなアプリケーションをマウントしてみた

なかなか保育業務支援アプリケーション制作の具体的な内容に入れないが、自主学習のため今日はRailsエンジンについて自分なりに学んでみる。

Railsエンジンとは?

少し古いけど、Railsエンジンとは?ということで以下の記事がわかりやすかった。

d.hatena.ne.jp

自分なりの解釈でいくと、2つのRailsアプリケーションがあった場合や、1個のRailsアプリケーションが肥大化していった時などに、その片方やもしくは1個のアプリケーション内の機能をエンジンを使って1つにまとめる(親子の関係にする)ことができるというもの。

gemなどのプラグインとは異なり、エンジンが独自のrouteやlocaleを持つことができたり、親アプリケーションのhelperなどもエンジンから呼出せたりするそう。 上記を読んでいて思ったのは、例えば管理画面が2種類あるようなアプリケーションの場合。

今職場で開発しているアプリケーションってほぼ同じ機能だけどみるDBを分けるために同じものを複製するような形で作った記憶があって、それってメンテナンス性からいうと結構微妙な気がする。そういう時にエンジンとして分けておいて、一ついじるだけで済むようにすればいい感じにいけるんじゃないかな、とちょっと思った。 (違うかもしれない。)

実際にやってみた

まあとにもかくにも、実際に触ってみてなんぼだなと思うので

qiita.com

上記のサイトを見ながらRailsエンジンに触れていく。

$ rails new kinoko_engine

まずは適当なrailsアプリケーションを作成する。 そして

$./bin/rails plugin new board_engine --mountable -T --dummy-path=spec/dummy_app

を実行すると、appフォルダと同階層にboard_engineフォルダが生成される。 そして、board_engine.gemspecを開いてみると、

$:.push File.expand_path("../lib", __FILE__)

# Maintain your gem's version:
require "board_engine/version"

# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
  s.name        = "board_engine"
  s.version     = BlogEngine::VERSION
  s.authors     = ["username"]
  s.email       = ["email"]
  s.homepage    = "TODO"
  s.summary     = "TODO: Summary of BoardEngine."
  s.description = "TODO: Description of BoardEngine."
  s.license     = "MIT"

  s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]

  s.add_dependency "rails", "~> 5.1.6"

  s.add_development_dependency "sqlite3"
end

おお、確かにできている・・! 上記のうち、[TO DO]と[username],[email]となっているところを任意の設定に変えてboard_engine直下で

$ bundle install

そして1番大事な親アプリケーションへ読み込ませる作業としてkinoko_engineのGemfileに

gem 'board_engine', path: 'board_engine'

を記載し、bundle installを実行。 そして親アプリケーションのrouteファイルへ

mount BoardEngine::Engine, at: '/board'

と記載し、マウント完了。ここで表示用のURLが設定できるので、 localhost:300x/boardが今回の確認用のURLとなる。 そして残るエンジン側のroute設定と表示確認のため、

$ cd board_engine

$ bundle exec rails g scaffold articles title body:text

にて一括で作成。 scaffoldをするとmigrationファイルも生成されるので、

$ cd ../

$ rake board_engine:install:migrations

にて親アプリケーションへコピー。(これでコピーできるの知らなかった)

そしてあとは親アプリケーションにてdb:migrateを実行し、/board/ariticleに遷移すると表示が確認できた!!

やってみて

とりあえず勉強用なので一旦ここまで。たしかに意外と読み込ませるまでは難しくなかった。 rails/info/routesでみてみると、

new_article_path GET /articles/new(.:format) blog_engine/articles#new

とか生成されててちょっと感動する。 調べてみると今回はgemで親アプリケーションへ読み込ませたが、gitからソースを読み込んで来る方が一般的らしい。

あとは詳細は

railsguides.jp

やっぱりこの辺を読んで勉強してみようと思う。 (これぐらい最初にやっておくとガイドもすんなり読めそうな気がする・・!)

※補足

ガイドを読んでみて、あーそうだったのか!というところが多かったので自分の学習のため追記。

  • --mountableオプション

    マウント可能かつ名前空間で分離されたエンジンを生成する場合に使用します。

→だから、scaffoldした時にblog_engine/articles#newという形で名前付きルートが設定されていたのかな。ちなみにappディレクトリツリーなんかもこの時生成される。 (多分、lib/blog_engine/engine.rbのisolate_namespaceメソッドが設定されるのではないだろうか)

デフォルトで名前空間が作られるあたり、やはり親アプリケーションとの親子関係が大前提なんだろうなぁと思う。

  • lib/blorgh/engine.rb

→config/application.rb と同等の役割をする。

  • isolate_namespaceメソッド

    エンジンのコントローラ/モデル/ルーティングなどが持つ固有の名前空間を、アプリケーション内部のコンポーネントが持つ類似の名前空間から分離する役目を担います。

→ようは名前衝突を避けるためということ。

ちょっとこれは本筋とはずれるけど、モデルのテーブルが名前空間化すると

モデルのテーブルも名前空間化され、単なるarticlesではなくblorgh_articlesになります。

ということらしい。