flash_timedout = "true" when user session expires in rails using devise - ruby-on-rails-3

My code for session time out is as follows:
In sessions_controller:
prepend_before_filter { request.env["devise.skip_timeout"] = true }
In user model:
devise :timeoutable, :timeout_in => 2.minutes
application.html.erb:
<%=content_tag :div, msg, :class =>"flash_#{key}", :id => "app_flash"%>
If my session expires, i am getting an error "Your session has expired..." from devise errors which is fine.
But i am getting extra error outside the form as "true" where i inspect it as [:flash_timedout].
Please help me how to disable this true [:flash_timedout] ?

That is a known issue. You must only display :notice and :alert messages or remove the :timedout key from the flash hash as stated in the Devise documentation.
See https://github.com/plataformatec/devise#configuring-controllers

I was able to disable [:flash_timedout] "true" and provide customized error.
I wrote below steps in my message partial:
<% if flash[:timedout] && flash[:alert] %>
<% flash.keep(:timedout) %>
<% flash.keep(:alert) %>
<div class = "alert alert-danger">
Your session expired. Please sign in again to continue.
</div>
<% else %>
<% flash.each do |name, message| %>
<div class = "alert alert-<%= message.include?('Invalid') ? 'danger' : 'success'%>">
<ul>
<%= message %>
</ul>
</div>
<% end %>
<% end %>

Related

The error message when trying to login from devise is not showing in a Rails 7.0 application

