ราง - ประดิษฐ์ - การจัดการ - devise_error_messages


125

ในหน้าแก้ไขผู้ใช้ของฉันมีบรรทัดดังนี้:

<%= devise_error_messages! %>

ปัญหาคือสิ่งนี้ไม่ได้แสดงข้อผิดพลาดตามวิธีมาตรฐานที่แอปอื่น ๆ ทำ:

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

คำถามของฉันคือฉันจะทำให้ข้อความแสดงข้อผิดพลาดของอุปกรณ์ทำงานเหมือนกับคนอื่น ๆ ที่ใช้แฟลชได้อย่างไรแต่ละ?

ขอบคุณ


1
โปรดทราบว่า Devise ใช้แฟลชอยู่แล้วในขณะที่แอปอื่น ๆ กำลังทำอยู่ devise_error_messages ไม่เกี่ยวกับข้อความแฟลช (ข้อมูลจากหน้าสุดท้าย) แต่เป็นข้อผิดพลาดในการตรวจสอบความถูกต้องจากคู่มือ
Christopher Oezbek

คำตอบ:


135

ฉันพยายามคิดออกด้วยตัวเอง ฉันเพิ่งพบปัญหานี้เมื่อเข้าสู่ระบบ Github https://github.com/plataformatec/devise/issues/issue/504/#comment_574788

Jose กำลังบอกว่าdevise_error_messsages!วิธีการนั้นเป็นเพียงส่วนท้าย (แม้ว่าจะมีการนำไปใช้งาน) และเราควรจะลบล้าง / แทนที่ คงจะดีไม่น้อยหากสิ่งนี้ถูกชี้ให้เห็นที่ไหนสักแห่งใน wiki ซึ่งเป็นเหตุผลว่าทำไมฉันเดาว่ามีคนไม่กี่คนที่เหมือนเราที่เดาได้

ดังนั้นฉันจะลองเปิดโมดูลใหม่และกำหนดวิธีการใหม่โดยลบล้างการใช้งานเริ่มต้นอย่างมีประสิทธิภาพ ฉันจะแจ้งให้คุณทราบว่ามันเป็นอย่างไร

ปรับปรุง

ใช่มันได้ผล ฉันสร้างapp/helpers/devise_helper.rbและลบล้างมันดังนี้:

module DeviseHelper
  def devise_error_messages!
    'KABOOM!'
  end
end

เมื่อรู้สิ่งนี้ฉันจึงสามารถปรับเปลี่ยนวิธีการแสดงข้อความแสดงข้อผิดพลาดในแบบที่ฉันต้องการได้

เพื่อช่วยให้คุณแก้ปัญหาเดิมของคุณ: นี่คือต้นฉบับdevise_helper.rbบน Github ดูว่าข้อความแสดงข้อผิดพลาดถูกส่งผ่านอย่างไร:

messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join

ซึ่งจะช่วยให้คุณเริ่มต้นได้ :)

การอัปเดตอื่น

resourceวัตถุเป็นจริงรูปแบบที่จะถูกใช้โดยประดิษฐ์ (ตัวเลขไป)

resource.class         #=> User
resource.errors.class  #=> ActiveModel::Error

ดูเหมือนว่าจะกำหนดไว้ในขอบเขตที่สูงขึ้น (อาจมาจากคอนโทรลเลอร์) ดังนั้นจึงสามารถเข้าถึงได้ในหลาย ๆ ที่

ทุกที่ในตัวช่วยของคุณ

module DeviseHelper
  def devise_error_messages1!
    resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
  end

  def devise_error_messages2!
    resource.errors.full_messages.map { |msg| content_tag(:p, msg) }.join
  end
end

มุมมองของคุณ

<div><%= resource.errors.inspect %></div>

ฉันเพิ่งลองสิ่งนี้ แต่ไม่ได้ผล เป้าหมายคือการรับข้อผิดพลาดเพื่อส่งออกที่นี่: <% flash แต่ละ do | key, value | %>
AnApprentice

@ColdTree ไม่เป้าหมายคือให้มันทำงานเหมือนข้อความแฟลช ความสามารถในการควบคุมมาร์กอัปเป็นทางออกที่ดี
Benjamin Atkin

... ฉันไม่คิดว่าสิ่งนี้จะตอบคำถามแม้ว่าจะเป็นงานวิจัยที่ดีก็ตาม
deivid

37

โซลูชันด้านล่างทำงานร่วมกับอุปกรณ์ล่าสุด ณ ตอนนี้ (4.1.1) และ Rails 4.2.6 แต่มันง่ายมากจนฉันไม่เห็นเหตุผลว่าทำไมมันถึงใช้ไม่ได้อีก 10 ปีนับจากนี้;)

หากคุณต้องการรีไซเคิลข้อความแสดงข้อผิดพลาดของคุณและทำให้ดูเหมือนกันในแอปของคุณฉันขอแนะนำสิ่งนี้ (วิธีที่ฉันได้เรียนรู้กับ Michael Hartl tut):

สร้างบางส่วนสำหรับข้อความแสดงข้อผิดพลาด: layouts/_error_messages.html.erb ใส่รหัสต่อไปนี้ (ที่นี่ฉันใช้คลาส bootstrap 3 บางส่วน):

<% if object.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-danger alert-dismissable">
      <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
      <p><strong>This form contains <%= pluralize(object.errors.count, 'error') %>.</strong></p>
      <ul>
        <% object.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  </div>
<% end %>

ตอนนี้คุณมีสิ่งที่สามารถรีไซเคิลได้และคุณสามารถใช้มันได้ทั่วทั้งกระดาน แทนที่จะเป็นอุปกรณ์มาตรฐาน:

<%= devise_error_messages! %>

เรียกมันในรูปแบบของคุณดังนี้:

<%= render 'layouts/error_messages', object: resource %>

คุณสามารถวางไว้ในรูปแบบใดก็ได้ แทนที่จะส่งทรัพยากรประดิษฐ์คุณสามารถส่งตัวแปรจากแบบฟอร์มของคุณได้ดังนี้:

<%= form_for @post do |f| %>
  <%= render 'layouts/error_messages', object: f.object %>  
  <%= f.text_field :content %>
  <%= f.submit %>
<% end %>

1
อาจเป็นคำตอบที่ดีที่สุดและเข้าใจง่ายที่สุดเท่าที่เคยมีมา
วิกเตอร์

2
น้ำยาเด็ด. พหูพจน์ (object.errors.count, 'error' ควรเปลี่ยนเป็นพหูพจน์ (object.errors.count, 'error' แม้ว่า
mizurnix

1
@LukaszMuzyka ในโซลูชันนี้ .. ฉันจำเป็นต้องลบ: validatable จาก user.rb .. ???
Vishal

1
@ วิชาล - ไม่. วิธีแก้ปัญหาข้างต้นใช้ HTML ที่แตกต่างกันเพื่อแสดงข้อความที่ไม่เปลี่ยนแปลงกลไกใด ๆ ของ Devise
Lukasz Muzyka

1
@Vishal เมื่อคุณใช้อุปกรณ์มันกำลังทำการตรวจสอบความถูกต้องที่คุณได้กล่าวถึงโดยไม่มีรหัสเพิ่มเติมใด ๆ วิธีแก้ปัญหาข้างต้นเป็นเพียงการลบล้างพฤติกรรมการประดิษฐ์เริ่มต้นเท่านั้น คุณต้องมีการวางแผนการทำงานตั้งแต่แรก คุณแน่ใจหรือไม่ว่าคุณได้ทำตามคำแนะนำในการรวมอุปกรณ์เข้ากับโครงการของคุณแล้ว?
Lukasz Muzyka

22

ฉันรู้ว่ามันผ่านมาสักพักแล้วที่คำถามนี้ถูกโพสต์ แต่ฉันแค่อยากจะแสดงความคิดเห็นในสิ่งที่ฉันพบ สองคนที่ตอบไปแล้วเป็นความช่วยเหลืออย่างมากสำหรับฉันและฉันแค่อยากจะมีส่วนร่วม

คุณจะเห็นตลอด Devise ว่ามีการโทรโดยใช้ render_with_scopeคุณจะเห็นตลอดประดิษฐ์ที่มีสายใช้ฉันเชื่อว่านี่เป็นวิธีการที่กำหนดโดยประดิษฐ์และโดยพื้นฐานแล้วจะใช้ขอบเขตปัจจุบันกับมุมมองถัดไปที่แสดงผล

เหตุใดจึงเกี่ยวข้อง ประดิษฐ์มีข้อผิดพลาดของคุณภายในresource.errors( ไม่ @resource.errors ) Devise ใช้งานได้ดีหากคุณต้องการใช้งานนอกกรอบเพื่อที่จะพูด

ปัญหาเกี่ยวกับข้อผิดพลาดเหล่านี้เกิดขึ้นหากคุณเริ่มเปลี่ยนพฤติกรรมการจัดการผู้ใช้ โดยการเพิ่มredirect_toหรือrender(แทนrender_with_scope ) โดยที่ก่อนหน้านี้ Devise ไม่มีเลยคุณจะต้องทิ้งข้อความแสดงข้อผิดพลาดโดยทั่วไป สิ่งนี้ทำให้ Devise ไม่เป็นมิตรกับการดัดแปลงในความคิดของฉัน

ทางออกของฉันคือสิ่งนี้

# 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 %>

และ

# 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

บล็อกโค้ดหลังรับข้อความแสดงข้อผิดพลาดของ Devise เป็นอาร์เรย์และต่อท้ายflash[:notice](เป็นอาร์เรย์) แต่ละข้อความจะพิมพ์ออกมาทีละบรรทัด ถ้าฉันมีเวลาฉันคิดว่าฉันจะเปลี่ยนวิธีที่ Devise จัดการกับข้อความแสดงข้อผิดพลาดเพื่อทำสิ่งนี้ในแอปของฉันเพราะดูเหมือนว่าจะมีระบบข้อความแสดงข้อผิดพลาดเดียวแทนที่จะเป็นสองระบบ


3
ขอบคุณมากสำหรับสิ่งนั้นฉันกำลังเอาหัวโขกกับกำแพงเพื่อพยายามทำอย่างนั้น
Lucas

1
ตอนนี้เป็นเวลา 5 ปีต่อมาและคำตอบนี้ช่วยประหยัดเบคอนของฉัน ขอบคุณมาก @ eric-hu
marcamillion

12

ฉันแก้ไขสิ่งนี้ในทำนองเดียวกันกับ YoyoS โดยการสร้างapp/helpers/devise_helper.rbและวางสิ่งนี้ไว้ในนั้น:

module DeviseHelper

  # Hacky way to translate devise error messages into devise flash error messages
  def devise_error_messages!
    if resource.errors.full_messages.any?
        flash.now[:error] = resource.errors.full_messages.join(' & ')
    end
    return ''
  end
end

ทำงาน!


11

ฉันแค่ต้องการนำชิ้นส่วนใหม่มาที่นี่:

ฉันจึงพบวิธีที่ง่ายกว่าเพื่อให้ได้ผลลัพธ์ที่ "AnApprentice" ต้องการ

ก่อนอื่นหากคุณต้องการปรับแต่งอะไรภายในปลั๊กอิน Devise ฉันขอแนะนำให้คุณคัดลอกโค้ดจาก "\ Ruby_repertory \ lib \ ruby ​​\ gems \ 1.9.1 \ gems \ devise-version \ app \ controllers | ผู้ช่วย | จดหมาย ... "ไปยังไฟล์ที่คุณต้องการในโครงการของคุณ

[แก้ไข] หรือคุณสามารถทำให้ไฟล์ของคุณสืบทอดจากไฟล์ "ปกติ" ได้ ... เช่น ... พูดว่า ... คุณต้องการเขียนทับฟังก์ชันเดียวเท่านั้นภายในอุปกรณ์ / registers_controller.rb ซึ่งเป็นบรรทัดแรกของผู้ใช้ของคุณที่กำหนดเอง ตัวควบคุมการลงทะเบียนจะเป็น:

class Users::RegistrationsController < Devise::RegistrationsController

[แก้ไข 7 สิงหาคม 2013] ตอนนี้ Devise ยังมีเครื่องมือในการสร้างคอนโทรลเลอร์: https://github.com/plataformatec/devise/wiki/Tool:-Generate-and-customize-controllers

ดังนั้น ... อย่างไรก็ตาม ... ฉันจัดการเพื่อให้ได้สิ่งที่ "AnApprentice" ต้องการเพียงแค่เขียนสิ่งนี้ (สำหรับวิธีการแก้ปัญหาที่สะอาดกว่าโปรดดูการแก้ไขขนาดใหญ่ต่อไปนี้):

#/my_project/app/helpers/devise_helper.rb
module DeviseHelper
   def devise_error_messages!
      return "" if resource.errors.empty?

      return resource.errors
   end
end

และในมุมมองของฉันบรรทัดถัดไปก็ใช้ได้ดี:

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

ถ้าอย่างนั้นคุณสามารถเข้าถึงข้อผิดพลาดสำหรับแอตทริบิวต์เฉพาะเช่นนี้:

    #Imagine you want only the first error to show up for the login attribute:
    <%= devise_error_messages![:login].first %> 

และ ... เคล็ดลับเล็ก ๆ น้อย ๆ ที่จะมีข้อผิดพลาดเพียงข้อเดียว (ข้อแรกที่จับได้) ปรากฏขึ้นต่อแอตทริบิวต์:

<% if resource.errors.any? %>
  <% saved_key = "" %>
  <% devise_error_messages!.each do |key, value| %>
    <% if key != saved_key %>
        <div class="flash <%= key %>"><%= key %> <%= value %></div>
    <% end %>
    <% saved_key = key %>
  <% end %>
<% end %>

ฉันรู้ว่ามันเป็นเวลานานแล้วที่คำถามนี้ถูกโพสต์ แต่ฉันคิดว่ามันจะช่วยผู้ใช้งานได้มาก :)

แก้ไขใหญ่:

ในขณะที่ฉันชอบที่จะขยายโค้ดของฉันทำให้มันสะอาดขึ้นและแบ่งปันกับคนอื่น ๆ ฉันเพิ่งอยากเปลี่ยน devise_error_messages! วิธีการเพื่อใช้ในมุมมองของฉันและทำให้มันแสดงเคล็ดลับที่ฉันอธิบายไว้ข้างต้น

ดังนั้นนี่คือวิธีการของฉัน:

 def devise_error_messages! 
    html = ""

    return html if resource.errors.empty?

    errors_number = 0 

    html << "<ul class=\"#{resource_name}_errors_list\">"

    saved_key = ""
    resource.errors.each do |key, value|
      if key != saved_key
        html << "<li class=\"#{key} error\"> This #{key} #{value} </li>"
        errors_number += 1
      end
      saved_key = key
    end

    unsolved_errors = pluralize(errors_number, "unsolved error")
    html = "<h2 class=\"#{resource_name}_errors_title\"> You have #{unsolved_errors} </h2>" + html
    html << "</ul>"

    return html.html_safe
 end

ไม่มีเรื่องใหญ่ที่นี่ฉันใช้รหัสที่เขียนในมุมมองของฉันซ้ำเพื่อแสดงแอตทริบิวต์ pey ข้อผิดพลาดเพียงรายการเดียวเนื่องจากบ่อยครั้งที่อันแรกจะเกี่ยวข้องเพียงช่องเดียว (เช่นเมื่อผู้ใช้ลืมช่องที่จำเป็น)

ฉันกำลังนับข้อผิดพลาด "ที่ไม่ซ้ำกัน" เหล่านั้นและฉันกำลังสร้างชื่อ H2 HTML โดยใช้พหูพจน์และวางไว้ก่อนรายการข้อผิดพลาด

ตอนนี้ฉันสามารถใช้ "devise_error_messages!" เป็นค่าเริ่มต้นและแสดงผลตามที่ฉันเคยแสดงมาก่อนหน้านี้

หากคุณต้องการเข้าถึงข้อความแสดงข้อผิดพลาดเฉพาะในมุมมองของคุณตอนนี้ขอแนะนำให้ใช้ "resource.errors [: attribute] .first" โดยตรงหรืออะไรก็ได้

เซย่า, กุลการ์.


6

ฉันใช้ Devise ใน Rails 3 และโค้ดแฟลชของคุณก็ค่อนข้างเหมือนกับที่ฉันมี ในแอปของฉันรหัสทำงานตามที่คาดไว้ ข้อความแสดงข้อผิดพลาดของ Devise จะถูกส่งออกพร้อมกับข้อความแฟลชที่เหลือของฉัน:

<% flash.each do |name, msg| %>
  <%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
<% end %>

ลองใช้รหัสนี้และดูว่าสร้างความแตกต่างได้หรือไม่ - แอตทริบิวต์ ID อื่นอาจช่วยได้


ขอบคุณ แต่สุดท้ายก็ไม่ได้แสดงอะไรเลย "<% = devise_error_messages!%>" แสดงข้อผิดพลาด ข้างต้นไม่ได้ทำอะไรเลย? ความคิด?
AnApprentice

ขอโทษ - ฉันเพิ่งเห็นความคิดเห็นของคุณพูดตามตรงฉันหมดความคิด ฉันถือว่าคุณได้ดูซอร์สในเบราว์เซอร์ของคุณและตรวจสอบ HTML ที่สร้างขึ้น? ในกรณีที่มีบางอย่างซ่อนอยู่โดย CSS คุณใช้ Devise 1.1.3 เวอร์ชันล่าสุดหรือไม่
Scott

5

ฉันมาถึงจุดนี้แล้วและมันก็ใช้งานได้แล้ว ซึ่งจะเพิ่มข้อความประดิษฐ์ลงในแฟลชเพื่อให้สามารถใช้งานได้ตามปกติ โปรดพิจารณาว่าฉันเพิ่งเริ่มใช้ Ruby and Rails ...

class ApplicationController < ActionController::Base
  after_filter :set_devise_flash_messages, :if => :devise_controller?
  ...

  private:

  def set_devise_flash_messages
    if resource.errors.any?
      flash[:error] = flash[:error].to_a.concat resource.errors.full_messages
      flash[:error].uniq!
    end
  end
end

แก้ไข:

ขออภัยฉันใช้ยามและมีพฤติกรรมที่ไม่ต้องการบางอย่าง เนื่องจากafter_filterถูกเรียกหลังจากการแสดงผลดังนั้นจึงไม่ทำงานตามที่คาดไว้ หากมีใครทราบวิธีเรียกใช้เมธอดหลังการดำเนินการ แต่ก่อนการเรนเดอร์ ...

แต่คุณสามารถใช้สิ่งนั้นแทนได้:

module ApplicationHelper

  # merge the devise messages with the normal flash messages
  def devise_flash
    if controller.devise_controller? && resource.errors.any?
      flash.now[:error] = flash[:error].to_a.concat resource.errors.full_messages
      flash.now[:error].uniq!
    end
  end

end

ใน views/shared/_messages.html.erb

<% devise_flash %>
<!-- then display your flash messages as before -->

1
+1 คำตอบที่ดี ฉันคิดว่านี่เป็นทางออกที่สะอาดที่สุดและเข้ากับสถาปัตยกรรมปัจจุบันของฉันได้เป็นอย่างดี คำตอบนั้นไม่ชัดเจนนัก - โดยพื้นฐานแล้วทุกอย่างก่อนการแก้ไขควรถูกละเว้น (และลบหรือตีผ่าน imo)
zelanix

3

หากคุณต้องการแสดงแฟลชมากกว่าหนึ่งประเภทที่กำหนด (: alert,: notice, etc ... ) และไม่ต้องเสียเวลาในการแก้ไขพฤติกรรมของอัญมณีนี่คือวิธีแก้ปัญหาที่ฉันใช้กับ Devise ฉันค่อนข้างมั่นใจว่ามันสามารถใช้กับอัญมณีที่ใช้ข้อความแฟลชได้

สิ่งแรกที่ต้องทำใน application_controller.rb ของคุณให้เพิ่มสิ่งนี้:

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

สิ่งที่สองที่ต้องทำแสดงข้อความแฟลชของคุณด้วยสิ่งนี้ใน application.html.erb (หรือทุกที่ที่คุณต้องการ):

   <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>

สิ่งที่สามที่ต้องทำเมื่อใดก็ตามที่คุณต้องการเพิ่มข้อความแฟลชในตัวควบคุมใด ๆ ให้ทำสิ่งนี้:

flash_message(:success, "The user XYZ has been created successfully.")

แต่วิธีรับข้อความ Devise เพื่อเรียกใช้ flash_messages แทนที่จะเก็บวัตถุข้อผิดพลาด
คริสโตเฟอร์ Oezbek

3

สร้าง DeviseHelper:

module DeviseHelper
  def devise_error_messages!
    return "" if resource.errors.empty?

    messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg)}.join
    return flash.now[:alert] = messages.html_safe
  end
end

ในมุมมองของคุณแทนที่

<%= devise_error_messages! %>

ถึง:

<% devise_error_messages! %>

1
จริงๆแล้วคุณควรใช้: flash.now [: alert]
BM

2

เป็นที่ยอมรับว่าแฮ็คนิดหน่อย แต่ฉันใช้ตัวช่วยนี้ (app / helpers / devise_helper.rb) เพื่อจับแฟลชและใช้สิ่งเหล่านี้หากตั้งค่าเริ่มต้นเป็นresource.errors. นี่เป็นเพียงผู้ช่วยที่อยู่ในอุปกรณ์ lib

module DeviseHelper

  def devise_error_messages!
    flash_alerts = []
    error_key = 'errors.messages.not_saved'

    if !flash.empty?
      flash_alerts.push(flash[:error]) if flash[:error]
      flash_alerts.push(flash[:alert]) if flash[:alert]
      flash_alerts.push(flash[:notice]) if flash[:notice]
      error_key = 'devise.failure.invalid'
    end

    return "" if resource.errors.empty? && flash_alerts.empty?
    errors = resource.errors.empty? ? flash_alerts : resource.errors.full_messages

    messages = errors.map { |msg| content_tag(:li, msg) }.join
    sentence = I18n.t(error_key, :count    => errors.count,
                                 :resource => resource.class.model_name.human.downcase)

    html = <<-HTML
    <div id="error_explanation">
      <h2>#{sentence}</h2>
      <ul>#{messages}</ul>
    </div>
    HTML

    html.html_safe
  end

