Rails + Sinatra apps sharing sessions

2019-05-14 09:22发布

问题:

I haven't found a good answer to this yet. How can I get my Rails app and Sinatra app (mounted in my Rails app's config.ru) to share a session successfully? If I visit my Sinatra app first, then the Rails app, I get an error like undefined method sweep for {}:Hash, presumably because Rails uses a custom subclass of Hash for storing session info, and Rack::Session::Cookie doesn't. My code so far:

config.ru

map "/" do
  run MyRailsApp::Application
end

map "/sinatra" do
  use Rack::Session::Cookie, 
      key: "_app_session",
      secret: "<SECRET_KEY>"

  run MySinatraApp
end

config/initializers/session_store.rb

MyRailsApp::Application.config.session_store :cookie_store, key: '_app_session'

config/initializers/secret_token.rb

MyRailsApp::Application.config.secret_token = "<SECRET_KEY>" # same as config.ru

Anything I've missed?

回答1:

A quick grep of the Rails source reveals sweep is a method on ActionDispatch::Flash::FlashHash, which Rails stores in the session under the flash key.

Sinatra-Flash also uses the flash key of the session, but it stores a plain Hash object there.

Rails is getting the object at session['flash'], which is the Hash put there by Sinatra, assuming it is a FlashHash and trying to call sweep on it, hence the error message: undefined method sweep for {}:Hash.

A possible work around might be to use a different key in the Sinatra app for the flash rather than the default (e.g. flash(:my_flash)[:error]="foo").

That won't help if you want to use the flash to see messages when going between Rails and Sinatra though.



回答2:

The "undefined method sweep for {}:Hash" issue is with your browser storing previously cached cookies. Just delete the cookies related to the application and refresh the browser. It worked for me.