[ruby-on-rails] 레일-고안-취급-devise_error_messages

내 사용자 편집 페이지에는 다음과 같은 줄이 있습니다.

<%= devise_error_messages! %>

문제는 이것이 나머지 앱이 수행하는 표준 방식으로 오류를 출력하지 않는다는 것입니다.

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

내 질문은 flash.each를 사용하는 다른 것과 비슷하게 고안 오류 메시지를 얻는 방법입니다.

감사.



답변

나는 이것을 스스로 알아 내려고 노력하고있다. 방금이 문제가 Github https://github.com/plataformatec/devise/issues/issue/504/#comment_574788에 기록 된 것을 발견했습니다.

Jose는 devise_error_messsages!메소드가 단지 스텁 (구현이 포함되어 있음)이고이를 재정의 / 교체해야한다고 말합니다. 이것이 위키의 어딘가에 지적되면 좋았을 것입니다. 그래서 우리와 같은 사람들이 추측하고있는 것 같습니다.

그래서 모듈을 다시 열고 메소드를 재정 의하여 기본 구현을 효과적으로 재정의하려고합니다. 어떻게되는지 알려 드리겠습니다.

최신 정보

그렇습니다. 나는 app/helpers/devise_helper.rb그것을 이렇게 만들고 무시했다.

module DeviseHelper
  def devise_error_messages!
    'KABOOM!'
  end
end

그래서 이것을 알면 원하는 방식으로 오류 메시지를 표시하도록 메소드를 수정할 수 있습니다.

원래 문제를 해결하기 위해 : devise_helper.rbGithub 의 원본 다음과 같습니다 . 오류 메시지가 어떻게 전달되는지 살펴보십시오.

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>


답변

아래 솔루션은 현재 최신 장치 (4.1.1) 및 Rails 4.2.6에서 작동합니다. 그러나 너무 간단하여 10 년 후에 왜 작동하지 않는 이유를 알 수 없습니다.)

오류 메시지를 재활용하고 앱 전체에서 동일하게 보이게하려면 다음과 같이 권장합니다 (Michael Hartl tut으로 배웠습니다).

오류 메시지에 대한 부분 작성 :
layouts/_error_messages.html.erb 다음 코드를 넣으십시오 (여기서는 부트 스트랩 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 %>


답변

이 질문이 게시 된 지 오래되었다는 것을 알고 있지만 찾은 내용에 대해 의견을 말하고 싶었습니다. 이미 답한 두 사람은 저에게 큰 도움이되었고 저는 단지 기여하고 싶었습니다.

Devise 전체에서을 사용하는 통화가 있음을 알 수 render_with_scope있습니다. 나는 이것이 고안에 의해 정의 된 방법이며 기본적으로 현재 범위를 렌더링 된 다음보기에 적용한다고 생각합니다.

이것이 왜 관련이 있습니까? Devise는 resource.errors( not @resource.errors ) 내에 오류를 포함합니다 . 상자 밖에서 사용하려면 Devise가 제대로 작동합니다.

사용자 관리 동작 변경을 시작하면 이러한 오류와 관련된 문제가 발생합니다. Devise가 이전에없는 경우 redirect_to또는 render대신 () 대신을 추가하면 render_with_scope기본적으로 오류 메시지가 표시됩니다. 이것은 내 의견으로는 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가 오류 메시지를 처리하는 방법을 앱 전체에서 처리하는 방법을 변경한다고 생각합니다. 두 개가 아닌 하나의 오류 메시지 시스템을 갖는 것이 훨씬 깨끗해 보입니다.


답변

나는 이것을 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

일했다!


답변

나는 단지 여기에 새로운 작은 조각을 가져오고 싶다.

그래서 “AnApprentice”가 원하는 결과를 얻는 더 쉬운 방법을 찾았습니다.

우선, Devise 플러그인 내에서 어떤 것을 사용자 정의하려면 “\ Ruby_repertory \ lib \ ruby ​​\ gems \ 1.9.1 \ gems \ devise-version \ app \ controllers에서 코드를 복사하는 것이 좋습니다. | helpers | mailers … “를 프로젝트에서 원하는 파일에 추가하십시오.

[편집] 또는 파일을 “일반”고안 파일에서 상속하도록 할 수 있습니다 … …처럼 … 말 … 사용자 정의의 첫 줄인 devise / registrations_controller.rb 내에서 하나의 함수 만 덮어 쓰려고합니다. 등록 컨트롤러는 다음과 같습니다.

class Users::RegistrationsController < Devise::RegistrationsController

[2013 년 8 월 7 일 편집] 이제 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

여기서 큰 문제는 없었습니다. 내가 작성한 오류 코드 하나만 표시하기 위해 필자가 작성한 코드를 재사용했습니다.

이 “고유 한”오류를 세고 있으며 복수형을 사용하여 H2 HTML 제목을 만들고 오류 목록보다 먼저 표시합니다.

이제 “devise_error_messages!”를 사용할 수 있습니다 기본으로 사용하고 이전에 이미 렌더링 한 것과 정확하게 렌더링합니다.

보기에서 특정 오류 메시지에 액세스하려면 “resource.errors [: attribute] .first”등을 직접 사용하는 것이 좋습니다.

세야, 쿨 가르


답변

Rails 3에서 Devise를 사용하고 있으며 플래시 코드는 내가 가진 것과 거의 동일합니다. 내 앱에서 코드는 예상대로 작동합니다. 즉, Devise 오류 메시지가 나머지 플래시 메시지와 함께 출력됩니다.

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

이 정확한 코드를 사용해보고 차이가 있는지 확인하십시오. 다른 ID 속성이 도움이 될 수 있습니다.


답변

나는 이것에 도달했고 지금까지 일하고있다. 이렇게하면 고안 메시지가 플래시에 추가되므로 평상시처럼 사용할 수 있습니다. 내가 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 -->