I am totally new in ruby. My Ruby version 2.2. I have an edit profile form. I want to show both the table and form data in two different different place. Please check my code
users_controller.rb
def edit_profile
#user = User.get_profile(session[:user_id])
raise $user.inspect
respond_to do |format|
if params[:user][:avatar]
params[:user][:photo] = orginal_file_upload params[:user][:avatar]
end
raise params.inspect
if #user.update(user_params)
format.html { redirect_to :back, notice: 'Your profile was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :my_profile }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
Here I have define raise $user.inspect and raise params.inspect I want to get both data. But here in my page only coming first one. Please check and let me know how to get my both array value.
Thank you.
raise is a mechanism of throwing errors. raise $user.to_s returns the control out of action. You can use puts method to display the values in controller.
The correct code will be:
def edit_profile
#user = User.get_profile(session[:user_id])
respond_to do |format|
if params[:user][:avatar]
params[:user][:photo] = orginal_file_upload params[:user][:avatar]
end
#user.update(user_params)
format.html { render :inline => "User<p> ID:<%= #user.id %><br>NAME: <%= #user.name %><br>EMAIL: <%= #user.email %></p>Params <p><%= params.inspect%></p>".html_safe }
end
end
Assign them to instance variables like #user and #params and access them in your views. Having said that you already have assigned #user variable and params is accessible in your views automatically.
# In your view
<%= #user.name %>
<%= params %>
Also, consider making your controller RESTful. You can send PUT request to your controllers URL (eg. PUT profile/1) it will automatically call your ProfileController#edit method.
Related
I looked at a few different answers similar to this question, but they all are getting the id passed into the params hash, it is just coming back as a nil value. I cant seem to get the id to be whitelisted and I cant figure out why.
This is my create and show action, also includes the params. I explicitly whitelisted id although I dont know if it is necessary.
def show
#board = Board.find(params[:id])
end
def create
#board = Board.new(board_params)
if #board.save
# flash[:notice] = 'You successfully created your post!'
redirect_to board_path
else
render 'new'
# flash[:danger] = 'One or more errors occurred when processing your post'
end
end
private
def board_params
# params.require(:board).permit!
params.require(:board).permit(:id, :project_name, :project_description, :postition_title, :project_url, :project_headquarters, :application_process)
end
The output of my routes show action
board GET /boards/:id(.:format) boards#show
And the output of the params hash on board#create
Parameters: {"utf8"=>"✓", "authenticity_token"=>"k+KKRhBk4Dnba1vxtFCanI2grfhNXFSgJpfEBLnhPdablfOsXRi1wBehPpM1qgx1pySrqxVHTeiwkneluXwRIQ==", "board"=>{"project_name"=>"sdf", "postition_title"=>"sdf", "project_headquarters"=>"sdf", "project_url"=>"fsd", "project_description"=>"dfs", "application_process"=>"dfs"}, "commit"=>"Create Board"}
Can anyone see what I need to change in order to get the id passed in correctly?
Try this.
Take :id out of params.
def show
end
def create
#board = Board.new(board_params)
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render :show, status: :created, location: #board }
else
format.html { render :new }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
in create action...
change ..
redirect_to board_path
to...
redirect_to board_path(#board)
###OR
### this calls the show action
redirect_to #board
I am using this 3rd party controller:
class LibController
def update
# 29 lines of code
respond_with resource
end
end
I want to do something other than the respond_with at the end. But I don't want to just copy/paste all 29 lines into MyController.update. Unfortunately I can't figure out a way to render or redirect anywhere else:
class MyController < LibController
def update
super
redirect_to somewhere_else
end
end
I get a DoubleRenderError: Render and/or redirect were called multiple times in this action. I assume this is because respond_with calls render immediately. Is there a way to block/prevent that?
Thanks!
I think you are doing a twice redirection.
Try to remove one redirection on your update method.
Check sample code below that shows equivalent response when using respond_with.
def create
#user = User.new(params[:user])
flash[:notice] = 'User was successfully created.' if #user.save
respond_with(#user)
end
Which is exactly the same as:
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to(#user) }
format.xml { render xml: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.xml { render xml: #user.errors, status: :unprocessable_entity }
end
end
end
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
I want to present users with separate pages/dialogs for editing their own information. However, the information is held in a single model (called User). Now I'm trying to find the best approach for handling the update calls from partials. My code currently:
def edit
render :layout=>!request.xhr?
end
def edit_password
render :layout=>!request.xhr?
end
def edit_extra
unless #user.extra
#user.build_extra
#user.extra.value = 2047
end
render :layout=>!request.xhr?
end
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, :notice => 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit", :layout=>!request.xhr? }
end
end
end
The thing is, all forms in methods (edit, edit_password and edit_extra) call the update method. However, there are two problems:
If the data parsing isn't validated, user is presented with the "edit" form, which is incorrect.
I want to have a password confirmation on extra data. User shouldn't be able to edit that information unless they supply a correct password.
I would like to make more generalized solution than just duplicating the update -code. The largest problem is rendering correct layout (edit, edit_password) based on the current action.
For now, I solved the problem by creating separate edit_section parameter that will be handled in update.
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, :notice => (t :actionsuccesful) }
format.json { head :no_content }
else
action = if params[:edit_section] then "edit_" + params[:edit_section] else "edit" end
format.html { render :action => action, :layout=>!request.xhr? }
end
end
end
And in forms (edit_password, etc)
=form_for(#user, :remote => true) do |f|
= hidden_field_tag :edit_section, "password"
I have a very common HABTM relationship between Product and Category. I'm based on Railscasts Episode #17. The problem I'm facing is related to the way all the categories are fetched to show them in the product form (this is the way R. Bates has the view for it):
<% for category in Category.find(:all) %>
<div>
<%= check_box_tag "product[category_ids][]", category.id, #product.categories.include?(category) %>
<%= category.name %>
</div>
<% end %>
but I want to implement it this way:
<% for category in #categories %>
where I have #categoriesdefined in my controller:
def edit
#categories = Categories.all
#product = Product.find params[:id]
end
It all goes smoothly until some validation fails. Say some field can't be blank and so the redirection (on the update action of the ProductsController) shoot's me back to edit:
def update
#product = Product.find(params[:id])
#supplier.category_ids = params[:product][:industry_category_ids] ||= []
respond_to do |format|
if #product.update_attributes(params[:product])
format.html { redirect_to #supplier, notice: 'Profile was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" } <=== HERE
format.json { render json: #supplier.errors, status: :unprocessable_entity }
end
end
end
An that point I get the following error, saying that #categories in the correponding form is nil:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
...
<% for ic in #industry_categories %> <==== HERE
...
So, is there a way to keep the MVC best practices to accomplish this? Or I just have to do it Bate's way?
In other words, is is possible to have a form_for say #product with checkboxes for the "HABTM" related objects and be redirected to it after validation fails BUT without fetching the stuff on the view (Category.all) (i.e. doing it on the corresponding controller #categories = Category.all as I showed before)
Thanks!
Populate #categories when you fail your validation:
def update
#product = Product.find(params[:id])
#supplier.category_ids = params[:product][:industry_category_ids] ||= []
respond_to do |format|
if #product.update_attributes(params[:product])
format.html { redirect_to #supplier, notice: 'Profile was successfully updated.' }
format.json { head :ok }
else
#categories = Categories.all <--- HERE
format.html { render action: "edit" }
format.json { render json: #supplier.errors, status: :unprocessable_entity }
end
end
end
When you make a call to "render :action", Rails just continues processing the current request and renders the view mapping to the :action you specified. So in this case, you're re-rendering the 'edit' view (because you failed your validation) but since there's no #categories variable declared in the 'update' action you will get a nil reference exception.