railsでenterprise機能を作成する方法
railsでenterprise機能を作成する方法について確認する。
chatwootの場合
enterprise機能のcommitは https://github.com/chatwoot/chatwoot/pull/3209 が初となる。
このcommitでは、enterpriseディレクトリを作成し、enterpise/LICENSEにエンタープライズライセンスを利用すると明記している。
作成したenterrprise機能を読み込むために、config/application.rb
で eager_load_paths
を使って読み込みパスに追加している。
# config/application.rb
config.eager_load_paths += Dir["#{Rails.root}/enterprise/app/**"]
追加されたenterpriseディレクトリ配下の機能は、config/initializers/01_inject_enterprise_edition_module.rb
を利用してprepend
することで、app/ディレクトリの機能を拡張をしている。
機能自体は、gitlabの https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/initializers/0_inject_enterprise_edition_module.rb を参考に実装されている。
gitlabの場合
gitlab は CEとEE の2つのリポジトリを1つのリポジトリに統合した経緯がある。現在はgitlabリポジトリ1つで開発が進められており、enterprise機能はee/配下に格納されている。
enterprise edition 開発の詳細について
Developing Enterprise Edition Features https://chatwoot.help/hc/handbook/articles/developing-enterprise-edition-features-38 に enterprise機能の開発について記載がある。
viewの場合
controllerはviewをレンダリングする際に、デフォルトではapp/views/
ディレクトリパスのみを探索する。
prepend_view_path
https://api.rubyonrails.org/classes/ActionView/ViewPaths.html#method-i-prepend_view_path を使って、enterpriseディレクトリ配下のviewを利用するようにcontrollerで指定する。
class EnterpriseBaseController
before_action :prepend_view_paths
def prepend_view_paths
prepend_view_path 'enterprise/app/views/'
end
controllerの場合
既存controllerの拡張
enterprise/app/controllers/enterprise/accounts_controller.rb
で、moduleを作成し、拡張元で継承階層を指定する
# enterprise/app/controllers/enterprise/accounts_controller.rb
module Enterprise::AccountsController
def self.prepended(base)
base.before_action :prepend_view_paths
end
def prepend_view_paths
prepend_view_path 'enterprise/app/views/'
end
end
# app/controllers/enterprise/accounts_controller.rb
class AccountsController < ApplicationController
...
end
::AccountsController.prepend(Enterprise::AccountsController)
app/controllers/enterprise/accounts_controller.rbでprependで先読みすると、controllerの継承階層は次の通りとなる。
AccountsController.ancestors
=>
[Enterprise::AccountsController,
AccountsController,
ApplicationController,
...
Enterprise専用機能の場合
enterprise/app/controllers/articles_controller.rb
で、classを作成する。prepend_view_pathsを使ってレンダリングするviewsディレクトリを調整する。
# enterprise/app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
before_action :prepend_view_paths
def prepend_view_paths
prepend_view_path 'enterprise/app/views/'
end
...
migrateについて
Data Models & Data Migrations
Users could be migrating between versions. So we always have to ensure that all the migrations are run for both the edition. The database schema needs to remain the same for both editions. In the Case of DataMigrations, you can have blank implementations for these migrations by conditionally excluding Enterprise specific DataModels with ChatwootApp.enterprise?
migrateについては、chatwootでは各バージョンへの移行がある可能性があるため、db/migrateで一本化されている。
まとめ
enterpriseディレクトリ配下にenterpriseライセンスを使って、enterprise機能を拡張していく。
enterpriseから移行する場合があるため、dbは一本化し、あくまでプランのひとつとして考える。
参考
gitlabのエディションについて
eager_load_pathsについて
Discussion