I have a rails 7.0 application, in my application.html.erb
<body>
<%= yield %>
<div class="signin-container">
<div class="signin-container-inner">
<%- flash.each do |name, msg| -%>
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
<%- end -%>
</div>
</div>
</body>
When I visit signin page and add some wrong email or password the error message is not showing.
Since Ruby on Rails 7 uses :turbo_stream, we need to make some modifications to get what you need.
First, we let's add a new parent controller for Devise:
# frozen_string_literal: true
# app/controllers/turbo_devise_controller.rb
class TurboDeviseController < ApplicationController
class Responder < ActionController::Responder
def to_turbo_stream
controller.render(options.merge(formats: :html))
rescue ActionView::MissingTemplate => e
if get?
raise e
elsif has_errors? && default_action
render rendering_options.merge(formats: :html, status: :unprocessable_entity)
else
redirect_to navigation_location
end
end
end
self.responder = Responder
respond_to :html, :turbo_stream
end
Second, we also need to tell Devise to use our new controller and also add a class to handle our errors:
# frozen_string_literal: true
# app/config/initializers/devise.rb
# ! Create custom failure for turbo
class TurboFailureApp < Devise::FailureApp
def respond
if request_format == :turbo_stream
redirect
else
super
end
end
def skip_format?
%w(html turbo_stream */*).include? request_format.to_s
end
end
Devise.setup do |config|
...
config.parent_controller = 'TurboDeviseController'
config.navigational_formats = ['*/*', :html, :turbo_stream]
config.warden do |manager|
manager.failure_app = TurboFailureApp
end
...
end
That's it.
More information about it: GoRails - How to use Devise with Hotwire & Turbo.js
Here is a workaround this issue that occurs when using Rails 7, Hotwire, Turbo, and Devise together. By passing data:{turbo: false} along with each Devise form, it can prevent Turbo from conflicting with the Devise authentication process. This should allow Devise to function properly while still using Hotwire and Turbo in your Rails application.
Here is an example of how you might use data:{turbo: false} on a Devise form:
<%= form_for(resource, as: resource_name, url: session_path(resource_name), data: {turbo: false}) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, autofocus: true %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Log in" %>
<% end %>
In this example, the data: {turbo: false} is being passed as an option to the form_for helper method. This tells Turbo to not apply any of its features to this form, which should prevent any conflicts with Devise's authentication process.

undefined method `model_name' for Mailer - Rails 5

I am trying to make a contact me form in Rials 5 with the built in Mail features.
I put it together a lot like a regular controller and views with a Mailer as the model. But when I have it all written out I get the error:
undefined method `model_name' for #ContactMailer
Contact is the name of the Mailer.
The error comes up when I try to view the new.html.erb page with rails server running. It looks like this:
Screen Shot
Here is the code I am working with:
contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = ContactMailer.new
end
def create
#contact = ContactMailer.new(params[:name, :email, :message])
if #contact.deliver
flash[:success] = "Your message has been sent."
else
flash[:error] = "There was a problem sending your message."
render 'new'
end
end
And
new.html.erb
<%= form_for #contact do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control', required: true %></div>
<div class="form-group">
<%= f.label :message %>
<%= f.text_area :message, class: 'form-control' %>
</div>
<%= f.submit "Send", class: 'btn btn-default' %>
<% end %>
There is also the generated Mailer and views, but I have not changed anything with those.
From what I have been able to research the error could be that I have not initialized the #contact variable, but I believe that I have. And now I am lost. Any help would be appreciated.
As additional information:
My plan is for this contact form to send an email using send grid on Heroku.
You are trying to build a mailer.Thats not how they are used. They are not models.
Instead you would do something like:
ContactMailer.some_method_you_added_to_your_mailer(params[:name, :email, :message]).deliver_now
You don't use new on them.
Suggest you read over http://guides.rubyonrails.org/action_mailer_basics.html .

Simple_Form and Bootstrap 3 Form Validation Notification Stopped Working

I'm still learning RoR and have followed various tutorials online. In that process I believe I have messed up the nice flash notifications that Bootstrap 2 showed when validating Simple_Form submissions. I have tried to update my code, but without success. Here is what I have so far...
Running:
Rails 3.2.13
Ruby 2.0.0
I just upgraded to Bootstrap 3 using this gem in my gemfile:
gem 'bootstrap-sass-rails'
In my application.html.erb I have:
<%= render 'layouts/messages' %>
In my _messages partial I have:
<% flash.each do |type, message| %>
<div class="alert <%= bootstrap_class_for(type) %> fade in">
<button class="close" data-dismiss="alert">×</button>
<%= message %>
</div>
<% end %>
In my application_helper.rb I have:
def bootstrap_class_for flash_type
case flash_type
when :success
"alert-success"
when :error
"alert-error"
when :alert
"alert-block"
when :notice
"alert-info"
else
flash_type.to_s
end
end
In my users_controller.rb I have:
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'Account successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
And in my edit.html.erb view I have:
<%= simple_form_for(#user) do |f| %>
<%= f.input :firstname %>
<%= f.input :lastname %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
<%= f.submit "Save changes", class: "btn btn-lg btn-primary" %>
<% end %>
The validation works, but when returned to the edit view, no formatting (red for errors) or flash message appears. Only a very hard to spot message outside each field is displayed. I must be missing some link between Simple_Form and Bootstrap 3, just don't know what.
I found another post where poster suggested to add:
config.input_class = "form-control"
to my simple_form initializer, but that gave me an error (think I might not have the latest version?):
undefined method `input_class=' for SimpleForm:Module (NoMethodError)
I wish I knew what was going on but I really hope someone can help me get the formatting and flash messages back. Apologies if this is a total newbie question, but I feel a little lost and possibly regretting that I upgraded too soon to Bootstrap 3 maybe.
A thousand thanks in advance to anyone reading all this :)
I got the following mix of code from railscasts.com and other websites.
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert">×</a>
<%= msg %>
</div>
<% end %>
Add this to the top of your controller:
respond_to :html, :json
Put this in each controller action:
def create
...
flash[:notice] = 'User was successfully created.'
respond_with(#user)
end
works with rails 3.2+ and 4.0 and twitter bootstrap rails 2, untested in tbsr 3 but will probably work fine.
This worked for me far much better than others as it;s shorter and includes all alert cases -> error, success, alert & notice provided by Bootstrap.
N.B: I renamed your _messages partial to _flash_messages because that is what most people use.
And for those who may be wondering where to generate the _flash_messages partial, it's pretty easy, just right-click your layouts folder in views and 'add new file'. You can call it _flash_messages as I've done, and ensure you have that first underscore (_) before 'flash...'. Tap 'Save'
Now in your _flash_messages.html.erb partial, use this
<% unless flash.blank? %>
<% flash.each do |type, message| %>
<div class="alert <%= flash_class(type.to_s) %>">
<button class="close" data-dismiss="alert">x</button>
<%= message %>
</div>
<% end %>
<% end %>
And in your application_helper.rb use this
def flash_class (type)
case type
when 'error'
"alert-error"
when 'notice'
"alert-info"
when 'alert'
"alert-block"
when 'success'
"alert-success
else
type.to_s
end
end
Then in your application.html.erb, add this as your first line in your first div
<%= render partial: 'layouts/flash_messages', flash: flash %>
Notice that we render the partial (any partial that is), without the 'starter' underscore(_), i.e before the word 'flash..'
You can check out this answer from teamtreehouse on displaying different alert cases.
Hope this helps!

authentication, cant go through login page

im trying create backend under password from database and i cant go through login page :P
My AdminController
class Backend::AdminController < ApplicationController
layout :layout
before_filter :authorize, :except => :login
def authorize
if session[:backend] != true
redirect_to backend_login_path
end
end
private
def layout
if session[:backend] == true
"admin"
else
"login"
end
end
def login
employee = Employee.authenticate(params[:name], params[:password])
if employee
session[:backend] = true
redirect_to backend_root_path, :notice => "Logged in!"
else
flash.now.alert = "Invalid login"
end
end
def logout
session[:backend] = nil
redirect_to backend_login_path, :notice => "Logged out!"
end
end
My Routes
match "backend/login" => "backend/admin#login"
match "backend/logout" => "backend/admin#logout"
My Login page
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>
<h1>Log in</h1>
<%= form_tag backend_login_path do %>
<p>
<%= label_tag :name %><br />
<%= text_field_tag :name, params[:name] %>
</p>
<p>
<%= label_tag :password %><br />
<%= password_field_tag :password %>
</p>
<p class="button"><%= submit_tag "Log in" %></p>
<% end %>
when i go on url /backend im redirected to /backend/login, thats right
when i enter good login or bad login nothing happened and NO flashes appears thats strange ?
from webserver console output, i see the POST informations go through login method.. i dont know what is wrong ? thank you
edit: when i try go to URL /backend/logout im getting
Unknown action
The action 'logout' could not be found for Backend::AdminController
i really dont understand this :( im begginer
one of the conventions in rails is, that public methods in a controller are considered to be actions.
if you want to write methods for before_filter etc, make them private or protected so that rails will not expose them as actions.
on the flipside, you are not able to define actions as private.

Interaction between controllers

On my web app I have a login page which is in the Pages Controller called welcome.html.erb
Inside it has a simple form for login and a simple for for sign up, both on the same page.
If the user signs up with wrong credentials (like password confirmation wrong, or length of password and etc) the controller that handles this is the new method in the Users Controller.
Inside the new method it checks if a user is created, and if not I'd like it to return to the welcome method in Pages Controller, passing to it the errors that were created during the user's creation.
It seems that if I do a
redirect_to root_path
The error count of the signup is reset when returning to the root page. If instead I call some other action of the users controller I do see the errors.
But since all of the html code is in the welcome view I don't want to replicate the code in the users controller views as well..
Is there a way to pass that errors data to the pages controller?
The partial for the error is
<% if object.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(object.errors.count, "error") %> prohibited this <%= object.class.to_s.underscore.humanize.downcase %> from being saved:</h2>
<p>There were problems with the following fields:</p>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Which I call using
<%= render 'shared/error_messages', :object => f.object %>
redirect_to welcome_path
(Or whatever the actual path is.)
From the Users controller I called
flash[:errors]=#user.errors
and then I changed the partial to be
<% if object.any? %>
<div id="error_explanation">
<h2><%= pluralize(object.count, "error") %> prohibited this <%= object.class.to_s.underscore.humanize.downcase %> from being saved:</h2>
<p>There were problems with the following fields:</p>
<ul>
<% object.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Which I called using
<%= render 'shared/error_messages', :object =>#user_errors %>
That solved the issue for now..