end

2

หากคุณต้องการ piggyback จาก devise_error_messages คุณสามารถทำได้โดยเพิ่มใน resource.errors

หากคุณต้องนั่งทับตัวควบคุมการลงทะเบียนอาจมีลักษณะดังนี้

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 

2

วิธีที่ง่ายมากในการแสดงข้อความแสดงข้อผิดพลาดสำหรับแต่ละฟิลด์

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

ใส่สำหรับแต่ละฟิลด์ด้วยชื่อฟิลด์ในวงเล็บเหลี่ยมด้านล่างทุกบรรทัดที่คุณต้องการแสดงข้อความแสดงข้อผิดพลาดแบบอินไลน์


1

เพื่อแสดงข้อผิดพลาดจากอุปกรณ์ควบคุมของคุณโดยมีเพียงข้อผิดพลาดแรกที่แสดงขึ้น

flash[:error] = @resource.errors.full_messages.first

1

เพียงเพื่อเพิ่มคำตอบของ Eric Hu ที่ด้านบนซึ่งใช้คำสั่ง If ทั้งหมดให้ทำสิ่งนี้แทน

# Controller
flash.now[:error] = flash[:error].to_a.concat(resource.errors.full_messages)

# View
<% flash.each do |name, msg| %>
 <% Array(msg).uniq.each do |message| %>
  <%= message %>
 <% end %>
<% end %>

1

ฉันแค่ทำสิ่งนี้ได้ผลสำหรับฉัน: ในแอพ / ผู้ช่วย /ฉันสร้างไฟล์devise_helper.rb

  module DeviseHelper

  def devise_error_messages_for(resource)
    return "" if resource.errors.empty?

    messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
    sentence = I18n.t("errors.messages.not_saved",
                      count: resource.errors.count,
                      resource: resource.class.model_name.human.downcase)

    html = <<-HTML
    <div id="error_explanation">
      <h2>#{sentence}</h2>
      <ul>#{messages}</ul>
    </div>
    HTML

    html.html_safe
  end
end

ในไฟล์ดูทั้งหมดฉันเปลี่ยน

<%= devise_error_messages! %>

สำหรับ:

<%= devise_error_messages_for(#your object in your formular)%>

สำหรับฉันมันทำให้ในมุมมองของฉันแก้ไขและผู้ใช้ใหม่:

  <%=form_for resource, as: @user, url: user_path(@user),...
      <%= devise_error_messages_for(@user) %>

หวังว่ามันจะช่วยคุณได้;)


ฉันไม่เข้าใจจริงๆว่ามันทำอะไร? นี่คือพฤติกรรมมาตรฐาน? เป็นอีกวิธีหนึ่งในการทำ<%= devise_error_messages! %>และไม่ตอบคำถาม คำถามจะถามวิธีใช้แฟลชกับแต่ละข้อความ
มาร์ค

