render partial from controller with :layout => !request.xhr? returns missing template? - ruby-on-rails-3

I cloned and tweak this rails app and I am experiencing some trouble with rendering a partial when on ajax request, in the logs I see that the guilty line is in the registrations_controller.rb (Devise)
class RegistrationsController < Devise::RegistrationsController
def create
build_resource
if resource.save
if resource.active_for_authentication?
sign_in(resource_name, resource)
(render(:partial => 'thankyou', :layout => false) && return) if request.xhr?
respond_with resource, :location => after_sign_up_path_for(resource)
else
resource.update_attribute(:encrypted_password, nil) # make sure there is no password
expire_session_data_after_sign_in!
(render(:partial => 'thankyou', :layout => false) && return) if request.xhr?
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
render :partial => 'email_capture', :action => :new, :layout => !request.xhr?**
end
end
protected
def after_inactive_sign_up_path_for(resource)
'/thankyou.html'
end
def after_sign_up_path_for(resource)
redirect_to root_path
end
end
The error message returned is this:
ActionView::MissingTemplate - Missing partial
with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder,
:coffee, :haml]}. Searched in: *
"/Users/Davide/Documents/Jobsite/rails-prelaunch-signup-1click/app/views"
* "/Users/Davide/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/devise_invitable-1.1.8/app/views"
* "/Users/Davide/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/devise-2.2.4/app/views"
Interestingly if I remove the :layout => !=request.xhr? parameter the partial gets found but the page refreshes and the loses all the stylesheets and other assets.
Any idea where should I start looking?
Thanks!

I have also cloned and modified that project, and ran into nearly the same issue. For me, the problem would appear after the second failure of saving a bad email address--but the result was identical.
By using context and information from the following question/answer:
form returned from AJAX request is not recognized as 'remote' when submitted
I was able to make a change that resolved my issue. In _email_capture.html.erb, add :remote => true, to the simple_form_for line. In my case, the whole revised line is:
<%= simple_form_for resource, :as => resource_name, :remote => true, :url => registration_path(resource_name) , :html => {:class => 'form-inline'} do |f| %>
Hope this helps you, too!

Related

respond_with location ignored on GET request

