LoginSignup
2
1

More than 3 years have passed since last update.

Rails EngineのRoutesを書き換える

Last updated at Posted at 2021-01-09

はじめに

Rails Engineは複数のプロジェクトで、同じアプリケーションの機能を提供したい場合に使いますよね

有名なgemではdeviceとかでしょうか

そんなRails Engineですが、上位アプリケーションで独自の機能を追加したいときがあります

今回はRoutesにフォーカスします

上位アプリケーションで、Rails EngineのRoutesを上書き、追加してみましょう

Rails Routes

アプリケーションのルーティングを定義します

routes.rb
Rails.application.routes.draw do
  resources :posts
end

Rails Engineではこんな感じです

routes.rb
MyEngine::Engine.routes.draw do
  resources :users
end

draw

このdrawメソッドが何をやっているのか見てみる

rails/actionpack/lib/action_dispatch/routing/route_set.rb
def draw(&block)
  clear! unless @disable_clear_and_finalize
  eval_block(block)
  finalize! unless @disable_clear_and_finalize
  nil
end

なんかclear!して、blockを展開して、finalize!している

clear!

clear!が何をしているのか見てみる

rails/actionpack/lib/action_dispatch/routing/route_set.rb
def clear!
  @finalized = false
  named_routes.clear
  set.clear
  formatter.clear
  @polymorphic_mappings.clear
  @prepend.each { |blk| eval_block(blk) }
end

なんか@prependを展開してますね

@prependはどこでセットされてるのか?

rails/actionpack/lib/action_dispatch/routing/route_set.rb
def prepend(&block)
  @prepend << block
end

prependってメソッドのblockが展開されることがわかります

ってことは、prependで定義されたroutesは、アプリケーションのdrawで定義された手前に差し込まれるってことです

Railsのroutesは上から順番にマッチングされるので、定義済みのルーティングを上書きしたりできます

finalize!

finalize!が何をしているのかを見てみる

rails/actionpack/lib/action_dispatch/routing/route_set.rb
def finalize!
  return if @finalized
  @append.each { |blk| eval_block(blk) }
  @finalized = true
end

@appendを展開してますね

@appendはどこでセットされているのか?

rails/actionpack/lib/action_dispatch/routing/route_set.rb
def append(&block)
  @append << block
end

appendってメソッドのblockが展開されていることがわかります

ってことは、appendで定義されたroutesは、アプリケーションのdrawで定義されたあとに差し込まれるってことです

なので、単純にRoutesを追加することができますが、アプリケーションで定義されているルーティングが優先されます

Rails EngineのRoutesを上書き

では、Engineのroutesを上書きしてみる

こんなルーティングが定義されていて、ネストしたルーティングに上書きしたい!

routes.rb
MyEngine::Engine.routes.draw do
  resources :users
end

上書きなので、prependを使って定義します

こういうネストをさせたいユースケースは、Engineの名前空間を利用したいときですかね

config/initializers/my_engine_routes.rb
MyEngine::Engine.routes.prepend do
  resources :users do
    resources: posts
  end
end

追加したい場合は、appendを使って定義します

config/initializers/my_engine_routes.rb
MyEngine::Engine.routes.append do
  resources: posts
end

まとめ

今回はRilas EngineのRoutesを上書き、追加する方法を、Railsのコードをみながら書きました

もちろん、上位アプリでも同じことができます

prepend,appendを使って、肥大化したroutesのファイルを分割したりもできますね

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1