(मैंने कुछ महीने पहले इस पोस्ट को अपनी सूची में भेजा था। यदि आप इसे पसंद करते हैं, और इसे और अधिक पढ़ना चाहते हैं, तो आपको साइन अप करना चाहिए!)
मैं दूसरे दिन अपने एक ऐप के साथ एक अजीब स्थिति में फंस गया।
मान लें कि आपके पास Article
है मॉडल, और इन लेखों को पहले ड्राफ्ट के रूप में बनाया जाता है। ये ड्राफ्ट हल्के होने चाहिए। आप चाहते हैं कि आप उन्हें बिना किसी बॉडी, या यहां तक कि एक शीर्षक के तुरंत ही बना और संपादित कर सकें।
लेकिन जब आप प्रकाशित . करते हैं इन लेखों के लिए, आपको कुछ अतिरिक्त सत्यापन की आवश्यकता है। उनके पास एक शीर्षक, एक बॉडी और बाकी सभी चीजें होनी चाहिए।
आप if
. का एक गुच्छा लिख सकते हैं स्वयं जाँच करने के लिए कथन। लेकिन आपके पास रेल से प्राप्त होने वाले सभी अच्छे फॉर्म नहीं होंगे। और मैंने पाया है कि रेल जिन चीजों को अच्छी तरह से संभालता है, उनके लिए रेल के साथ जाने से आपको बाद में बहुत सारे सिरदर्द से बचा जा सकेगा। क्या इसके लिए अभी भी सत्यापन का उपयोग करने का कोई तरीका है?
if
और unless
?
सत्यापन समर्थन :if
और :unless
पैरामीटर, लेकिन यह हमेशा इतना साफ नहीं होता है:
class Article < ActiveRecord::Base
# validate in draft mode
validates_presence_of :author_id
# validate only when published
validates_presence_of :body, unless: lambda { |o| o.draft? }
...
end
इसके अलावा, मैं इस तरह से कोई लेख प्रकाशित नहीं करना चाहता। मैं एक लेख को कार्रवाई . के रूप में प्रकाशित करने के बारे में सोचना चाहता हूं , नहीं एक राज्य लेख में है, इसलिए किसी विशेषता को सेट करना और जाँचना सही उत्तर नहीं है।
एक अल्पज्ञात, हल्के ढंग से प्रलेखित रेल सुविधा
यह समस्या रेल के सत्यापन संदर्भों के लिए एकदम उपयुक्त है। मैंने पहली बार कस्टम सत्यापन संदर्भों के बारे में एक जिस्ट डीएचएच ने लिखा था, उसके बारे में सीखा। लेकिन ये क्या थे, और इनका उपयोग कैसे करना है, इसकी एक अच्छी व्याख्या खोजना कठिन था।
कस्टम संदर्भों के लिए दस्तावेज़ीकरण बहुत पतला है। इसका एकमात्र उल्लेख मुझे एपीआई डॉक्स में मिल सकता है यहाँ । और इन सत्यापनों के लिए एपीआई दस्तावेज़ कस्टम संदर्भों का बिल्कुल भी उल्लेख नहीं करते हैं! इससे यह विशेष रूप से कठिन हो जाता है - यदि आप नहीं जानते कि किसी चीज़ को क्या कहा जाता है, तो आप उस पर अधिक दस्तावेज़ीकरण कैसे प्राप्त करते हैं?
मुझे अंत में यहाँ एक अच्छा अवलोकन मिला:https://blog.arkency.com/2014/04/mastering-rails-validations-contexts/। यह पढ़ने लायक है। आइए देखें कि यह हमारे उदाहरण के लिए कैसा दिखता है:
class Article < ActiveRecord::Base
# validate in draft mode
validates_presence_of :author_id
# validate only when published
validates_presence_of :body, on: :publish
...
end
class ArticleController < ApplicationController
respond_to :html
def create
@article = Article.create(article_params)
respond_with @article
end
def publish
@article = Article.find(params[:id])
@article.attributes = article_params
@article.save(context: :publish)
respond_with @article
end
private
def article_params
params.
require(:article).
permit(:body, :title, :author_id)
end
end
इतना भी बेकार नहीं! केवल अजीब चीज है save
. का उपयोग करना update
. के बजाय प्रकाशित विधि में। ऐसा इसलिए होता है क्योंकि update
एक पैरामीटर के रूप में एक सत्यापन संदर्भ नहीं ले सकता। (शायद यह एक पुल अनुरोध का अवसर है?)
बेयरिंग सेविंग
कस्टम सत्यापन संदर्भ केवल एक रिकॉर्ड को अलग-अलग तरीकों से सहेजने से कहीं अधिक के लिए उपयोगी होते हैं। प्रसंग valid?
. के साथ काम करते हैं :
@article.valid?(:publish)
इसलिए आप सत्यापन संदर्भों का उपयोग कहीं भी कर सकते हैं जहां आप प्रश्न का उत्तर देना चाहते हैं:“क्या इस वस्तु में यह गुण है? और अगर नहीं तो क्यों नहीं?"
DHH -able?
. में समाप्त होने वाली एक विधि बनाता है जो valid?(:context)
. को दर्शाता है ) मुझे उसका लुक बहुत पसंद है:
class Article
validate :has_been_published, on: :view
validate :is_not_spam, on: :view
def viewable?
valid? :view
end
private
def has_been_published
if published_at.future?
errors.add(:published_at, "is in the future")
end
end
def is_not_spam
if is_spam?(body)
errors.add(:body, "has been detected as spam")
end
end
end
इस तरह, जब आप इसकी जांच करते हैं, तो आपको true
. से अधिक जानकारी प्राप्त होती है या false
:
unless @article.viewable?
# @article.errors is now filled out
end
क्या लेख देखने योग्य है? अच्छा, क्यों नहीं?
बस काफी हल्का है
कुछ अन्य तरीके हैं जिनसे आप इस प्रकार का सत्यापन व्यवहार प्राप्त कर सकते हैं। आप कस्टम ActiveModel
बना सकते हैं service ऑब्जेक्ट्स अपने स्वयं के सत्यापन के साथ। आप :if
. का उपयोग कर सकते हैं या :unless
आपके सत्यापन पर। लेकिन रेल में बहुत सी चीजों की तरह, कस्टम सत्यापन संदर्भ पठनीयता और लचीलेपन के बीच एक अच्छा समझौता है।