Rack Middlewareのリダイレクト設定をrspecでテストする
こんばんは,@h3_potetoです.
RailsにはRack Middlewareという,普通にアプリケーションを作っていると,「ちょっと触らないけど見覚えあるな」というものがあります.
Rack Middlewareといのは,Railsアプリケーションに到達する手前に挟み込まれているミドルウェアです.
そのため,アプリケーションの仕様ではないものだけれど,サーバーの設定ではないところに積みたいときなどに良く使います.
最たるものが,サイトの移行時におけるリダイレクト設定などでしょう.
アプリケーションの仕様として必要なものではないけれど,なだらかに移行するために一時的に組んでいたりするものが多いですよね.
でもそれって,将来的には必要ないものだし,できれば切り離して管理したい……でもnginxの設定に組み込むとなると,そっちだけ別の管理方法を考えなきゃいけない……
リダイレクト設定を組んだ
というわけで,リダイレクトの設定をRack Middlewareに組み込みました.
設定しようと思えば,Railsのルーティングでも,nginxのリダイレクト設定でも構わないのですが,上記のような理由によりRack Middlewareに積むことにしました.
Rack Middlewareを作成
まず,lib/middlewares/request_redirect.rb
というようなファイルを作ります.
例として,旧サイトの/3reason
というアドレスを/reasons
にリダイレクトさせてみましょう.
class RequestRedirect def initialize(app) @app = app end def call(env) request = Rack::Request.new(env) case request.path when /^\/3reason($|\/.*)/ return [301, {'Location' => "/reasons"}, self] end @app.call(env) end def each(&block) end end
これで完成ですが,これをRailsアプリケーションで読み込んでやる必要があります.
Rack Middlewareの読み込み
config/application.rb
に以下を追記します.
# coding: utf-8 ## 中略 module TestApplication class Application < Rails::Application config.autoload_paths << "#{config.root}/lib/middlewares" ## 中略 end end
上記でRack Middlewareを作成した場所をautoload_paths
に設定してやります.
これで,/3reason
にアクセスすると見事にリダイレクトされます.
RSpecでテストが組みたい
これ,リダイレクトの設定が上手く作動しているかのテストなんて,そんな面倒なことをいちいちチェックしたくないですよね.
というわけで当然のごとくテストを組むわけです.
ただし,Rspec側で標準で用意してくれているものではないので,全部自作する必要があります.
require "spec_helper" describe RequestRedirect do include Rack::Test::Methods let(:test_app) { ->(env) {[200, env, "app"] }} let(:app) { RequestRedirect.new(test_app) } describe "/reasons redirect" do it "/3reason should redirect to /reasons" do get("/3reason") (last_response.header["Location"]).should eq("/reasons") end end end
まず,Rack::Test::Methods
をincludeしておく必要があります.これは後ほどlast_response
を使えるようにするためです.
そして,RequestRedirect
に食わせるダミーのアプリを適当に生成してやります(test_app).
今回はLocation
の書き換えをするだけなので,body
の中身は適当に"app"
とかにしておきました.
last_response
というのが肝心な判定部分ですが,Rack::Test::Methods
でリクエストを送信していると,last_request
とlast_response
というのが使えます.
last_request
というのが,最後に送信しているリクエストです.
つまり,test_app
で作成したものをRequestRedirect
に噛ませてget("/3reason")
していますが,このときに渡しているリクエストですね.
last_response
は,そこから最後に受信するレスポンスです.
つまり,今回の場合であればRequestRedirect
から返ってきたレスポンスです.