Rails: How to print error message with Ajax Jquery? - ruby-on-rails

Currently, this is the code I have for creating a new message:
if #message.save
respond_to do |format|
format.html { redirect_to messages_path }
format.js
end
else
flash[:notice] = "Message cannot be blank!"
redirect_to :back
end
How do I get the same message to print in Ajax? Would also like control to format it and position it.

In aplication controller
after_filter :add_flash_to_header
def add_flash_to_header
# only run this in case it's an Ajax request.
return unless request.xhr?
# add different flashes to header
response.headers['X-Flash-Error'] = flash[:error] unless flash[:error].blank?
response.headers['X-Flash-Warning'] = flash[:warning] unless flash[:warning].blank?
response.headers['X-Flash-Notice'] = flash[:notice] unless flash[:notice].blank?
response.headers['X-Flash-Message'] = flash[:message] unless flash[:message].blank?
# make sure flash does not appear on the next page
flash.discard
end
Move notifications code into partial:
<div class="noticesWrapper">
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert"><i class="icon-remove"></i></a>
<%= msg %>
</div>
<% end %>
</div>
In js.erb file:
$('.noticesWrapper').html("<%= j(render partial: 'layouts/flash_notices') %>");
In controller action you need to flash messages with flash.now:
flash.now[:error] = "your message"

Related

Ruby on Rails 7 + Turbo - Not showing notice message

