Can't find View template in Rails? - ruby-on-rails

This is my users_controller.rb code:
...
def edit
#user = #current_user
end
def update
#user = #current_user # makes our views "cleaner" and more consistent
if #user.update_attributes(params[:user])
flash[:notice] = "Account settings updated."
redirect_back_or_default account_url
else
render :action => 'edit'
end
end
...
I have the following views/users:
new.html.erb
password.html.erb
profile.html.erb
show.html.erb
Everytime I try to update my user account settings, the following pops up:
ActionView::MissingTemplate (Missing template users/edit.erb in view path app/views:vendor/plugins/admin_data/app/views):
app/controllers/users_controller.rb:46:in `update'
It's not the fault of admin_data is you are curious. It's the controller. What have I done wrong? Thanks.

First, if you want the update action to return to :show, you should change
render :action => 'edit'
to
render :action => 'show'
otherwise, it will of course look for edit.html.erb or edit.erb
Second, if you use 'show' for letting the user edit his/her information, why do you actually have the :edit action in your controller? If you don't use it, you should probably remove the following:
def edit
#user = #current_user
end

unless you tell the edit method to render something else or redirect to some where, the default is that it will look for a template of edit.erb...

Related

How to render an action plus GET parameter?

In my Rails 4 application I have this controller:
class ProfilesController < ApplicationController
SECTIONS = %w(time currency letterhead)
def edit
section = Profile::SECTIONS.include?(params[:section]) ? params[:section] : Profile::SECTIONS[0]
session[:section] = section
end
def update
if #profile.update_attributes(profile_params)
flash[:success] = "Profile updated."
redirect_to edit_profile_path(:section => session[:section])
else
render :edit
end
end
end
In the view, each user's profile record is spread across three different tabs using GET parameters.
E.g. when the user is in the "time" tab and successfully saves it, s/he is redirected to that same tab. Nice!
But unfortunately, when the save is unsuccessful (and Rails' validation kicks in), that doesn't work.
I tried adding a parameter to render but to no avail.
Can anybody tell me what's the best way to do this?
Thanks for any help.
I think you're checking params[:section] in the view and you're using its value to determine which tab to show. So the easiest solution is to just set params[:section] in the else part.
if #profile.update_attributes(profile_params)
flash[:success] = "Profile updated."
redirect_to edit_profile_path(:section => session[:section])
else
params[:section] = session[:section]
render :edit
end
Another easier way is to just use session[:section] in the view so you don't have to pass it in between requests.
render :edit, :locals => {:params1 => "value"}
Use locals to pass paramters in render

First argument in form cannot contain nil or be empty on render

On the update action of the Video controller, I have written -->
def update
if current_user.video.update_attributes(video_params)
flash[:success] = "Video App Updated!"
redirect_to root_url
else
render :edit
end
end
However, the render :edit part seems to be throwing out an error. It says :
First argument in form cannot contain nil or be empty
Extracted source (around line #6):
<div class="row">
<div class="span6 offset3">
<%= form_for(#video) do |f| %> # line 6
I'm assuming I'm not quite understanding what the render is doing. This is what my edit action looks like -->
def edit
#video = current_user.video
end
What do you guys think? Still a noob, much appreciated :)
You don't set #video variable on update action, so it's nil. You should have:
def update
#video = current_user.video
if current_user.video.update_attributes(video_params)
flash[:success] = "Video App Updated!"
redirect_to root_url
else
render :edit
end
end
You should remember that rendering other action's template in controller doesn't run the code of that action. So, if you have
render :edit
the partial edit will be rendered, but controller code for this action (setting #video) won't run.
The line render :edit will show the edit.html.erb view, but the edit action is not executed. The edit.html.erb is expecting a #video variable that is not set in the update action, that's why you have this error. There is 2 solutions:
Set the #video variable in the update_action
def update
#video = current_user.video
if #video.update_attributes(video_params)
flash[:success] = "Video App Updated!"
redirect_to root_url
else
render :edit
end
end
or
Redirect to the edit action when update fails
def update
if current_user.video.update_attributes(video_params)
flash[:success] = "Video App Updated!"
redirect_to root_url
else
flash[:alert] = current_user.video.errors.full_messages.join('\n')
redirect_to :action => :edit, :id => current_user.video.id
end
end
If the edit was complex, the second solution would be better because it avoids duplication. In your case, the first solution is good also.
The difference between render and redirect_to is explained in Guide Layouts and Rendering in Rails 2.3.2
I have the same type of condition and i have done it like this. and its working in my case
def update
#video = current_user.video
respond_to do |format|
if #video.update_attributes(video_params)
format.html { redirect_to root_url }
else
format.html { render :edit }
end
end
end

Redirection based on the current controller's action

Right now, I have two views that are using the users#create action: users/new.thml.erb and enter_email.html.erb.
The problem is that with the current code, the user is redirected to new.html.erb when the
form in enter_email.html.erb has a validation error. So I tried this:
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
if params[:action] == "enter_email"
render 'enter_email'
else
render 'new'
end
end
end
I wanted to user to be redirected to enter_email.html.erb when the action is 'enter_email'. But I'm still being redirected to 'new.html.erb'.
Any suggestions to fix this? (it is because the action being performed is actually create? If so, how to modify the code to make the redirection work?)
I see a couple of ways to do it:
Add a hidden field to both forms, and check in params for the value of that field, so you know which form you come from
# in your new.html.erb view
hidden_field_tag 'form_name', 'new'
# in your enter_email.html.erb view
  hidden_field_tag 'form_name', 'enter_email'
# in controller
if params[:form_name] == "enter_email"
render 'enter_email'
else
render 'new'
end
Use a different action for creation, like create_from_enter_email, and direct the enter_email form to it.
As you thought, the problem is that the action is create and not enter_email, so the if/else conditional always goes to the else branch and the new view is rendered.
To render the previous view, you can use request.referrer as suggested in this answer:
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
if request.referrer == root_url
render 'enter_email'
else
render 'new'
end
end
end
I'm checking if request.referrer is root_url based on the fact that the login partial is on the homepage (which you mention in the comments below). This should work.

Controller not calling the View in Rails , is Sample

1 - My controller is this , but this not call the view whit this name is login.html.erb, im not understand beacause what happen this , is to show the form of the login.
class FinancesController < ApplicationController
# GET /finances
# GET /finances.json
def login
#user = User.find_by_name(params[:user])
if #user
session[:user_id] = #user.id
redirect_to :action => 'index'
else
redirect_to login_url
end
end
def index
#finances = Finance.all(:order => "created_at")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #finances }
end
end
2 - Someone can talk to me to use the authenticate method to validate a sample login whit user and password forms some, can show to me how use this method , the find_by_name_and_password dont works.
I thanks by the answers, many.
Routes.rb
Controle::Application.routes.draw do
match 'login' => 'finances#login'
resources :finances
end
check for the #user object.
because, as of your code it will redirect to your login method if #user is not available.
To render login.html.erb from login method, there is no need for any manual redirections.

New to jQuery/Ajax how can I add a user relation to creating a new review?

I have been trying to get to grips with jQuery and been following a railscast on adding an Ajax add review form, which works fine but I would now like to add into it the ability for a review to belong to a user as well as a venue.
Reviews controller
def create
#review = Review.create!(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
views\reviews\create.js.erb
$("#new_review").before('<div id="flash_notice"><%= escape_javascript(flash.delete(:notice)) %></div>');
$("#reviews_count").html("<%= pluralize(#review.venue.reviews.count, 'Review') %>");
$("#reviews").append("<%= escape_javascript(render(:partial => #review)) %>");
$("#new_review")[0].reset();
I have tried changing the controller to:
def create
#review = #current_user.reviews.create!(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
but it just wont submit, with no errors.
I think I have the models set correctly with belongs_to and has_many, I think this is a controller issue I'll add other code bits if needed.
Development log
NoMethodError (undefined method `reviews' for nil:NilClass):
app/controllers/reviews_controller.rb:14:in `create'
Thanks for any help!
It appears that your error is residing with #current_user. According to your development log, #current_user is nil when you call #current_user.reviews on it. I would say track down where this #current_user instance variable is being set and find out why it is nil. Now, what kind of authentication are you using? Most authentication plugins, especially those used by Ryan Bates of the Railscasts you mentioned, use a local variable, say just current_user, as the means to access the currently signed in user. I know I do in all my code.
So, rewrite the line as
#review = current_user.reviews.create!(params[:review])
and see if that works. If it doesn't, change it back and then track down where this #current_user is being set. Chances are good it is being set in a before_filter :method_name at the beginning of your controller.
Calling create! (with exclamation mark) will throw an exception and thus abort your create action if saving fails. Check your log/development.log for these exceptions.
Use build instead of create and lose the exclamation mark.
def create
#review = #current_user.reviews.build(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end

Resources