特にRailtie、Engine(full/mountable)あたりの区分けについて、日本語の情報があまり見当たらなかったためメモします。
TL;DR
- 汎用的なRubyスクリプトをGem化したい時は
bundle gem <gem_name>
。 - Railsのレールに乗ってプラグインを作りたい時はEngine(こちらもGemとして配布可能)。
- Railtieの仕組み自体はRails全体に通ずるため理解しておきたい。
- Full EngineとMountable Engineの違いはホストアプリケーションとの結合度。
Gem
RubyGems経由で公開されているRuby製のライブラリ全般。
よってRailtieプラグインやEngineもGemの中に含まれる。
最もシンプルに(Railsの文脈に囚われずに)作っていきたい場合は以下コマンドで作成。
生成コマンド
bundle gem <gem_name> -t
※-t
でspecファイルを一緒に生成してくれます。
もう少し詳しく
はじめてのgem作成
http://shiro-16.hatenablog.com/entry/2014/03/12/001402
君がOpsでもRubyで書いたライブラリはGemで配ろう
http://qiita.com/sawanoboly/items/ede7715c605e5822ad22
bundlerを使ってRSpecを書きつつGemを開発する
http://qiita.com/kakkunpakkun/items/4271973425e151afbd1a
Railtieプラグイン
そもそもRailtieとは
Rails公式のプラグイン機構で、RailsのあらゆるコンポーネントはRailtieの機能を保有している。
Railtieに基づいたプラグインを部品として組み合わせていくことで、Railsの初期化処理(イニシャライザ)やジェネレータ(rails generate ~
)、Rakeタスク、設定項目(config)等々コアな部分を手軽に拡張していくことが出来る。
その本体は
module MyPlugin
class Railtie < Rails::Railtie
# config.my_plugin = ...
# initializer "my_lugin.set_configs" ...
end
end
であり、コメントのようにconfigやinitiaizerを追加の上でRailsアプリケーションから読み込むことで、Railsの一部となり拡張が実現される。
ちなみに、Action Mailer, Action Controller, Action View, Active RecordなどももちろんRailtieの機構を用いているが、それはあらゆるRailsアプリケーションのconfig/application.rbを見れば明らかになる。
# Pick the frameworks you want:
require "active_model/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
RailtieこそがRailsの世界を司る
※ パーフェクトRuby on Rails引用の、Railtie/Engine/Applicationの関係を示した疑似コード。
module Rails
class Railtie
end
class Engine < Railtie
end
class Application < Engine
end
end
Railtieが全ての基本となり、さらにEngineがあり、その上にApplication(日常的な文脈における所謂「Rails」)がある。
Railtieプラグイン
Railtieの機能を保持したプラグインを生成するには、以下コマンドを利用すると手軽。
生成コマンド
rails plugin new <plugin_name>
もう少し詳しく
Rails::Railtie
http://api.rubyonrails.org/classes/Rails/Railtie.html
Railtie を使った Rails3の拡張 (翻訳版)
http://www.engineyard.co.jp/blog/2013/extending-rails-3-with-railties/
※ Railtieプラグインの事例は少ない様子。
ちょっと気の利いたものを作る時は、Engineの方がより親切にRailを敷いてくれているからかもしれません。
しかし上述のように結局はEngineもRailtieの仕組みを継承しているだけなので、Railtieのことはよく理解しておくと良いです。
Engine(Full Engine)
よりRailsアプリケーションの中身に踏み込みたい時、つまり、既存アプリのControllerやModel、Routing等を拡張したい時に利用。
Railtieと異なる点として、デフォルトでいくつかinitializerが組み込まれており、
Engineのapp,lib,configディレクトリ配下のファイルをホストアプリケーション(Engineを使う側)が自動で認識してくれる。
DeviseやDoorKeeper等が該当。
生成コマンド
rails plugin new <engine_name> --full
もう少し詳しく
Rails::Engine
http://api.rubyonrails.org/classes/Rails/Engine.html
Mountable Engine(Isolated Engine)
より独立性の高いEngine。
ホストアプリケーションから完全に独立している、つまり単体で小さなRailsアプリケーションとして動作可能。
隔絶された独自のRoutingやNamespaceを持つ。
ActiveAdmin等が該当。
生成コマンド
rails plugin new <engine_name> --mountable
もう少し詳しく
使いやすくなった Rails 3.1 の Engine
http://d.hatena.ne.jp/passingloop/20110801/p1
(文中の「それ、プラグインでできるよ」は「Railtieプラグイン」のことだと思われます)
rails pluginコマンドで簡単に出来るgemの作成方法。
http://qiita.com/camelmasa/items/44ceb6ea1a3c727bc567
(「Mountable Engine」という言葉は出てこないが、それの話)
Full Engine と Mountable Engine
ざっくりユースケースの違い
Full Engine
- ホストアプリケーションの延長として使えるので「ちょっと拡張したい」という場合は便利。
- RoutingやNamespaceがコンフリクトする可能性がある。
Mountable Engine
- ホストアプリケーションとコンフリクトする心配無し。
- Engine自体が複雑な場合はMountableで完全に分離するのが吉か。
Routingの拡張を例に思想の違いを見る
Full Engine
ホストアプリケーション側のroutes.rbに特に何も書かずとも、Engineのroutes.rbの中身を勝手に継承してくれる。
Rails.application.routes.draw do
end
Rails.application.routes.draw do
get 'foo' => 'bar'
end
この状態でhostapp側でルーティング確認すると
$ rake routes
Prefix Verb URI Pattern Controller#Action
foo GET /foo(.:format) bar#foo
Engineのroutesが継承されている。
手軽だけどぶつかるリスクもありますね。
Mountable Engine
Rails.application.routes.draw do
mount MyEngine::Engine => "/my_engine" # /my_engine以下にMyEngineのルーティングをmount
end
MyEngine::Engine.routes.draw do
get 'foo' => 'bar'
end
ルーティングを確認
$ rake routes
Prefix Verb URI Pattern Controller#Action
my_engine /my_engine MyEngine::Engine
Routes for MyEngine::Engine:
foo GET /foo(.:format) my_engine/bar#foo
実際のアクセスURLとしては、/my_engine/foo
。
EngineはEngine、ときちっと分離している。
もう少し詳しく
Getting Started with Engines
http://guides.rubyonrails.org/engines.html
Engines – Mountable or Full?
http://www.astjohn.ca/2011/08/06/rails-31-engines-mountable-or-full-part-1
Engine vs. Mountable App
http://stackoverflow.com/questions/6118905/rails-3-1-engine-vs-mountable-app
その他参考
Defining Gems, Plugins, Railties, and Engines
http://hawkins.io/2012/03/defining_plugins_gems_railties_and_engines/
rails/rails engine.rb
https://github.com/rails/rails/blob/master/railties/lib/rails/engine.rb
最後に
今のところ公式APIドキュメント(原文)をあたるのが一番早くて正確そうです。
とはいえ日本語でも正確な情報が増えると良いですね!