W pełni niestandardowy komunikat o błędzie walidacji za pomocą Rails

Używając Rails próbuję uzyskać komunikat o błędzie, taki jak" Pole piosenki nie może być puste " w save. Wykonanie:

validates_presence_of :song_rep_xyz, :message => "can't be empty"

... wyświetla tylko "Song Rep XYW can 't be empty" , co nie jest dobre, ponieważ tytuł pola nie jest przyjazny dla użytkownika. Jak Mogę zmienić tytuł samego pola ? Mógłbym zmienić rzeczywistą nazwę pola w bazie danych, ale mam wiele pól "piosenki" i muszę mieć konkretne nazwy pól.

Nie chcę się włamywać po railach' proces walidacji i uważam, że powinien być sposób, aby to naprawić.

Author: marcgg, 2009-04-30

15 answers

Obecnie akceptowanym sposobem ustawiania humanizowanych nazw i niestandardowych komunikatów o błędach jest użycie locales .

# config/locales/en.yml
en:
  activerecord:
    attributes:
      user:
        email: "E-mail address"
    errors:
      models:
        user:
          attributes:
            email:
              blank: "is required"

Teraz humanizowana nazwa i wiadomość potwierdzająca obecność dla atrybutu "email" zostały zmienione.

Komunikaty walidacji mogą być ustawione dla określonego modelu+atrybut, model, atrybut lub globalnie.

 389
Author: graywh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-17 16:30:24

W twoim modelu:

validates_presence_of :address1, :message => "Put some address please" 

In your view

<% m.errors.each do |attr,msg|  %>
 <%=msg%>
<% end %>

If you do instead

<%=attr %> <%=msg %>

Pojawia się komunikat o błędzie z nazwą atrybutu

address1 Put some address please

Jeśli Chcesz otrzymać komunikat o błędzie dla jednego atrybutu

<%= @model.errors[:address1] %>
 59
Author: Federico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 03:50:45

Spróbuj tego.

class User < ActiveRecord::Base
  validate do |user|
    user.errors.add_to_base("Country can't be blank") if user.country_iso.blank?
  end
end

Znalazłem to tutaj .

Oto inny sposób, aby to zrobić. To, co robisz, to definiowanie metody human_attribute_name na klasie modelu. Metoda przekazuje nazwę kolumny jako łańcuch znaków i zwraca łańcuch znaków do wykorzystania w komunikatach sprawdzania poprawności.

class User < ActiveRecord::Base

  HUMANIZED_ATTRIBUTES = {
    :email => "E-mail address"
  }

  def self.human_attribute_name(attr)
    HUMANIZED_ATTRIBUTES[attr.to_sym] || super
  end

end

Powyższy kod pochodzi z tutaj

 58
Author: Maulin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 13:28:38

Tak, jest sposób, aby to zrobić bez wtyczki! Ale nie jest tak czysty i elegancki jak korzystanie z wspomnianej wtyczki. Tutaj jest.

Zakładając, że to Rails 3 (Nie wiem czy w poprzednich wersjach jest inaczej),

Zachowaj to w swoim modelu:

validates_presence_of :song_rep_xyz, :message => "can't be empty"

I w widoku, zamiast zostawić

@instance.errors.full_messages

Jak by było, gdy użyjemy generatora rusztowania, umieść:

@instance.errors.first[1]

I otrzymasz tylko wiadomość określoną w modelu, bez atrybutu nazwisko.

Wyjaśnienie:

#returns an hash of messages, one element foreach field error, in this particular case would be just one element in the hash:
@instance.errors  # => {:song_rep_xyz=>"can't be empty"}

#this returns the first element of the hash as an array like [:key,"value"]
@instance.errors.first # => [:song_rep_xyz, "can't be empty"]

#by doing the following, you are telling ruby to take just the second element of that array, which is the message.
@instance.errors.first[1]

