रेल के साथ पूरी तरह से कस्टम सत्यापन त्रुटि संदेश


260

रेल का उपयोग कर मैं "गीत फ़ील्ड खाली नहीं हो सकता" जैसे त्रुटि संदेश प्राप्त करने की कोशिश कर रहा हूं। निम्न कार्य करना:

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

... केवल "गीत प्रतिनिधि XYW खाली नहीं हो सकता" प्रदर्शित करता है, जो अच्छा नहीं है क्योंकि क्षेत्र का शीर्षक उपयोगकर्ता के अनुकूल नहीं है। मैं स्वयं फ़ील्ड का शीर्षक कैसे बदल सकता हूँ? मैं डेटाबेस में फ़ील्ड का वास्तविक नाम बदल सकता था, लेकिन मेरे पास कई "गीत" फ़ील्ड हैं और मुझे विशिष्ट फ़ील्ड नाम रखने की आवश्यकता है।

मैं रेल के सत्यापन की प्रक्रिया के आसपास हैक नहीं करना चाहता और मुझे लगता है कि इसे ठीक करने का एक तरीका होना चाहिए।

जवाबों:


432

अब, मानवकृत नाम और कस्टम त्रुटि संदेश सेट करने का स्वीकृत तरीका स्थानों का उपयोग करना है

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

अब "ईमेल" विशेषता के लिए मानवीकृत नाम और उपस्थिति सत्यापन संदेश को बदल दिया गया है।

सत्यापन संदेश विशिष्ट मॉडल + विशेषता, मॉडल, विशेषता या विश्व स्तर पर सेट किए जा सकते हैं।


19
यदि आप मोंगॉयड का उपयोग कर रहे हैं, तो एक्टिवरकॉर्ड की जगह लें: मोंगॉयड के साथ:
इंटेंस

88
@graywh: किसी उत्तर के बारे में प्रश्न कहां पोस्ट किए जाने चाहिए, यदि टिप्पणियों में नहीं? यहाँ I18n गाइड है: guide.rubyonrails.org/i18n.html
टायलर रिक

4
वैसे: यदि आप 3.1.3 में अपने सत्यापनकर्ता के संदेश पैरामीटर के लिए एक प्रतीक पास करते हैं, तो यह आपको वह दायरा बताएगा जिसकी वह तलाश कर रहा था जैसा कि उसे ई नहीं मिलेगा, इसलिए आप जानते हैं कि वास्तव में आपको क्या करना है स्थानों वाईएमएल।
aceofspades

4
ठीक है, यह ठीक है और सभी है, लेकिन क्या होगा अगर भोलेपन से स्तंभ नाम (चाहे वह कितना भी पठनीय क्यों न हो) को पूरी तरह से बंद कर दिया जाएगा, जिससे पूरी तरह से अप-व्याकरण (विशेषकर गैर-अंग्रेजी भाषाओं में) को बढ़ावा मिलेगा? क्या मुझे वास्तव में उपयोग करने की आवश्यकता है errors.add :base, msg? मैं जानना चाहता हूं कि त्रुटि किस कॉलम के बारे में है, इसलिए मैं इसे सही फ़ॉर्म फ़ील्ड पर प्रदर्शित कर सकता हूं।
पैन्ज़ी

6
@graywh शायद मुझे कुछ याद आ रहा है, लेकिन क्या यह हमेशा संदेश से पहले कॉलम का नाम नहीं बताता है? यहां तक ​​कि अंग्रेजी में भी मुझे पसंद है और इसके बजाय The password is wrong.या । The email address is not valid.Password is wrong.Email is not valid.
17

65

आपके मॉडल में:

validates_presence_of :address1, message: 'Put some address please' 

आपके विचार में

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

अगर आप इसके बजाय करते हैं

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

आपको यह त्रुटि संदेश विशेषता नाम के साथ मिलता है

address1 Put some address please

यदि आप एक एकल विशेषता के लिए त्रुटि संदेश प्राप्त करना चाहते हैं

<%= @model.errors[:address1] %>

वह स्वीकार्य समाधान नहीं है। क्या होगा यदि मैं अन्य सभी विशेषताओं (Attr + msg) के लिए डिफ़ॉल्ट व्यवहार चाहता हूं?
रौमूल सेकोन

