Template is missing - ruby-on-rails

Currently working on a project, and have encountered a problem that I have never come across before. Currently doing a login sign up page that ask the user to sign up. I had a undefined method `name'error before, and then realised that the method is not called name it was called full_name. I have gone through all the folders to ensure that any method or attribute is not called 'name' and renamed it to 'full_name. Having refreshed the browser I recieve the following error which I haven't seen before. Can some please explain what this error is and how possibly I may go about resolving it.
Template is missing
Missing template users/create with
{:handlers=>[:erb, :rjs, :builder,
:rhtml, :rxml], :formats=>[:html],
:locale=>[:en, :en]} in view paths
"C:/Users/patterd/Documents/Project/app/views"

This error happens if you don't redirect in the create method of your controller.
Are you redirecting in the create method in the controller or rendering the new form, in case of error?
Without the redirection in the create method in the controller, you need to make a new file called create.html.erb. Usually, after successful creation, you redirect to some other page like shown below
def create
# some object you want to create
# if the object.save is fine
# redirect_to object
# else
# render new with the errors
# end
end

In my case I had to process and render no view.
def return_payment
# do lots of stuff
head :ok
end

I had the same problem and the reason was that I left accidentally other empty 'create' method :)

Generally missing template error occurs
-when you don't have view file of that method of controller, or
-if a method is just for calculation that does not have any view file, then you must have to render/redirect the method.
If you do not render or redirect the method, it will search for the view page of current method name (in your case it will search for create.html.erb).So, you have to render/redirect the method.

I had the same problem and just added the redirect_to and it worked!
def update
#visitor = Visitor.find(params[:id])
if #visitor.update_attributes(visitor_params)
flash[:notice] = "Update ok!"
redirect_to root_path #just added this line and it worked!
else
render 'edit'
end
end

Related

How to pass objects from one controller to another controller

On an unsuccessful save, I would like to redirect to the previous view but with the error message.
redirect_to user_path(#user_id), errors: #user.errors
but in the view, when I check for errors I get an undefined variable errors.
I am not using the same controller new and create, so I can't have #user.errors.any in new.html.erb. I have two different controllers, one in which form is there, and another controller which will take care of create, if the create is not happening I need to redirect to the previous controller.
You may need to use render instead of redirect_to.
Something like this:
# controller_1
def step_1
#user = User.new
#user.do_something
...
end
# controller_2
def step_2
if #user.save?
# redirect to another...
else
render 'controller_1/step_1`
end
end
Then on view step_1.html.erb, you can print out errors of #user with #user.errors.
You have to pass the parameters inside the redirect_to helper like below,
redirect_to user_path(id: #user_id, error: #user.errors.messages)
Please check the rake routes and pass the appropriate key for id, whether it's :id, or :user_id

Can I override just part of an ActiveAdmin controller action using `super` + custom redirect?

I've registered a Widget in ActiveAdmin and want to change the redirect that takes place after creating a new one. So that I can accomplish various things with Javascript, I've created a custom form for creating/editing them such that in /admin/widget.rb I have this:
form do |f|
render "create_or_edit_widget"
end
I want to modify the basic Admin::WidgetsController#create action to change where the user is redirected after successfully creating one. I can fill out the rest of the custom action to complete this, except I don't know how to handle a case where the .save fails and the user is redirected back to the form with the formtastic inline error messages. I know how I could do this if I wanted the normal Rails form behavior of creating a list of error messages but not enough about Formtastic to copy its behavior. So far I have this:
controller do
def create
#widget = Widget.new(params[:widget])
if #widget.save
redirect_to admin_widgets_path, notice: "Successfully created Widget."
else
redirect_to :back
end
end
end
I was wondering if I can somehow user super and then only change the redirect path after successful creation instead of having to write out the entire action. If that's not possible, can anyone tell me where in the ActiveAdmin GitHub I'd be able to find the standard #create action so I can copy it out and change the one part?
Yes, you can do that. Here is a working code from my application using super and just changing the redirection
def create
super do |format|
redirect_to admin_submission_discussion_path(id: resource.discussion.slug, submission_id: resource.discussion.client_application.slug) and return if resource.valid?
end
end

Calling methods that render views conditionally in a Rails Controller

I am writing a Ruby on Rails application with a controller called "pages_controller" that is responsible for displaying pages to users. There are 3 different types of pages that can be displayed, and different things have to happen on the back end in each case, so I decided to break the functionality out into 3 methods within the controller. When the user requests a page, the "show" method is called, which figures out whether the page:
1. Belongs to the user
2. Belongs to another user, and can be viewed by the user requesting it
3. Belongs to another user, and cannot be viewed by the user requesting it (unauthorized)
The appropriate method is then called from there to display the page. The code looks something like this:
def show
if (something)
showMine
elsif (something else)
showAnother
else
showUnauthorized
end
end
def showUnauthorized
respond_to do |format|
format.html # showUnauthorized.html.erb
end
end
def showMine
respond_to do |format|
format.html # showMine.html.erb
end
end
def showAnother
respond_to do |format|
format.html # showAnother.html.erb
end
end
I am getting a template missing error because rails wants to render a view when "show" is called, but I do not want any views to be rendered when "show" is called. I simply want "show" to call the correct method from there, and the corresponding view for that method (showMine, showAnother, or showUnauthorized) to be rendered. How can I do this? Or am I going about this the wrong way entirely?
You need to declare these new actions that you have created in the routes file, as they don't belong to the RESTful routes.
I sugest to keep only the show action in your controller and create the IFs in the show view using the render method to include the partials(_showMine.html.erb, showAnother.html.erb, showUnauthorized)
example:
show view:
if (something)
<%= render 'showMine' %>
elsif (something else)
<%= render 'showAnother' %>
else
<%= render 'showUnauthorized' %>
end
I hope it helps...
I basically agree with Samy's comment, but here's some background:
The method that tells Rails what view to use is render. If there's no call to that method in your show method, Rails assumes you have a view called show.xxx.xxx, e.g. show.html.erb, that is supposed to be rendered. Note that it doesn't assume template will be prefixed with show because that's the name of the method. It assumes it will be show because that's the name of the action. The name of the action is passed to the controller as part of the request; it's not simply derived from the name of whatever method has a respond_to block in it.
All the respond_to blocks do is specify different view templates based on the MIME type of the request, but since you never call render, all of those extra methods are still trying to call the show view (show.html.erb in every case), because you never told Rails to render any other view, and the action name is show.
So, instead of the respond_to blocks, just call render [some_view] in each of your other methods.
This might not be the clearest answer, but I'd suggest also reading the following:
http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/
It describes what respond_to does, in particular how it keys off the action name to determine what view to render.

rails controller test, getting ActionView::MissingTemplate: Missing template

I figured I should finally write some tests for my rails app.
My controller is "UsersController". It doesn't have any HTML as I just have an iphone app sending a post in to a rails controller.
Here is my test:
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def test_create
# to http post
# /users
#user[email]=%#&user[password]=%#&user[password_confirmation]=%#
#post
post(:create, :user => {:password => "testpassword", :password_confirmation => "testpassword"})
end
Problem is that I get this error:
1) Error:
test_create(UsersControllerTest):
ActionView::MissingTemplate: Missing template users/new with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths
So I guess it's trying to populate an HTML page? If so, I find this odd. I would think it would directly do the post to the controller. Can someone confirm that this "post" method tries and populates an HTML form?
If this is the case, how should I proceed in writing a test to directly send an HTTP post to the controller?
Thanks for any help
You can specify "format" to make it work:
post(:action, {'param1'=>'value1', 'param2' => 'value2', :format => 'js'})
Unless you tell it otherwise the post method assumes the requested content type is HTML. Typically the create action looks something like this:
#user = User.new(params[:user])
if #user.save
redirect_to posts_path
else
render :new
end
If the action fails it tries to render 'users/new', which doesn't exist, thus the error.
So there are a couple of issues here. It's not clear what content type is expected (XML?). The action is failing, but we can't see why. It might help to edit the question to show us what the controller action does.