Do tej pory wyświetlamy tylko jeden komunikat, zawsze dla pierwszego błędu. Jeśli chcesz wyświetlić wszystkie błędy, możesz zapętlić hash i pokazać wartości.

Mam nadzieję, że to pomogło.
 16
Author: Marco Antonio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-18 15:33:04

Kod Rails3 z w pełni zlokalizowanymi komunikatami:

W modelu użytkownika.rb define the validation

validates :email, :presence => true

W config / locales / en.yml

en:  
  activerecord:
    models: 
      user: "Customer"
    attributes:
      user:
        email: "Email address"
    errors:
      models:
        user:
          attributes:
            email:
              blank: "cannot be empty"
 14
Author: Lukas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-18 13:34:15

W niestandardowej metodzie walidacji użyj:

errors.add(:base, "Custom error message")

Jako że add_to_base jest przestarzałe.

errors.add_to_base("Custom error message")

 12
Author: amit_saxena,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 12:40:09

Zalecam zainstalowanie custom_error_message gem (lub jako plugin) pierwotnie napisany przez Davida Easleya

Pozwala robić takie rzeczy jak:

validates_presence_of :non_friendly_field_name, :message => "^Friendly field name is blank"
 12
Author: Ryan Bigg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-01 08:02:51

Związane z zaakceptowaną odpowiedzią i kolejna odpowiedź na liście :

Potwierdzam, że widelec nanamkim z custom-err-msg działa z Rails 5 i z ustawieniami lokalnymi.

Wystarczy uruchomić wiadomość locale za pomocą karetki i nie powinna ona wyświetlać nazwy atrybutu w wiadomości.

Model zdefiniowany jako:

class Item < ApplicationRecord
  validates :name, presence: true
end

Z następującym en.yml:

en:
  activerecord:
    errors:
      models:
        item:
          attributes:
            name:
              blank: "^You can't create an item without a name."

item.errors.full_messages wyświetli:

You can't create an item without a name

Zamiast zwykłe Name You can't create an item without a name

 10
Author: Rystraum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:28

Po prostu zrób to w normalny sposób:

validates_presence_of :email, :message => "Email is required."

Ale wyświetl to tak zamiast

<% if @user.errors.any? %>
  <% @user.errors.messages.each do |message| %>
    <div class="message"><%= message.last.last.html_safe %></div>
  <% end %>
<% end %>

Zwraca

"Email is required."

Metoda lokalizacji jest zdecydowanie "właściwym" sposobem, aby to zrobić, ale jeśli robisz mały, Nie-globalny projekt i chcesz po prostu zacząć działać szybko - jest to zdecydowanie łatwiejsze niż przeskakiwanie plików.

Lubię to za możliwość umieszczenia nazwy pola gdzieś indziej niż początek łańcucha:

validates_uniqueness_of :email, :message => "There is already an account with that email."
 6
Author: brittohalloran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-24 14:26:12

Oto inny sposób:

Jeśli użyjesz tego szablonu:

<% if @thing.errors.any? %>
  <ul>
    <% @thing.errors.full_messages.each do |message| %>
      <li><%= message %></li>
    <% end %>
  </ul>
<% end %>

Możesz napisać własną wiadomość tak:

class Thing < ActiveRecord::Base

  validate :custom_validation_method_with_message

  def custom_validation_method_with_message
    if some_model_attribute.blank?
      errors.add(:_, "My custom message")
    end
  end

W ten sposób, z powodu podkreślenia, pełna wiadomość staje się "moją niestandardową wiadomością", ale dodatkowa przestrzeń na początku jest niezauważalna. Jeśli naprawdę nie chcesz tej dodatkowej przestrzeni na początku, po prostu Dodaj metodę .lstrip.

<% if @thing.errors.any? %>
  <ul>
    <% @thing.errors.full_messages.each do |message| %>
      <li><%= message.lstrip %></li>
    <% end %>
  </ul>
<% end %>

Ciąg.metoda lstrip pozbędzie się dodatkowego miejsca utworzonego przez': _ ' i pozostawi wszelkie inne błędy wiadomości bez zmian.

