rails - Devise - Handling - devise_error_messages

2020-01-23 10:05发布

in my user edit page, there is a line as follows:

<%= devise_error_messages! %>

The problem is this does not output errors the standard way that the rest of the app does:

<% flash.each do |key, value| %>
    <div class="flash <%= key %>"><%= value %></div>
<% end %>

My question is, how do I get the devise error message to work like the others that use the flash.each?

Thanks.

20条回答
干净又极端
2楼-- · 2020-01-23 11:00

If you are looking to piggyback off of devise_error_messages then you can so by adding to resource.errors

If you were to over ride the registration controller, it might look like

def create
  if validation_or_other_check_passes
    super
  else
    build_resource
    clean_up_passwords(resource)
    resource.errors.add(:notice, "The check failed.")
    render :new 
查看更多
Root(大扎)
3楼-- · 2020-01-23 11:01

I just created an app/helpers/devise_helper.rb like John but overrode the method like that :

module DeviseHelper
  def devise_error_messages!
    flash[:error] = resource.errors.full_messages.join('<br />')
    return ''
  end
end

With this I don't have to modify anything else. Is it a bad idea ? I'm new to rails, don't hesitate to correct me. Thanks.

查看更多
▲ chillily
4楼-- · 2020-01-23 11:02

If you want to be able to display more than one flash of a given type (:alert, :notice, etc...) and not waste your time trying to modify a gem behavior, this is the solution I used with Devise. I'm pretty sure it could be used with any gem that uses flash messages.

First thing to do, in your application_controller.rb, add this:

  # Adds the posibility to have more than one flash of a given type
  def flash_message(type, text)
    flash[type] ||= []
    flash[type] << text
  end

Second thing to do, displaying your flash messages with this in application.html.erb (or wherever you want):

   <div class="flashes">
      <% flash.each do |key, messages| %>
        <% messages = Array(messages) unless messages.is_a?(Array) %>
        <% messages.each do |message| %>
        <div class="alert alert-<%= key %>">
          <%= message %>
        </div>
        <% end %>
      <% end %>
    </div>

Third thing to do, whenever you want to add a flash message in any controller, do this:

flash_message(:success, "The user XYZ has been created successfully.")
查看更多
孤傲高冷的网名
5楼-- · 2020-01-23 11:02

Very easy way to display error message for each field

<%= resource.errors.messages[:email].join(" ") %>

put for each field with field name in square bracket below every line where u want to display inline error message.

查看更多
神经病院院长
6楼-- · 2020-01-23 11:05

To show your devise error from your controller with only the first error to showing up.

flash[:error] = @resource.errors.full_messages.first
查看更多
做个烂人
7楼-- · 2020-01-23 11:06

I know it's been a while since this question was posted, but I just wanted to comment on what I've found. The two people who've already answered have been a tremendous help to me and I just wanted to contribute.

You'll see throughout Devise that there are calls using render_with_scope. I believe this is a method defined by devise and basically applies the current scope to the next view rendered.

Why is this relevant? Devise contains your errors within resource.errors (not @resource.errors). Devise works fine if you want to use it out of the box, so to speak.

Problems with these errors arise if you start changing your user management behavior. By adding a redirect_to or render (instead of render_with_scope) where Devise previously didn't have one, you're basically tossing out the error messages. This makes Devise unfriendly to modification, in my opinion.

My solution is this

# In application.html.erb
<% flash.each do |name, msg| %>

  # New code (allow for flash elements to be arrays)
  <% if msg.class == Array %>
    <% msg.each do |message| %>
      <%= content_tag :div, message, :id => "flash_#{name}" %>
    <% end %>
  <% else %>

    # old code
    <%= content_tag :div, msg, :id => "flash_#{name}" %>

  <% end %> #don't forget the extra end
<% end %>

and

# Wherever you want Devise's error messages to be handled like 
# your other error messages
# (in my case, registrations_controller.rb, a custom controller)
flash[:notice] = flash[:notice].to_a.concat resource.errors.full_messages

The latter code block takes Devise's error messages as an array and appends it to flash[:notice] (as an array). Each message will be printed out one line at a time. If I have the time, I think I'm going to change how Devise handles error messages to do this throughout my app, as it seems much cleaner to have one error message system instead of two.

查看更多
登录 后发表回答