Rails: create from two pages

I'm very new to Rails, so maybe I'm just missing the "Rails way" of doing this, but I have a model, call it Post. I can create a post from the canonical posts/new page but also from another page, say home/index.
In home/index i have a form_for #post (slightly different from the one in posts/new, but say that i can use a partial). The problem is that in the PostController.create I cannot pass the newly created #post object back to home/index (in case of errors) because:
if I don't specify a page to render, it will automatically render posts/new
i don't know the calling page in order to redirect it to the right calling page (posts/new or home/index)
even if i knew it (hacking the request referrer or using redirect_to :back), redirect_to doesn't pass objects back, so that #post is empty when called from home/index
Any help? thanks
EDIT
Maybe a possible solution would be to get the calling controller / action from the request and render it back. Any way to do this?
In theory, you could achieve what you're trying to do by checking the referer:
def create
#post = Post.new
if #post.update_attributes(params[:post])
# redirect as appropriate
else
render :action => case request.referer
when new_post_path then "posts/new"
when "/" then "home/index" # assuming that home/index is the root of the site
end
end
end
To get the referrer page, you can make a hidden field with the name redirect. You can use it in the controller.
redirect_to params[:redirect] || posts_path
Have you tried that you pass the post's id in the query string to the home/index
eg: /home/index?post_id=42
You can find out who called your page by looking at
request.referrer
I don't know if this is the "rails way" but here's my solution.
You can add a route for
match home/index/(:id) => "home#index"
and redirect to this after creating the Post. Then in your Home controllers index action just do a
#Post = Post.find(params[:index]) if params[:index]
Your view should display the post if #Post exists
I like this approach because it keeps all the logic where it should be. Routing logic in the controller and view logic in the views.

Resources