I have a website that degrades gracefully for users without javascript. For a user without javascript, the controller will respond to a form submit with HTML. For a user with javascript, there will be an AJAX form submit. This is in the create method in the controller:
if !#goal.save
flash[:error] = array_to_list(#goal.errors.full_messages)
else
flash[:success] = "Your goal was successfully added."
end
respond_to do |format|
format.html { redirect_to :action => "show"}
format.js
end
I don't want to put those messages into flash if the user has javascript enabled, because then it will display after the user has already dealt with it. Is there any way to tell Rails to display a flash message only if responding with html?
You can put the flash bits of the code into your format.html block in order to achieve this.
Maybe something like this:
#goal.save
respond_to do |format|
format.html do
if #goal.errors
flash[:error] = array_to_list(#goal.errors.full_messages)
else
flash[:notice] = "Your goal was successfully added."
end
redirect_to :action => "show"
end
format.js
end
Have you thought about that you might want to have some kind of error message with the AJAX request as well? It might be a good idea if your AJAX request breaks by some reason so that stuff doesn't get saved.
Related
When there was an error on updating my model, I was rendering :edit, but this was stripping the /edit from my url because #update is the same as #show with a different request method. To solve this I tried following the advice given here, but this caused me to get an ActionDispatch::Cookies::CookieOverflow error when I try to submit an invalid form. How should I correctly re render the edit page, while keeping both the /edit url and the flash messages? Is it possible to check for validity and show the errors without making a call to update?
Original code:
def edit
end
def update
respond_to do |format|
format.html do
if #model.update(model_params)
redirect_to home_base_url_or_default(model_url(#model)), notice: "Successfully updated."
else
render :edit
end
end
end
end
Failing code:
def edit
if flash[:model]
#model = flash[:model]
end
end
def update
respond_to do |format|
format.html do
if #model.update(model_params)
redirect_to home_base_url_or_default(model_url(#model)), notice: "Successfully updated."
else
flash[:model] = #model
redirect_to :action => :edit
end
end
end
end
Rather than doing a redirect, in this case the problem was solved by doing a render, then controlling the view by setting an instance var in the controller saying if it is the edit page or not. Also by using the update class in the CSS. However, this still has the the url for the show page, but at least the layout is correct.
One way to do it would be to allow the edit action to accept the POST method as well. Use request.method to check whether it is a POST or GET, then perform your render or redirect accordingly.
I have a Ruby on Rails 3.2 app with an action that redirects from a CSV request to an HTML request, but the flash[:notice] is not available after the redirect.
The first action looks like this:
def first_action
respond_to do |format|
format.html do
redirect_to other_action_controller_url, notice: "This message will be displayed."
end
format.csv do
redirect_to other_action_controller_url, notice: "The message will NOT be displayed."
end
end
end
So if you request /controller/first_action.csv it redirects to /controller/other_action but the flash messages do NOT appear. On the other hand, if you request /controller/first_action it redirects to /controller/other_action and the flash messages work.
So how can one redirect from one format to another and pass a message into the flash successfully?
Try appending the flash message as below:
def first_action
respond_to do |format|
format.html
format.csv do
flash[:notice] = "The CSV is not available."
redirect_to other_action_controller_url
end
end
end
Flash message will persist for one redirect action only. after that, it will go off.
Hope it helps :)
I feel somewhat stupid about this one, but:
if #prof.update_attributes(params[:profile])
respond_to do |format|
format.html {redirect_to(#prof, :notice => "Profile successfully created.") }
end
end
...is in the update method of my controller. I have some attributes being validated in the model.
If validation fails, I just want them back on the same form to be scolded by various red text. (ie. everything in the errors array).
I'm getting a 'template missing' error when validation fails - the template for 'update'. I feel like I'm overlooking something extremely simple. Help!
Try this:
respond_to do |format|
if #prof.update_attributes(params[:profile])
format.html { redirect_to(#prof, :notice => "Profile successfully created.") }
else
format.html { render action: 'edit' }
end
end
The cause of the error is due to the fact that Rails, unless told otherwise, will attempt to render a template with the same name as the action, in this case update, which obviously doesn't exist.
What you want to do is tell rails to render the edit action again in the event of an error. Typically, you would do this with the respond_to block, allowing the block to respond differently depending on whether validation passed or failed.
At present, you have your if statement wrapping the block, and no statements telling rails to render differently in the event of an error. To fix this, I would do the following:
respond_to do |format|
if #prof.update_attributes(params[:profile])
# all is well, redirect as you already wrote
else
format.html { render action: 'edit' }
end
end
I'm new to rails and am using this great guide to create a simple contact form in a new app: contact-form-in-rails-3
Everything works but the app I'm building will have a live stream with a contact form for people to submit questions as they watch. The issue is that when I send a message at present, I am redirected to the root_path. It is necessary that the app does not redirect or reload the page and that the flash appears in a similar fashion to the validation flash. I understand why this is happening, from the controller below:
Class ContactController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
However, when I try to change the redirect line to something such as:
flash[:notice] = "Message was successfully sent."
The form ceases to submit.
Any advice would be greatly appreciated.
Thanks
you need to ad ajax to you form, here is an example of how to add this functionality:
http://stjhimy.com/posts/07-creating-a-100-ajax-crud-using-rails-3-and-unobtrusive-javascript
Or just render the same page, with the given information and the notice message.
What you can do when the redirect occur when you send an ajax is this:
In your controller:
respond_to do |format|
format.js { head :no_content }
format.html { head :no_content}
end
In your ajax:
So basically, event.preventDefault() will inhibit the button to act normally and shouldn't reload the page.
$('#selector').click(function(event){
event.preventDefault();
//Do whatever you want
});
I would like to do a conditional update in ruby on rails 3.1
Where based on the location you came from, after update, an redirect will be done.
Splitted my 1 big form in to separate smaller ones, so now the Idea is to redirect to the correct subform.
For example the form can be submitted from:
profile basics form
Profile details form
The only thing I could come up with is checking the action name and use that to redirect. But its very ugly and long code and not fully working either. What would be the railsway of doing this?
This is my controller update action:
def update
#profile = Profile.find(params[:id])
respond_to do |format|
if #profile.update_attributes(params[:profile])
format.html { redirect_to #profile, notice: 'Profile was successfully updated.' }
else
format.html {
render :action => "edit_basics"
#
}
end
end
end
Why not just pass the redirect location as a hidden_field in the form, then have each form set it as needed:
redirect_to params[:redirect_location]
You could also do this using steps or something if you don't want to expose the raw string in your HTML:
redirect_to location_for_step(params[:step])