0
  1. ลบ "devise_error_messages!" จากเทมเพลต "app / views / users / passwords / new"
  2. สร้างคอนโทรลเลอร์ที่กำหนดเองสำหรับผู้ใช้ของคุณ (app / controllers / users / passwords_controller.rb) และใน after filter เพิ่ม error flash array:
class Users::PasswordsController < Devise::PasswordsController
  after_filter :flash_errors

  def flash_errors
    unless resource.errors.empty?
      flash[:error] = resource.errors.full_messages.join(", ")
    end
  end
end

0

ฉันชอบที่จะทำเหมือนกับที่ทำในคอนโทรลเลอร์ Devise อื่น ๆ ด้วยการโกงนี้

<% if flash.count > 0 %>
  <div id="error_explanation">
    <h2>Errors prevented you from logging in</h2>
      <ul>
        <% flash.each do |name, msg| %>
        <li>
          <%= content_tag :div, msg, id: "flash_#{name}" %>
        </li>
       <% end %>
     </ul>
   </div>
<% end %>

0

เพื่อให้ materialisecss แสดงข้อความแสดงข้อผิดพลาดเป็นขนมปังฉันได้เพิ่มรหัสนี้ใน app / helpers / devise_helper.rb

module DeviseHelper
  def devise_error_messages!

    messages = resource.errors.full_messages.map { |msg|
      String.new(" M.toast({html: '" + msg + "' }); ".html_safe )
    }.join

    messages = ("<script>" + messages + "</script>").html_safe
  end 
end

ฉันแน่ใจว่าพวกเขาจะเป็นวิธีที่สะอาดที่สุดในการเขียน แต่มันก็ทำได้ดีมาก


0

DeviseHelper#devise_error_messages! เลิกใช้งานแล้วและจะถูกลบออกในเวอร์ชันหลักถัดไป

ตอนนี้ Devise ใช้บางส่วนด้านล่างdevise/shared/error_messagesเพื่อแสดงข้อความแสดงข้อผิดพลาดตามค่าเริ่มต้นและทำให้ง่ายต่อการปรับแต่ง อัปเดตมุมมองของคุณเปลี่ยนการโทรจาก:

      <%= devise_error_messages! %>

ถึง:

      <%= render "devise/shared/error_messages", resource: resource %>

-1

ฉันเพิ่งสร้างapp/helpers/devise_helper.rbเหมือน John แต่ลบล้างวิธีการเช่นนั้น:

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

ด้วยเหตุนี้ฉันจึงไม่ต้องแก้ไขอะไรอีก มันเป็นความคิดที่ไม่ดี? ฉันใหม่กับรางอย่าลังเลที่จะแก้ไขฉัน ขอบคุณ


ไม่ได้ผลตามที่ต้องการเพราะตอนนี้ข้อความแฟลชมีแท็ก html <br> โดยปกติคุณใส่เฉพาะสตริงในข้อความแฟลชของคุณ
AZ.

บางที แต่บรรทัดใหม่ยังคงใช้งานได้ เสนอทางออกอื่นถ้าคุณไม่ชอบอันนี้
YoyoS

-2

ฉันเพิ่งประกาศ devise_error_messages! เป็นผู้ช่วยที่ว่างเปล่า และดึงและจัดการข้อผิดพลาดด้วยตนเองใน _errors ทั่วไปบางส่วนสำหรับแอปพลิเคชันของฉัน ดูเหมือนจะเป็นวิธีแก้ปัญหาที่ง่ายที่สุดและฉันไม่ต้องไปถึงไฟล์ทั้งหมดของอุปกรณ์และลบการโทรไปยังตัวจัดการข้อผิดพลาด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.