At each step in my checkout process, an order is updated via a PUT request. However, one of the states has a form that submits to a third party which redirects back to my site, calling the update method with GET (no control over this).
Why does my respond_with code appear to be totally ignored and I get a Missing Template checkout/update error? It should be hitting #edit.
CheckoutController.rb
before_filter :load_order
def update
if #order.update_attributes(params[:order])
#order.next
end
respond_with(#order, :location => checkout_state_url(#order.state))
end
routes.rb
match '/checkout/update/:state' => 'checkout#update', :as => :update_checkout
match '/checkout/:state' => 'checkout#edit', :as => :checkout_state
match '/checkout' => 'checkout#edit', :state => 'client_details', :as => :checkout
It looks like respond_with does different things depending upon the HTTP verb and whether the resource has errors. See here and here.
The following code worked for me:
def update
if #order.update_attributes(params[:order]) && #order.next
respond_with(#order) { |format| format.html { redirect_to checkout_state_url(#order.state) } }
else
respond_with(#order) { |format| format.html { render :edit } }
end
end

Rails 3 Correctly routing the destroy action for a session

I am refactoring my access_controller into a sessions_controller and can't seem to get my destroy action working properly.
Logging in seems to work fine, but I am unable to log out of a session. Here is the link I have for logging out:
<%= link_to("Logout", :controller => "sessions", :action => 'destroy') %>
routes.rb
resources :sessions
sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
...
end
def destroy
session[:user_id] = nil
flash[:notice] = "You are now logged out"
redirect_to root_url
end
end
When I click "Logout" I get redirected to "/sessions/destroy" with a message of "The action 'show' could not be found for SessionsController". The destroy actions seems to want an id, but I don't need to pass in an id, I just want to run the action.
Ah, I found the answer here: http://railscasts.com/episodes/250-authentication-from-scratch
I need to set up my routes as follows:
get "log_out" => "sessions#destroy", :as => "log_out"
get "log_in" => "sessions#new", :as => "log_in"
resources :sessions

Rails 3 render partial from another controller (error: ActionView::MissingTemplate)

I'm trying to include a login (username / password) in the header of my application.html.erb. I am getting this error:
Missing partial /login with {:handlers=>[:rjs, :builder, :rhtml, :erb, :rxml], :locale=>[:en, :en], :formats=>[:html]} in view paths "/app/views"
This is happening when I make this call in my application.html.erb:
<%= render '/login' %>
'/login' is defined in my routes.rb as:
match '/login' => "sessions#new", :as => "login"
UPDATE: here is my sessions controller:
class SessionsController < ApplicationController
def create
if user = User.authenticate(params[:email], params[:password])
session[:user_id] = user.id
user.last_login = Time.now
user.save
redirect_to root_path, :notice => "login successful"
else
flash.now[:alert] = "invalid login / password combination " # don't show pass + params[:password]
#render :action => "new"
redirect_to login_path, :notice => "wrong user pass"
end
end
def destroy
reset_session
redirect_to root_path, :notice => "successfully logged out"
end
end
I have seen in other posts that this can be due to not defining a variable in a controller action, but since this is a session, and it is in the application.html.erb (application_controller.rb), I'm not sure how to do this. Anybody know how to do this? Thanks!
<%= render "sessions/login", :#user => User.new %>
will render login partial of sessions view, i.e. '_login.html.erb' in views/sessions and instantiate #user to new user so that it can be referenced directly in the partial as :
form_for #user, :url => sessions_path do |f|
f.text_field :email
Check your file extension in my case file extension was rhtml, I changed it into html.erb.
Now its working fine.
Note:
This file with rhtml extension was working fine in rails <= 3.0.10. But stopped working in rails 3.1.12. So I changed its extension as mentioned above.

Rails 3 Controller update action works locally but not on heroku, get missing template error

I am experiencing a similar problem as this previous SO question, but the answer doesn't seem to fit me. So I wanted to follow up with my issue.
I have an action in my controller that updates my Profile model using a checkbox. When I click the checkbox with the app running locally I have no problems. However when I deploy to Heroku I get:
ActionView::MissingTemplate (Missing template profiles/show_hometown_settings with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths "/app/app/views", "/app/vendor/plugins/rails_log_stdout/app/views", "/app/vendor/plugins/rails3_serve_static_assets/app/views", "/app/vendor/plugins/paperclip/app/views"):
I added both a _show_hometown_settings.html.erb file and a _show_hometown_settings.js.erb file but neither did the trick. Checking my checkbox gave me vanilla code on my screen and the above error.
If I add show_hometown_settings.html.erb I no longer get vanilla code. I see the show_hometown_settings.html.erb template, but I still get the error and I don't get redirected to my settings_path, which is the whole point (check to update, post to db, redirected to make further settings changes). Can anyone help me out with this?
Here is the controller action:
def show_hometown_settings
#profile = current_user.profile
if #profile.show_hometown == true
if #profile.update_attributes(:show_hometown => false)
redirect_to settings_path
else
redirect_to settings_path, :notice => 'Oops, something went wrong. Please try again.'
end
elsif #profile.show_hometown == false
if #profile.update_attributes(:show_hometown => true)
redirect_to settings_path
else
redirect_to settings_path, :notice => 'Oops, something went wrong. Please try again.'
end
end
end
Here's the form I use for the action:
<%= form_tag({:action => "show_hometown_settings", :controller => "profiles"}, :html => {:multipart => true }) do %>
<%= check_box_tag(:show_hometown, 1, #user.profile.show_hometown ? true : false) %>
<%= #user.profile.hometown %>
<% end %>
UPDATE: Here is the part of my routes.rb file that references the action:
match "profiles/show_hometown_settings", :to => "profiles#show_hometown_settings"
UPDATE 2: Following the question below, I got a different error and my logs show a route issue:
This returns
`The page you were looking for doesn't exist (404)`
And in my heroku logs --tail I see
2012-01-19T23:13:47+00:00 app[web.1]: Started POST "/profiles/show_hometown_settings" for 98.218.231.113 at 2012-01-19 23:13:47 +0000
2012-01-19T23:13:47+00:00 app[web.1]:
2012-01-19T23:13:47+00:00 app[web.1]: ActionController::RoutingError (No route matches "/profiles/show_hometown_settings"):
If I change the route from :via => [:put] to :via => [:post] it works. Hopefully that's alright.
You shouldn't need to have that template file at all since you aren't rendering a view, you're only redirecting.
What's probably happening is that your if-elsif logic is breaking down and the code is never reaching those redirects (because neither of the if blocks are evaluating to true). If Rails doesn't get a redirect_to call, then by default it will render the view for the controller action (which is what it is trying to do).
I would change it around to this:
Route:
match "profiles/show_hometown_settings", :to => "profiles#show_hometown_settings", :as => :show_hometown_settings, :via => [:put]
Controller:
def show_hometown_settings
if current_user.profile.update_attributes(:show_hometown => params[:show_hometown])
redirect_to settings_path
else
redirect_to settings_path, :notice => 'Oops, something went wrong. Please try again.'
end
end
Form:
<%= form_tag(show_hometown_settings_path, :method => :put) do %>
<%= check_box_tag(:show_hometown, 1, #user.profile.show_hometown ? true : false) %>
<%= #user.profile.hometown %>
<% end %>

Rails Routing Error

Rails is giving me a route error even though the route appears to
be in the route list.
The form is doing a Post to try to hit the update route on the Admin::ProductsController.
The edit route, index route, and show route work fine.
Using Rails 3.0.5 and ruby 1.9.2
Anyone have an idea? I can't seem to see the problem.
Error
No route matches "/admin/products/2039"
Code from ERB File that is generating the form
<%= form_for :product, #product, :url => { :action => "update" } do |f| %>
Products Controller method at this point is just a stub of
def update
puts params.inspect
end
Routes File
Analytics::Application.routes.draw do
match 'login' => 'Authentication#login', :via => [:get, :post]
namespace :admin do
# Directs /admin/products/* to Admin::ProductsController
# (app/controllers/admin/products_controller.rb)
root :to => 'AdminInterface#index', :via => :get
resources :products
resources :publishers, :only => [:edit, :update]
match 'publishers/query/:subset' => 'Publishers#index', :as => :publishers_subset, :via => [:get, :post]
end
end
According to your routes, shouldn't that be
= form_for [:admin, #product] do |f|
Your form_for can just be:
<%= form_for #product do |f| %>
If #product is an existing object then it will automatically know to go the update action of the ProductsController.