[action_push_native] Engineからの設定ファイル提供を可能にする`paths["config/push"]`の活用
Context: なぜこの変更が必要だったのか
Action Push Nativeは、これまでconfig_for(:push)を使って設定ファイルを読み込んでいました。しかし、この方法ではpaths["config"]にあるファイルしか参照できず、Engineが独自に登録したpaths["config/push"]のパスが無視されていました。
これは、Action Push Nativeを利用する他のGem(Engine)が、ホストアプリケーションに依存せず独自の設定ファイルを提供したい場合に問題となります。例えば、特定のプッシュ通知機能を提供するEngineが、デフォルトの設定を内包したい場合、これまでの実装では実現できませんでした。
このPRでは、paths["config/push"]を直接参照するように変更することで、Engineが自身の設定パスを追加できるようになります。
Technical Detail: 実装の変更点
設定読み込みロジックの変更
従来はconfig_for(:push)を直接呼び出していましたが、新たにconfigメソッドを導入し、paths["config/push"]から設定ファイルを探索するようになりました。
変更前:
def self.config_for(platform, notification)
platform_config = Rails.application.config_for(:push)[platform.to_sym]
# ...
end
変更後:
def self.config_for(platform, notification)
platform_config = config[platform.to_sym]
# ...
end
def self.config
path = Rails.application.paths["config/push"].existent.first
raise "ActionPushNative: config/push.yml not found" unless path
Rails.application.config_for(Pathname.new(path))
end
重要なポイント
paths["config/push"].existent.firstの使用: 存在する最初のパスを取得します。複数のパスが登録されている場合、先頭のパスが優先されます。エラーハンドリングの追加: 設定ファイルが見つからない場合に明示的なエラーメッセージを表示します。
Pathnameオブジェクトの使用:config_forにパスを渡す際、Pathnameオブジェクトでラップすることで、Railsの設定ファイル読み込み機構と互換性を保ちます。
Engineでの活用例
この変更により、Engineは以下のように独自の設定ファイルを提供できるようになります。
class MyEngine < ::Rails::Engine
initializer "my_engine.push_config" do |app|
# Engineのconfig/push.ymlを先頭に追加
app.paths["config/push"].unshift(
File.expand_path("../config/push.yml", __dir__)
)
end
end
この仕組みにより、ホストアプリケーションにconfig/push.ymlがない場合でも、Engineが提供する設定ファイルが自動的に使用されます。unshiftとexistent.firstの組み合わせにより、Engine側で追加された設定パスが優先されます。
テストケースからの確認
追加されたテストでは、Engine用の設定ファイル(push_from_engine.yml)を先頭に追加することで、その設定が読み込まれることを確認しています。
test "config loads from first existent path" do
# Engineがパスを先頭に追加することをシミュレート
prepended_path = file_fixture("config/push_from_engine.yml").to_s
paths = Rails.application.paths["config/push"]
original_existent = paths.existent
paths.stubs(:existent).returns([ prepended_path ] + original_existent)
config = ActionPushNative.config
# Engine側の設定が読み込まれていることを確認
assert_equal "engine_key_id", config.dig(:apple, :application, :key_id)
assert_equal "engine_calendar_key_id", config.dig(:apple, :calendar, :key_id)
end
このテストは、Engineが提供する設定値(engine_key_idなど)が正しく読み込まれることを検証しています。
まとめ
この変更により、Action Push Nativeを利用するEngineは、ホストアプリケーションに依存せず独自のプッシュ通知設定を提供できるようになりました。Railsのpathsメカニズムを正しく活用することで、柔軟な設定管理が可能になっています。