वहाँ तुम जाओ .. तुम उन 2 चीजों के साथ खेल सकते हो और काम कर सकते हो
Federico

आपको एक प्रतीक का उपयोग करना होगा इसलिए यह आपकी yml फ़ाइलों में दिखाई देगा, जैसेvalidates_presence_of :address1, :message => :put_some_address_please
Federico

यह स्वीकार्य नहीं है, क्योंकि क्षेत्र का नाम शामिल है
fatuhoku

62

इसे इस्तेमाल करे।

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

मुझे यह यहां मिला ।

यहाँ यह करने का एक और तरीका है। आप जो भी करते हैं वह मॉडल वर्ग पर एक human_attribute_name विधि को परिभाषित करता है। विधि को स्तंभ नाम स्ट्रिंग के रूप में पारित किया जाता है और सत्यापन संदेशों में उपयोग करने के लिए स्ट्रिंग लौटाता है।

class User < ActiveRecord::Base

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

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

end

उपरोक्त कोड यहाँ से है


समस्या यह है कि मेरे क्षेत्र को कहा जाता है: song_rep_xyz (अच्छी तरह से, कुछ जटिल), जो उपयोगकर्ता के अनुकूल नहीं है
marcgg

16
रेल्स 3 के लिए, "def self.human_attribute_name (attr)" को "def self.human_attribute_name (attr, options = {})" में
बदलना

3
इसके लिए धन्यवाद। मुझे कुछ चीज़ों की ज़रूरत थी जो रेल्स २ के लिए काम करती थीं (हाँ, मुझे गरीब ... :)
डैन बैरन

18

हाँ, प्लगइन के बिना ऐसा करने का एक तरीका है! लेकिन यह उल्लेखित प्लगइन का उपयोग करने के रूप में साफ और सुरुचिपूर्ण नहीं है। यही पर है।

यह मानते हुए कि यह रेल 3 है (मुझे नहीं पता कि यह पिछले संस्करणों में अलग है),

इसे अपने मॉडल में रखें:

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

और देखने में, छोड़ने के बजाय

@instance.errors.full_messages

जब हम पाड़ जनरेटर का उपयोग करेंगे, तो यह होगा:

@instance.errors.first[1]

और आपको मॉडल में निर्दिष्ट केवल संदेश मिलेगा, विशेषता नाम के बिना।

स्पष्टीकरण:

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

अभी तक हम केवल एक संदेश प्रदर्शित कर रहे हैं, हमेशा पहली त्रुटि के लिए। यदि आप सभी त्रुटियों को प्रदर्शित करते हैं, तो आप हैश में लूप कर सकते हैं और मान दिखा सकते हैं।

उम्मीद है कि मदद की।


16

Rails3 कोड पूरी तरह से स्थानीय संदेशों के साथ:

मॉडल में user.rb सत्यापन को परिभाषित करता है

validates :email, :presence => true

विन्यास / स्थानों / en.yml में

en:  
  activerecord:
    models: 
      user: "Customer"
    attributes:
      user:
        email: "Email address"
    errors:
      models:
        user:
          attributes:
            email:
              blank: "cannot be empty"

15

कस्टम सत्यापन विधि उपयोग में:

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

add_to_base के रूप में पदावनत किया गया है।

errors.add_to_base("Custom error message")


13

स्वीकृत उत्तर से संबंधित और सूची के नीचे एक और उत्तर :

मैं इस बात की पुष्टि कर रहा हूं कि नानकमकीम के कस्टम-एर-मैस के कांटे रेल 5 के साथ काम करते हैं, और स्थानीय सेटअप के साथ।

आपको केवल एक संदेश को कैरेट के साथ शुरू करने की आवश्यकता है और इसे संदेश में विशेषता नाम प्रदर्शित नहीं करना चाहिए।

एक मॉडल के रूप में परिभाषित:

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

निम्नलिखित के साथ en.yml:

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

item.errors.full_messages प्रदर्शित करेगा:

You can't create an item without a name

सामान्य के बजाय Name You can't create an item without a name


11

मैं custom_error_message मणि (या एक प्लगइन के रूप में ) स्थापित करने की सलाह देता हूं जो मूल रूप से डेविड इज़ले द्वारा लिखी गई है