I am learning Ruby on Rails. Rails 7 + Turbo stream... I am following a tutorial and I am having a problem with displaying the Notice message.
Can you help me understand why I am not getting notice message after I create a new quote?
Here is a create action in QoutesController.rb. Only when I put this line of code:
flash[:notice] = "Gets displayed with this line and a refresh... "
before the format.html line, then I will get the notice message after I refresh the page upon creating a quote. Only then the message gets displayed.
Can you please help me understand this?
(Yes, I am using a Devise gem here, Turbo stream, Turbo Rails, Rails 7)
Thank you
def create
#quote = current_company.quotes.build(quote_params)
if #quote.save
respond_to do |format|
flash[:notice] = "Gets displayed with this line and a refresh... " #weird
format.html { redirect_to quotes_path, notice: "Quote was successfully created." }
format.turbo_stream
#debugger
end
else
render :new, status: :unprocessable_entity
end
end
In Rails 7, unrefresh page when you create successfully. So, flash[:notice] not display.
Create views/shared
In share folder, we have _flash.html.erb, _notices.html.erb
_flash.html.erb
<div class="alert <%= bootstrap_class_for(msg_type) %> alert-dismissible fade show" role="alert">
<div class="container text-center">
<%= message %>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</div>
_notices.html.erb
<div id="flash">
<% flash.each do |msg_type, message| %>
<%= render partial: "shared/flash", locals: { msg_type: msg_type, message: message } %>
<% end %>
</div>
When you create success -> create views/qoutes/create.turbo_stream.erb
<%= turbo_stream.update "flash", partial: "shared/flash", locals: { msg_type: :notice, message: "your message" } %>
// msg_type: :notice, :alert, :error, :success
In views/layouts/application.html.erb
<%= render 'shared/notices' %>
<%= yield %>
In application_helper
module ApplicationHelper
def bootstrap_class_for(flash_type)
{
success: "alert-success",
error: "alert-danger",
alert: "alert-warning",
notice: "alert-info"
}.stringify_keys[flash_type.to_s] || flash_type.to_s
end
end
and if create failed
ex:
def create
if #object.save
// code
else
render_flash(:alert, full_messages(#post.errors.full_messages))
end
end
In application_controller
class ApplicationController < ActionController::Base
protected
def render_flash type, message
render turbo_stream: turbo_stream.update("flash", partial: "shared/flash", locals: { msg_type: type, message: message })
end
def full_messages messages
messages.join("\n")
end
end
=> This is my way. Hope to help you.

Allow user to complete form with a delay, error : undefined method `errors' for nil:NilClass

I try to allow user to fill the form with a delay between each user,
The delay is set to 100 between the last user registered in my database and the new one
Here is what I do in my controller :
class EmailsController < ApplicationController
def index
redirect_to root_path
end
def new
#email = Email.new
end
def create
if Time.now - Email.last.created_at < 100
respond_to do |format|
format.html{render :new, notice: "Wait !"}
end
else
respond_to do |format|
#email = Email.create(email_params)
if#email.persisted?
format.html {redirect_to invoice_index_path, notice: 'Email validated '}
else
format.html{render :new}
end
end
end
end
private
def email_params
params.require(:email).permit(:email, :id_user)
end
end
My view :
<div class="container">
<% if flash[:notice].present?%>
<center><p id="notice" class="alert alert-success"><%= flash[:notice] %></p></center>
<%end%>
<center><h1>Nouvelle Connection </h1></center>
<%= form_with model: #email, local: true do |form|%>
<% if #email.errors.any? %>
<div id="error explanation" class="alert alert-danger">
<p>Erreur(s) : </p>
<ul>
<% #email.errors.full_messages.each do |message|%>
<li><%=message%></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= label_tag :email %> :
<%= form.email_field :email, placeholder: "Insérez votre email", class: "form-control" %>
</div>
<div class="form-group">
<%= form.submit class: "btn btn-primary btn-lg btn-block", value: "Se connecter" %>
</div>
<%end%>
</div>
When I fill the form, nothing happen, just the url change from http://localhost:3000/ to http://localhost:3000/emails and when I re-click on Validate, it goes to http://localhost:3000/emails/53 with the error The action 'update' could not be found for EmailsController but I guess I have this error because I don't have any update/edit in my controller.
Do you know how to fix that to allow me a delay between each user ?
Edit : I now have the error undefined method errors for nil:NilClass in my view at the line <% if #email.errors.any? %>. I understand this is because my #email is nil but I tried to integrate this in my view :
<% if #email.nil?%>
<%= Wait for the moment %>
<%end%>
Also tried : <% if #email&.errors&.any? %> why so, I return to the URL : http://localhost:3000/emails
But still have the same error, do you know how to fix it ?
First off, in your view you check for notice.present? and that should be flash[:notice].present?. So then the error will be shown.
Secondly, in your controller you are actually first creating the email, and only then checking if it should be created, and then not even removing it? So the only result is that people will see a notice, but the email would still be created.
So instead do something like:
def create
if Time.now - Email.last.created_at < 100
respond_to do |format|
#email = Email.new(email_params)
format.html do
flash[:notice] = 'Wait! You cannot enter emails so quickly!'
render :new
end
end
else
respond_to do |format|
#email = Email.create(email_params)
if #email.persisted?
format.html {redirect_to invoice_index_path, notice: 'Email validé '}
else
format.html{render :new}
end
end
end
end
Secondly this does seem to mean that any user wanting to enter a new email, will be punished if another user has also entered another email. So in that case you might want to check as follows:
Email.where(created_by_id: current_user.id).last
to only check for Email 's the current user has entered (but maybe that is taking your problem/solution too far?).
Also note there are much better/efficient ways to throttle requests (rate limiting) using apache/nginx (which is probably how it will be deployed), so is this actually a good approach to handle in your ruby on rails code?

Rails 5 flash not working for redirect

I have created rails 5 application and I have the following code in controller and views for showing flash messages. I saw many question like this but I could not solve the problem.
controller side
respond_to do |format|
if #trigger.update(trigger_params)
flash[:success] = 'Trigger was successfully updated.'
format.html { redirect_to edit_project_trigger_path(#trigger, project_secret_key: #project.secret_key) }
format.json { render :show, status: :ok, location: #trigger }
else
error = ''
#trigger.errors.full_messages.each do |msg|
error += "#{msg} <br>"
end
flash.now[:error] = error
format.html { render :new }
format.json { render json: #trigger.errors, status: :unprocessable_entity }
end
end
view side
<% if flash[:error].present?%>
<div class="alert alert-danger alert-message alert-message-common" role="alert">
<%= flash[:error].html_safe %>
</div>
<% end %>
<% if flash[:notice].present? %>
<div class="alert alert-success alert-message alert-message-common" role="alert">
<%= flash[:notice].html_safe %>
</div>
<% end %>
<% if flash[:alert].present? %>
<div class="alert alert-danger alert-message alert-message-common" role="alert">
<%= flash[:alert].html_safe %>
</div>
<% end %>
<% if flash[:success].present?%>
<div class="alert alert-success alert-message alert-message-common" role="alert">
<%= flash[:success].html_safe %>
</div>
<% end %>
It's show when using alert but success messages are not shown. Is there any problem in rails 5 or any problem in my code ?
I hope alert working because of page render and success not working because of redirect.
Only alert and notice flash keys are supported by default.
To add success:
class ApplicationController
add_flash_types :successs
Reference: Ruby Guides
try this:
format.html { redirect_to edit_project_trigger_path(#trigger, project_secret_key: #project.secret_key), :success => 'Trigger was successfully updated.' }
This should work:
format.html { redirect_to edit_project_trigger_path(#trigger, project_secret_key: #project.secret_key), flash: {success: 'Trigger was successfully updated.'} }
For some reasons, in rails you should you either notice or alert keys in redirect_to method, but if you need success or something else, you should use nested hash in flash key.
Check here http://blog.remarkablelabs.com/2012/12/register-your-own-flash-types-rails-4-countdown-to-2013
The Rails docs for redirect_to mention that "There are two special accessors for the commonly used flash names alert and notice as well as a general purpose flash bucket." You need to use regular flash syntax for any others.

How to display a Rails flash notice upon redirect?

I have the following code in a Rails controller:
flash.now[:notice] = 'Successfully checked in'
redirect_to check_in_path
Then in the /check_in view:
<p id="notice"><%= notice %></p>
However, the notice does not show up. Works perfect if I don't redirect in the controller:
flash.now[:notice] = 'Successfully checked in'
render action: 'check_in'
I need a redirect though... not just a rendering of that action. Can I have a flash notice after redirecting?
Remove the .now. So just write:
flash[:notice] = 'Successfully checked in'
redirect_to check_in_path
The .now is specifically supposed to be used when you are just rendering and not redirecting. When redirecting, the .now is not to be used.
redirect_to new_user_session_path, alert: "Invalid email or password"
in place of :alert you can use :notice
to display
Or you can do it in one line.
redirect_to check_in_path, flash: {notice: "Successfully checked in"}
This will work too
redirect_to check_in_path, notice: 'Successfully checked in'
If you are using Bootstrap, this will display a nicely-formatted flash message on the page that's the target of your redirect.
In your controller:
if my_success_condition
flash[:success] = 'It worked!'
else
flash[:warning] = 'Something went wrong.'
end
redirect_to myroute_path
In your view:
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
This will produce HTML like:
<div class="alert alert-success">It worked!</div>
For available Bootstrap alert styles, see: http://getbootstrap.com/docs/4.0/components/alerts/
Reference: https://agilewarrior.wordpress.com/2014/04/26/how-to-add-a-flash-message-to-your-rails-page/
I had the same problem, and your question solved mine, because I had forgotten to include in the /check_in view:
<p id="notice"><%= notice %></p>
In the controller, just a single line:
redirect_to check_in_path, :notice => "Successfully checked in"

Flash messages in Rails 3.2.3 and json

There is an action in a controller. It can be called only with json format via ajax.
def update
#article = Article.find_by_id params[:id]
respond_to do |format|
if #article.update_attributes(params[:article])
flash[:message] = "good"
else
flash[:error] = #article.errors.full_messages.join(", ")
end
format.json { render :json => flash}
end
end
the part of a page
<% unless flash[:error].blank? %>
<%= flash[:error] %>
<% end %>
<% unless flash[:message].blank? %>
<%= flash[:notice] %>
<% end %>
<!-- page content goes -->
Of course, a page contains a button_to with :remote=>true that calls the method update.
The bottom line is that it shows nothing after updating. JSON object definitely returns, I can see it in fireBug.
The question is, am I using flash correctly? And how do I use it to show a message on a page? Please don't forget about ajax.
Why do you have an if/else statement in your respond_to block?
def update
#article = Article.find_by_id params[:id]
if #article.update_attributes(params[:article])
flash[:notice] = "Good"
else
flash.now[:notice] = "Bad"
render "edit"
end
respond_to do |format|
format.html {redirect_to #article}
format.js
end
end
Then create update.js.erb
$("#notice").text("<%= escape_javascript(flash[:notice]) %>")
$("#notice").show()
Code above might not be 100% correct.
For flash, I'd have something like:
<div id="notice">
<% flash.each do |key, value| %>
<%= content_tag(:div, value, :class => "flash #{key}") %>
<% end %>
</div>
This posting has all the code you'll need. It saved my hide:
https://gist.github.com/linjunpop/3410235
Here's a fork of it that makes a few minor modifications:
https://gist.github.com/timothythehuman/5506787
I think
You have to bind ajax:success call back which will display flash message by replacing message or placing message to dom.

Resources