Gem、Railtieプラグイン、Engine（full/mountable）の違いとそれぞれの基礎情報



特にRailtie、Engine（full/mountable）あたりの区分けについて、日本語の情報があまり見当たらなかったためメモします。

# TL;DR

- 汎用的なRubyスクリプトをGem化したい時は`bundle gem <gem_name>`。
- Railsのレールに乗ってプラグインを作りたい時はEngine（こちらもGemとして配布可能）。
- Railtieの仕組み自体はRails全体に通ずるため理解しておきたい。
- Full EngineとMountable Engineの違いはホストアプリケーションとの結合度。

# Gem

[RubyGems](https://rubygems.org/)経由で公開されている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）等々コアな部分を手軽に拡張していくことが出来る。


その本体は

```rb
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を見れば明らかになる。

```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](http://www.amazon.co.jp/gp/product/4774165166/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4774165166&linkCode=as2&tag=kidachi-22)引用の、Railtie/Engine/Applicationの関係を示した疑似コード。

```ruby
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](https://github.com/plataformatec/devise)や[DoorKeeper](https://github.com/doorkeeper-gem/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](https://github.com/gregbell/active_admin)等が該当。



### 生成コマンド

```
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の中身を勝手に継承してくれる。

```hostapp/config/routes.rb
Rails.application.routes.draw do
end
```

```my_engine/config/routes.rb
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


```hostapp/config/routes.rb
Rails.application.routes.draw do
  mount MyEngine::Engine => "/my_engine"  # /my_engine以下にMyEngineのルーティングをmount
end
```

```my_engine/config/routes.rb
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



# その他参考

[パーフェクトRuby on Rails](http://www.amazon.co.jp/gp/product/4774165166/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4774165166&linkCode=as2&tag=kidachi-22)

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ドキュメント（原文）をあたるのが一番早くて正確そうです。
とはいえ日本語でも正確な情報が増えると良いですね！