यह आपको सामान करने देता है जैसे:

validates_presence_of :non_friendly_field_name, :message => "^Friendly field name is blank"

मैंने अतीत में इस प्लगइन का उपयोग बड़ी सफलता के साथ किया है, हालांकि यह नियमित रूप से अब भी बनाए रखा प्रतीत नहीं होता है।
जारेड ब्राउन

1
आप वरना रेल 3. के लिए एक रत्न के रूप में स्थापित कर सकते हैं बस जोड़ने के gem "custom_error_message" अपने Gemfile के लिए - देखने GitHub अधिक जानकारी के लिए
डोरियन

वास्तव में जो मुझे चाहिए था
ओलियिकुआ

3
@ डॉकीबॉय मैं पुष्टि करता हूं कि नानकम के कांटे ( github.com/nanamkim/custom-err-msg ) रेल के साथ काम करता है 5. यह वास्तव में स्वीकृत उत्तर के साथ अच्छा खेलता है। मैं इसे एक अलग उत्तर के रूप में लिखूंगा।
5

@Rystraum मेरे जीवन के लिए मैं इस चारों ओर usecase याद नहीं कर सकते, लेकिन उत्तर के लिए धन्यवाद! मैं भविष्य के लिए इसे याद रखना सुनिश्चित करूंगा।
डिकिएबॉय

10

एक समाधान i18n डिफ़ॉल्ट त्रुटि प्रारूप को बदलने के लिए हो सकता है:

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

डिफ़ॉल्ट है format: %{attribute} %{message}


7

यहाँ एक और तरीका है:

यदि आप इस टेम्पलेट का उपयोग करते हैं:

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

आप इस तरह से अपने स्वयं के कस्टम संदेश लिख सकते हैं:

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

इस तरह, अंडरस्कोर के कारण, पूरा संदेश "मेरा कस्टम संदेश" बन जाता है, लेकिन शुरुआत में अतिरिक्त स्थान ध्यान देने योग्य नहीं है। यदि आप वास्तव में शुरुआत में अतिरिक्त स्थान नहीं चाहते हैं, तो केवल .lstripविधि जोड़ें ।

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

String.lstrip विधि ': _' द्वारा बनाए गए अतिरिक्त स्थान से छुटकारा पा लेगी और किसी अन्य त्रुटि संदेश को अपरिवर्तित छोड़ देगी।

या इससे भी बेहतर, कुंजी के रूप में अपने कस्टम संदेश के पहले शब्द का उपयोग करें:

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

अब पूर्ण संदेश "मेरा कस्टम संदेश" होगा जिसमें कोई अतिरिक्त स्थान नहीं होगा।

यदि आप चाहते हैं कि "URL खाली नहीं हो सकता" जैसे शब्द से शुरू होने वाला पूरा संदेश नहीं हो सकता है। इसके बजाय कुंजी के रूप में कुछ और शब्द जोड़ने का प्रयास करें:

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

अब पूरा संदेश "URL रिक्त नहीं हो सकता है"


ओह, आप भी कर सकते हैं errors.add(:_, 'foobar')और संदेश के रूप में '
फोब्बर

6

बस इसे सामान्य तरीके से करें:

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

लेकिन इसे इस तरह प्रदर्शित करें

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

रिटर्न

"Email is required."

स्थानीयकरण विधि निश्चित रूप से ऐसा करने का "उचित" तरीका है, लेकिन यदि आप एक छोटी, गैर-वैश्विक परियोजना कर रहे हैं और बस जल्दी जाना चाहते हैं - तो यह निश्चित रूप से फ़ाइल hopping की तुलना में आसान है।

मैं इसे स्ट्रिंग की शुरुआत के अलावा कहीं और क्षेत्र का नाम रखने की क्षमता के लिए पसंद करता हूं:

validates_uniqueness_of :email, :message => "There is already an account with that email."

2

यदि आप उन सभी को एक अच्छी सूची में सूचीबद्ध करना चाहते हैं, लेकिन बिना cruddy गैर मानव अनुकूल नाम का उपयोग किए बिना, तो आप यह कर सकते हैं ...

object.errors.each do |attr,message|
  puts "<li>"+message+"</li>"
end

1

आपके विचार में

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