A nawet lepiej, użyj pierwszego słowa niestandardowej wiadomości jako klucza:
  def custom_validation_method_with_message
    if some_model_attribute.blank?
      errors.add(:my, "custom message")
    end
  end

Teraz pełna wiadomość będzie "moja niestandardowa wiadomość" bez dodatkowego miejsca.

Jeśli chcesz, aby pełna wiadomość zaczynała się od słowa pisanego wielką literą, np. "URL can' t be blank", nie można tego zrobić. Zamiast tego spróbuj dodać inne słowo jako klucz:

  def custom_validation_method_with_message
    if some_model_attribute.blank?
      errors.add(:the, "URL can't be blank")
    end
  end

Teraz pełna wiadomość będzie brzmiała "URL nie może być pusty"

 6
Author: Cruz Nunez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-29 20:48:00

Jednym z rozwiązań może być zmiana domyślnego formatu błędu i18n:

en:
  errors:
    format: "%{message}"

Domyślnie jest to format: %{attribute} %{message}

 4
Author: cappie013,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-22 23:21:03

Jeśli chcesz umieścić je wszystkie na ładnej liście, ale bez używania szorstkiej, nie przyjaznej człowiekowi nazwy, możesz to zrobić...

object.errors.each do |attr,message|
  puts "<li>"+message+"</li>"
end
 2
Author: adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-23 15:05:28

In your view

object.errors.each do |attr,msg|
  if msg.is_a? String
    if attr == :base
      content_tag :li, msg
    elsif msg[0] == "^"
      content_tag :li, msg[1..-1]
    else
      content_tag :li, "#{object.class.human_attribute_name(attr)} #{msg}"
    end
  end
end

Jeśli chcesz nadpisać komunikat o błędzie bez nazwy atrybutu, po prostu poprzedź go znakiem ^ w ten sposób:

validates :last_name,
  uniqueness: {
    scope: [:first_name, :course_id, :user_id],
    case_sensitive: false,
    message: "^This student has already been registered."
  }
 1
Author: luckyruby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-13 16:07:40

Próbowałem śledzić, pracował dla mnie:)

1 zadanie.rb

class Job < ApplicationRecord
    validates :description, presence: true
    validates :title, 
              :presence => true, 
              :length => { :minimum => 5, :message => "Must be at least 5 characters"}
end

2 jobs_controller.rb

def create
      @job = Job.create(job_params)
      if @job.valid?
        redirect_to jobs_path
      else
        render new_job_path
      end     
    end

3 _form.html.erb

<%= form_for @job do |f| %>
  <% if @job.errors.any? %>
    <h2>Errors</h2>
    <ul>
      <% @job.errors.full_messages.each do |message|%>
        <li><%= message %></li>
      <% end %>  
    </ul>
  <% end %>
  <div>
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.label :description %>
    <%= f.text_area :description, size: '60x6' %>

  </div>
  <div>
    <%= f.submit %>
  </div>
<% end %> 
 0
Author: Aigul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-03 23:08:35

Oto Mój kod, który może być dla Ciebie przydatny, jeśli nadal go potrzebujesz: Mój model:

validates :director, acceptance: {message: "^Please confirm that you are a director of the company."}, on: :create, if: :is_director?

Następnie stworzyłem helpera do wyświetlania wiadomości:

module ErrorHelper
  def error_messages!
    return "" unless error_messages?
    messages = resource.errors.full_messages.map { |msg|
       if msg.present? && !msg.index("^").nil?
         content_tag(:p, msg.slice((msg.index("^")+1)..-1))
       else
         content_tag(:p, msg)
       end
    }.join

    html = <<-HTML
      <div class="general-error alert show">
        #{messages}
      </div>
    HTML

    html.html_safe
  end

  def error_messages?
    !resource.errors.empty?
  end
end
 0
Author: Oleksii Danylevskyi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-02 11:01:08