Reputation: 4144
I have the following, rather trivial, code that should log a user into my application using Devise. This actually works just fine if it's done using an HTML request rather than XHR. When I do it this way, the XHR is made,
= form_for(@user, :url => session_path(@user), :remote => true) do |f|
= f.label :email
= f.text_field :email, :size => 15, :maxlength => 32
= f.label :password
= f.password_field :password, :size => 15, :maxlength => 32
%br
= f.submit "Sign in"
and the result is:
Started GET "/" for 127.0.0.1 at 2012-12-04 13:24:44 -0800
Processing by HomeController#index as HTML
Rendered home/_hello_page.html.haml (0.1ms)
Rendered home/index.html.haml within layouts/application (1.9ms)
Completed 200 OK in 18ms (Views: 16.3ms | ActiveRecord: 0.4ms)
Started POST "/users/sign_in" for 127.0.0.1 at 2012-12-04 13:24:54 -0800
Processing by Devise::SessionsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"1cGaycA20NMhK0fOwQyN8e3aSFwCHB6BZcLwmvKTI3U=", "user"=>{"email"=>"[email protected]", "password"=>"[FILTERED]"}, "commit"=>"Sign in"}
Completed 500 Internal Server Error in 65ms
ActionView::MissingTemplate (Missing template devise/sessions/create, devise/create, application/create with {:locale=>[:en], :formats=>[:js, :html], :handlers=>[:erb, :builder, :coffee, :haml]}. Searched in:
* "/Users/sxross/Developer/iPhoneApps/motion/whos_here/whos_here_server/app/views"
* "/Users/sxross/.rvm/gems/ruby-1.9.3-p327@whos_here_server/gems/devise-2.1.2/app/views"
):
Everything is exactly as I expect it and it's clear that Processing by Devise::SessionsController#create as JS
is telling the receiving controller "ship me back the JSON I want." So the question is why is the Devise controller trying to render a template instead of JSON and what can I do to fix it?
Thanks!
Upvotes: 0
Views: 1436
Reputation: 525
You are missing a create.js.[erb|haml] file in views/devise/sessions
When you send a remote request for login, the request is done by Devise::SessionsController#create, and if you don't override it
respond_with resource, :location => after_sign_in_path_for(resource)
will look for a create.js.erb. I ussualy just have
window.location = "<%= root_url %>"
in it.
Also, you would need to set
config.http_authenticatable_on_xhr = false
config.navigational_formats = [:"*/*", "*/*", :html, :js]
inside config/initializers/devise.rb for this to work.
I for my own case have overridden the sessions controller with this:
@resource = warden.authenticate!(:scope => resource_name, :recall => "sessions#failure")
sign_in(resource_name, @resource)
respond_to do |format|
format.html { respond_with @resource, :location => after_sign_in_path_for(@resource) }
format.js
end
which throws me to a failure method if the authentication has failed, and process it in failure.js.erb to show the user that
Upvotes: 1