जब आप विशेषता नाम के बिना त्रुटि संदेश को ओवरराइड करना चाहते हैं, तो बस संदेश को ^ जैसे के साथ प्रीपेन्ड करें:

validates :last_name,
  uniqueness: {
    scope: [:first_name, :course_id, :user_id],
    case_sensitive: false,
    message: "^This student has already been registered."
  }

रेल के साथ काम नहीं करता है 5.1 / रूबी 2.4? उस दायरे में मॉडल का नाम मिल रहा है
बेन

@ मेरे लिए रेल पर काम करता है 5.1.2, रूबी 2.4.1p111। क्या आप अपना कोड साझा कर सकते हैं?
किस्मत

मुझे लगता है कि मुझे आगे देखना होगा, आप कोड की जांच कर सकते हैं और उसका जवाब stackoverflow.com/q/45128434/102133
बेन

0

मैंने कोशिश की, मेरे लिए काम किया :)

1 नौकरी .rb

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

2 जॉब्स_कंट्रोलर.आरबी

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

यहाँ मेरा कोड है जो आपके लिए उपयोगी हो सकता है यदि आपको अभी भी इसकी आवश्यकता है: मेरा मॉडल:

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

फिर मैंने संदेश दिखाने के लिए एक सहायक बनाया है:

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

एक अनोखा तरीका मैंने किसी का उल्लेख नहीं देखा है!

जिस तरह से मैं चाहता था कि सभी अनुकूलन प्राप्त करने में सक्षम था, after_validationमुझे त्रुटि संदेश में हेरफेर करने की अनुमति देने के लिए कॉलबैक का उपयोग करना था ।

  1. सत्यापन संदेश को सामान्य बनाने की अनुमति दें, आपको सत्यापन सहायक में इसे आज़माने और बदलने की आवश्यकता नहीं है।

  2. after_validationकॉलबैक बनाएँ जो दृश्य में आने से पहले उस सत्यापन संदेश को बैक-एंड में बदल देगा।

  3. में after_validationविधि आप सिर्फ एक सामान्य स्ट्रिंग की तरह कुछ भी आप सत्यापन संदेश के साथ चाहते हैं कर सकते हैं,! तुम भी गतिशील मूल्यों का उपयोग करें और उन्हें सत्यापन संदेश में सम्मिलित कर सकते हैं।


#this could be any validation
validates_presence_of :song_rep_xyz, :message => "whatever you want - who cares - we will replace you later"

after_validation :replace_validation_message

def replace_validation_message
    custom_value = #any value you would like
    errors.messages[:name_of_the_attribute] = ["^This is the replacement message where 
    you can now add your own dynamic values!!! #{custom_value}"]
end

After_validation पद्धति में रेल वेलिडेशन हेल्पर की तुलना में कहीं अधिक स्कोप होगा, जिससे आप ऑब्जेक्ट को वैसी एक्सेस कर पाएंगे जैसे आप ऑब्जेक्ट के साथ करने की कोशिश कर रहे हैं। जहां आप इसे कॉल करने का प्रयास कर रहे हैं, वह सत्यापन सहायक में काम नहीं करता है।

नोट: हम ^सत्यापन की शुरुआत में विशेषता नाम से छुटकारा पाने के लिए उपयोग करते हैं क्योंकि @Rystraum ने इस मणि को संदर्भित किया है


0

ग्रेव का जवाब सबसे अच्छा है अगर यह वास्तव में क्षेत्र का नाम प्रदर्शित करने में भिन्न है। डायनामिक फ़ील्ड नाम (प्रदर्शित करने के लिए अन्य क्षेत्रों के आधार पर) के मामले में, मैं ऐसा कुछ करूँगा

<% object.errors.each do |attr, msg| %>
<li>
  <% case attr.to_sym %>
  <% when :song_rep_xyz %>
    <%= #display error how you want here %>
  <% else %>
    <%= object.errors.full_message(attr, msg) %>
  <% end %>
</li>
<% end %>

अन्य पर full_message पद्धति वह है जो full_messages विधि के अंदर रेल का उपयोग करते हैं, इसलिए यह अन्य मामलों के लिए सामान्य रेल त्रुटियों को छोड़ देगा (रेल 3.2 और ऊपर)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.