web-dev-qa-db-ja.com

Rails内からRack環境にアクセスするにはどうすればよいですか?

次のようなRackアプリケーションがあります。

class Foo
  def initialize(app)
    @app = app
  end
  def call(env)
    env["hello"] = "world"
    @app.call(env)
  end
end

RackアプリケーションをRailsにフックした後、Rails内からenv["hello"]にアクセスするにはどうすればよいですか?

更新:回答をくれたGaiusに感謝します。 Rack and Railsリクエストの期間中、またはセッションの期間中、物を保存できます。

# in middleware
def call(env)
  Rack::Request.new(env)["foo"] = "bar"  # sticks around for one request

  env["rack.session"] ||= {}
  env["rack.session"]["hello"] = "world" # sticks around for duration of session
end

# in Rails
def index
  if params["foo"] == "bar"
    ...
  end
  if session["hello"] == "world"
    ...
  end
end
31

リクエストスコープ変数を渡すためにRack::Requestオブジェクトを使用できると確信しています。

# middleware:
def call(env)
  request = Rack::Request.new(env) # no matter how many times you do 'new' you always get the same object
  request[:foo] = 'bar'
  @app.call(env)
end

# Controller:
def index
  if params[:foo] == 'bar'
    ...
  end
end

または、その「env」オブジェクトを直接取得することもできます。

# middleware:
def call(env)
  env['foo'] = 'bar'
  @app.call(env)
end

# controller:
def index
  if request.env['foo'] == 'bar'
    ...
  end
end
27
James A. Rosen

簡単な答え:コントローラー内でrequest.envまたはenvを使用します。

長い答え:

Rails Guide on Rails controllers によると、ActionControllerは、に関する情報にアクセスするために使用できるrequestメソッドを提供します。コントローラが応答している現在のHTTPリクエスト。

ActionController::Base#request のドキュメントをさらに調べると、「現在のリクエストを表すActionDispatch :: Requestインスタンスが返されます」ことがわかります。

ActionDispatch::Request のドキュメントを見ると、 Rack::Request から継承していることがわかります。あはは!さあ行こう。

さて、 Rack::Request のドキュメントに慣れていない場合は、基本的にはRack環境のラッパーです。したがって、ほとんどの場合、そのまま使用できるはずです。ただし、生の環境ハッシュが本当に必要な場合は、 Rack::Request#env で取得できます。したがって、Railsコントローラー内では、それはrequest.envになります。

深く掘り下げる:

ActionController::Base のインスタンスメソッドをさらに調べたところ、見るべきものがそれほど多くないことに気づきました。特に、params変数とsession変数が欠落しているように見えることに気づきました。そこで、1つ上のレベルを ActionController::Metal に移動しました。これは、 ActionController::Base から継承されます。

ActionController::Metal で、メソッド env を発見しましたが、それが何をしたかについてのドキュメントはありませんでしたが、推測できました。私が正しかったことがわかりました。その変数は request.env に割り当てられていました。

ActionController::Metal には、 params メソッドも含まれています。これは、 ソース によれば、デフォルトで request.parameters に設定されています。結局のところ、request.parametersRack::Request からではなく、 ActionDispatch :: Http :: Parameters からのものであり、 ActionDispatch::Request に含まれています。このメソッドは Rack::Request#params メソッドと非常に似ていますが、変更するとRails固有のRack環境変数が変更される点が異なります(したがって、変更は ActionDispatch::Request のインスタンス間で永続的に維持されます)。

しかし、それでもsessionメソッドを見つけることができなかったようです。結局のところ、それはドキュメントにはまったく含まれていません。ソースコードで ActionController::Metal を検索したところ、ついに この行 で見つかりました。そうです、それは request.session のショートカットにすぎません。

要約する:

コントローラー内...

  • request.envまたはenvを使用して、生の環境オブジェクトを取得します
  • paramsを使用して、ラッククエリ文字列を読み取り、ラック入力ストリームからデータを投稿します。 (例: Rack::Request#params
  • ラック環境でrack.sessionの値にアクセスするには、sessionを使用します

ミドルウェア内...

21
Ajedi32