Engineを作る

手順

1. Engine 化対象のアプリケーションをまず作る

普通のRailsアプリケーションをまず作りこみます。その大部分ないし一部を Engine 化することになります。ここでは、myapp という名前のアプリケーションを作っているものとして例示していきます。

2. Rails Engines プラグインをインストール

myapp プロジェクト内にまだ Engines プラグインをインストールしていなければします。Subversion が入っておりインターネットに接続できるなら以下でインストールできます。

(myapp ディリレクトにて)

> ruby script/plugin install http://svn.railsengines.org/plugins/engines

plugin インストールには幾つかの方法があるので例えば以下の情報を参考にしてください。

ここまでの作業で、myapp のディリレクト構造の特徴は以下のようになります。

app ... プログラム内容が入っている
vendor
  plugins
    engines ... Rails Engines プラグイン

3. Engine の雛型を作成

myapp プロジェクト内に Engine の雛型を作成します。ここでは、Engine 名は MyEngine とします。この雛型を完成させていくことで、myapp プロジェクトが MyEngine をインストールした状態となります。

(myappディレクトリにて)

> ruby script/generate engine MyEngine

途中、ライセンスや作者、Eメールアドレスについて問い返されるので、それぞれ回答すると、それらが雛型に組み込まれます。

この作業によって、myapp ディリレクト構造は以下のように変化します。

app ... プログラム内容が入っている
vendor
  plugins
    engines ... Rails Engines プラグイン
    my_engine ... 今作成した Engine 雛型プラグイン

4. Engine化したいソースを Engine 側へ移動

Engine 側に持たせたいソースを vendor/plugins/my_engine/app 下の対応するディレクトリへ移動していきます。

必要に応じて Engine 側へ移動する対象となるソース類は以下のものです。 {{fn('これ以外のものでも移動して動くものがあるのかもしれませんが試していません。なお、Engine の動作に必要な別の(engines以外の) plugin がある場合、通常は Engine 内には含めず、アプリケーションが engines や my_engine とあわせてその必要 plugin をインストールする、という前提にするのが基本と思われます。')}}Hiki::PluginException (not plugin method): inline plugin

  • app
    • helpers ... ヘルパーのソース
    • models ... モデルのソース
    • controllers ... コントローラのソース
    • views ... ビューのソース
  • test ... テストのソース
  • db ... migrate ファイル
  • tasks ... rake task ファイル
  • lib ... Engine が動くのに必要なライブラリファイル
  • public ... stylesheet, javascript など

単に移動すればよいものもあれば、修正が必要になるものもあります。

修正が必要になるポイントを以下に説明します。

4-1. ApplicationController, ApplicationHelper

ApplicationController や ApplicationHelper はアプリケーション側で明らかに自前の定義が必要であるため、Engine には持っていかないほうが良いと考えられます。

そこで、Engine に持っていきたいコードについて、必要に応じて別のファイルに移動します。例えば以下のようにします。

  • application.rb の中の移したいコード
    • my_engine/lib/my_engine.rb に移して、my_engine をアプリケーションがインストールするときは MyEngine を ApplicationController に include してもらう取り決めにします。{{fn('多分そうだと思いますがまだ試していません。')}}Hiki::PluginException (not plugin method): inline plugin
module ApplicationController
 include MyEngine
end
  • application_helper.rb の中の移したいコード
    • my_engine/app/helpers/my_engine_helper.rb に移して、同様に、ApplicationHelper に MyEngineHelper を include してもらう取り決めにします。
module ApplicationHelper
 include MyEngineHelper
end

上記は例であり必ずしもこの方法をとる必要はありません。

4-2. レイアウト

コントローラ名によるレイアウトの適用が効かなくなる現象が起きた場合は、明示的に layout 宣言をしてみて下さい。

class FooController
  layout 'foo'
end

4-3. スタイルシート

スタイルシートそのもの(例:foo.css)は、基本的にはpublic フォルダの該当箇所に移動するだけです。

スタイルシートの参照を宣言している rhtml ファイルは、参照宣言の仕方を変更する必要があります。

変更前

<%= stylesheet_link_tag 'foo' %>

変更後

<%= engine_stylesheet 'my_engine', 'foo' %>

詳しくは Rails Engines の API を参照してください。

4-4. JavaScript

Stylesheet 同様に、宣言方法を変える必要があります。

変更前

<%= javascript_include_tag 'myscript' %>

変更後

<%= engine_javascript 'my_engine', 'myscript' %>

ただし、rails アプリケーションがデフォルトで用意するようなJavaScript(例えば prototype.js)の宣言については、(アプリケーション側にファイルがあるので)変更なしでも普通は動作します。相手のアプリケーション環境にこれらのファイルがあることを想定するのであれば特に Engine 側に持たせる必要はないでしょう。

5. アプリケーションの environment.rb の変更

5-1. 設定データの定義方法の変更

一般に、アプリケーションでは、設定情報を environment.rb に定義している場合があります。例えば表示ファイル数上限や、メールモードのOFFといった、アプリケーション運用者が決めるべきパラメータについて。

Engine 化を行った後も、これらの設定は引き続き動作しますが、MyEngine がいろいろなアプリケーションで使われる場合、パラメータ名の衝突や、どの部分がEngine でどの部分がアプリケーションの設定か明確でないなどの問題が起きる可能性があります。

これは、environment.rb の中で、config メソッド(Rails Engines によりModuleが拡張されて使えるようになります)を使って以下のように書くとスマートです。

 module MyEngine
   config :file_max, 100
 end

詳しくは Rails Engines の API を参照してください。

5-2. Engines.start

上記設定に関するコードの後で、以下の行を記述します。

Engines.start :my_engine

Engine の migrate

> rake db:migrate:engines:my_engine

Engine の migration version は、アプリケーションの migration versionとは別に、以下のテーブル構造で管理されます。

  • engine_schema_info テーブル
    • engine_name カラム ... engine 名
    • version カラム ... migration version

Engine の テスト

> rake test:engines:my_engine

アプリケーションとEngineを並行開発する場合の環境

アプリケーションと Engine を両方開発する場合、Engine がそのアプリケーションの一部としてしか当面開発されないなら、上記で紹介した myapp プロジェクトをまるごと SVN に入れて管理すればよいと思います。Engine に対して複数のアプリケーションを開発し、それぞれ SVNで管理する場合は、以下のようにすることができます。

app1 ---(SVNレポジトリ)
  vendor
    plugins
      my_engine ---(SVNレポジトリ)
app2 プロジェクト (SVNレポジトリ)
  vendor
    plugins
      my_engine ---(SVNレポジトリ)
Last modified:2020/06/12 18:49:05
Keyword(s):
References:[Ruby on Rails]