簡體   English   中英

在Rails中顯示鏈接表單錯誤消息

[英]Display link in Rails form error message

在我們的注冊表格中,我們validates_uniqueness_of :email

當用戶嘗試使用我們的注冊表單並指定現有的電子郵件地址時,我希望他們看到這樣的錯誤消息

該郵件地址已被使用。 如果您在登錄時遇到問題,可以重置密碼

顯然,我想使用命名路由作為鏈接,但我的用戶模型無法訪問它。 我怎么能做到這一點?

附注:我們將很快為我們的應用程序提供翻譯,所有這些錯誤消息將最終出現在YAML文件中。 我可以以某種方式在我的YAML語言環境文件中的消息中注入new_password_url嗎? (例如, config/locales/en.yml

我知道這是一個老問題,但對於想要在錯誤消息中插入鏈接的未來用戶,這里有一些適用於我的指南。

首先,I18n錯誤消息已經被假定為html安全,因此您可以繼續編寫合適的錯誤消息。 在這個例子中,我正在更改“發送電子郵件”消息。

# config/locales/en.yml
activerecord:
  errors:
    models:
      user:
        attributes:
          email:
            taken: 'has already been taken. If this is your email address, try <a href="%{link}">logging in</a> instead.'

注意插值變量%link

現在您需要在驗證器中傳遞該變量的值,如下所示:

# app/models/user.rb
validates :email, :uniqueness => {:link => Rails.application.routes.url_helpers.login_path}

(默認情況下,您在此處傳遞的任何選項將自動作為變量發送到I18n轉換器,包括一些特殊的預填充變量,如%value%model等)

而已! 您現在在錯誤消息中有一個鏈接。

這可能不能很好地簡化翻譯,但這里有一個建議:

在user_controller #create操作中,使用if語句包裝已有的所有內容。 這是一個粗略的例子:

class UserController < ApplicationController
...

def create
  if User.find(params[:email])
    flash[:alert] = "This email address is in use.  You can ".concat(generate_reset_password_link(params[:email])
    render :action => 'new'
  else
    <your current code>
  end
end

在此之后,你將不得不編寫一個輔助方法generate_reset_password_link ,但我認為這主要是尊重MVC布局。 控制器用於與視圖和模型連接。 它有點違反DRY原則,因為你基本上繞過了validates_uniqueness_of :email ,但是你得到了一些自定義行為。 如果你想制作更復雜的應用程序,DRY似乎不是100%可以實現的,但也許你可以改進這個並證明我錯了;)

您可能需要按一下這一點,以便render :action => 'new'將使用先前輸入的數據重新填充自身(如果用戶只是錯誤輸入了自己的電子郵件地址並且實際上不在系統中)。

如果你決定使用這種方法,我會扔在控制器和指示電子郵件獨特性在兩個地方基本檢查模型評論。 如果其他人必須查看此代碼,它將幫助他們理解和維護它。

您可以在錯誤消息中放置自己的標記,如〜[new_password_url]。 然后在渲染您的錯誤消息gsub ur標簽與實際。 如果你想一般性地做到這一點,你可以使用regexp獲取路徑然后評估它以獲取url然后gsub它回來。如果你將html放入你的文本,讓你使用raw方法。

如果您使用的是2.3.x,請將您對error_messages的調用替換為您自己的幫助程序,使用UsersHelper編寫。 它應該接受FormBuilder或ActiveRecord對象,並根據需要調整錯誤消息。 您可以根據需要進行任意數量的自定義,也可以像gsub一樣簡單:

def user_error_messages(f)
  find_error = "This email address is already in use."
  replacement = "This email address is already in use. #{link_to(...)} to reset your password"
  f.error_messages.sub(find_error, replacement).html_safe
end

如果您正在使用Rails3,請創建一個幫助方法, @user.errors.full_messages在它們被發送到視圖之前簡單地處理@user.errors.full_messages

今天偶然發現了這個:

http://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html

如果您需要從其他地方(例如模型)訪問此自動生成的方法,那么您可以通過在您的類中包含ActionController::UrlFor來實現:


第1步

了解模型的命名路線是很難的; 這讓我最重要的是。

現在我可以做一些事情

class User < ActiveRecord::Base
  include Rails.application.routes.url_helpers

  def reset_password_uri
    new_user_password_path(self)
  end
end

# User.find(1).reset_password_uri => "/users/password/new"

第2步

所以我們可以訪問命名路由,但現在我們需要將它注入YAML消息。

這是我剛學到的有關YAML變量的內容:

# en.yml
en:
  welcome: "Hello, %{username}!"

# es.yml
es:
  welcome: "¡Hola, %{username}!"

我可以通過在t方法中包含一個哈希來注入username

<div id="welcome">
  <%= t :welcome, :username => @user.username %>
</div>

第3步

現在我們只需要一種方法來為原始問題中描述的錯誤消息添加插值。 這是我目前卡住的地方:(

經過幾個小時試圖用設計來解決Rails 4,我意識到你可以直接將鏈接添加到驗證中:

# app/models/user.rb
validates :username, presence: true, uniqueness: {:message => "username has already been taken - <a href='/users'>search users</a>" }

這種情況下的鏈接是我的用戶索引。 希望這會對某人有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM