في الدرس السابق ألقينا نظرة عامة حول التحقيقات في Active Record وسنتابع في هذا الدرس تعلم مساعدات التحقيقات
2 مساعدات التحقيقات validation helpers
يعرض Active Record العديد من مساعدات تحقيقات المعرفة مسبقًا التي يمكنك استخدامها مباشرة داخل تعريفات فئتك. تدعم تلك المساعدات قواعد تحقيقات شائعة. فى كل مرة يفشل تحقيق ، تضاف رسالة خطأ الى مجموعة أخطاء الكائن ، و ترتبط تلك الرسالة بالخاصية التي يتم التحقق منها. يقبل كل مساعد رقم اعتباطي من أسماء الخواص ، لذلك يمكنك إضافة نفس نوع التحقيق للعديد من الخواص بسطر كود واحد. جميعم يقبل خيارات on:
و message:
الاثنين يحددان متى يجب أن يتم اجراء التحقيق ، و أي رسالة يجب إضافتها إلى مجموعة الأخطاء فى حال فشلها ، على الترتيب. خيار ال on:
يأخذ القيم create:
(أنشىء) أو :update:
(حدّث). هناك رسالة خطأ افتراضية لكل واحد من مساعدات التحقيق. تُستَخدم تلك الرسائل عندما لا يكون خيار message:
محددًا. فلنأخذ نظرة على كل واحد من مساعدات التحقيق.
2.1 القبول acceptance
تتأكد هذه الطريقة اذا ما كان الـ checkbox فى واجهة تشغيل المستخدم معلّمًا عندما يتم إرسال أي نموذج. يتم استخدام هذه الطريقة غالبًا عندما يكون المستخدم بحاجة لقبول شروطك لتقديم الخدمة ، يؤكد على قراءة نص معيّن ، أو أي مفهوم مشابه.
class Person < ApplicationRecord validates :terms_of_service, acceptance: true end
يجري هذا الفحص فقط إذا كانت شروط العمل ليست nil. رسالة الخطأ الافتراضية لهذا المساعد هي “must be acceptd” أي يجب أن تقبل. يمكن أيضًا تجاوز الرسالة المخصصة من خلال خيار الرسالة message.
class Person < ApplicationRecord
validates :terms_of_service, acceptance: { message: 'must be abided' }
end
يمكن أيضًا أن تستقبل خيار accept:
التي تحدد القيم المسموح بها لأن تعتبر مقبولة. إنها تعود كما هو افتراضي إلى [`1` , true]
و يمكن أن تتغير بسهولة.
class Person < ApplicationRecord
validates :terms_of_service, acceptance: { accept: 'yes' }
validates :eula, acceptance: { accept: ['TRUE', 'accepted'] }
end
هذا التحقيق مخصص جدًا لتطبيقات المواقع و هذا “القبول” acceptance لا يحتاج إلى أن يسجّل في أي مكان بقاعدة البيانات. إذا لم يكن لديك مجال له ، سوف ينشىء المساعد خاصية افتراضية. إذا كان لا يوجد مجال في قاعدة بياناتك يجب أن يكون خيار القبول مفعّلًا أو يتضمن true
وإلا لن يجري التحقيق.
2.2 validates.associated مرتبط بالتحقيق
يجب أن تستخدم هذا المساعد عندما يكون لنموذجك ارتباطات بنماذج أخرى و هم أيضًا بحاجة إلى أن يتم التحقق منهم. عندما تحاول حفظ كائن ، ?valid سيتم استدعائها لكل واحد من الكائنات المرتبطة.
class Library < ApplicationRecord
has_many :books
validates_associated :books
end
هذا التحقيق سوف يعمل مع كل أنواع الارتباطات.
اقتباستحذير: لا تستخدم
validates_associated
على نهايتي الـ associations. ستقوم كل واحدة باستدعاء الأخرى فى دائرة لا متناهية.
رسالة الخطأ الافتراضية لـ validates_associated
هي “is invalid” أي غير صالح. لاحظ أن كل associated object لن يحتوي على مجموعة أخطائه ، الأخطاء لا تتصاعد إلى نموذج الاستدعاء.
2.3 التأكيد confirmation
يجب أن تستخدم هذا المساعد عندما يكون لديك حقول نصوص التي يجب أن تستقبل نفس المحتوى بالضبط. على سبيل المثال من الممكن أن تكون تريد التأكيد على عنوان بريد إلكتروني أو كلمة مرور. هذا التحقيق ينشىء خاصية افتراضية بنفس اسم الحقل الذي يجب أن يتم التأكيد عليه بـ”_confirmation” (تأكيد) مُلحق.
class Person < ApplicationRecord
validates :email, confirmation: true
end
فى قالب العرض خاصتك يمكن أن تستخدم شيئًا مثل:
<%= text_field :person, :email %>
<%= text_field :person, :email_confirmation %>
هذا الفحص يجري فقط إذا كان email_confirmation
ليس nil
. لكي تطلب معلومات تأكد من إضافة presence check لخاصية التأكيد:
class Person < ApplicationRecord
validates :email, confirmation: true
validates :email_confirmation, presence: true
end
يوجد خيار case_sensitive
الذي يمكنك استخدامه لتحدد إذا ما كان من قيود التأكيد أن يكون مستشعرًا لحالة الحروف أم لا (أي يفرق بين الحروف الـ capital و الـ small). والخيار الافتراضي له هو true
.
class Person < ApplicationRecord
validates :email, confirmation: { case_sensitive: false }
end
رسالة الخطأ الافتراضية لهذا المساعد هي “doesn’t match confirmation” أي لا يتوافق مع التأكيد.
2.4 استثناء exclusion
هذا المساعد يصدّق أن قيم الخواص ليست متضمّنة فى مجموعة معطاة. في الحقيقة ، تلك المجموعة يمكن أن تكون أي كائن غير قابل للعد.
class Account < ApplicationRecord
validates :subdomain, exclusion: { in: %w(www us ca jp),
message: "%{value} is reserved." }
end
يمتلك مساعد الاستثناء خيار in:
الذي يستقبل مجموعة من القيم التي لن تقبل الخصائص المتحقق منها. خاصية in:
لها اسم آخر متعارف عليه هو within:
و الذي يمكن استخدامه لنفس الوظيفة. هذا المثال يستخدم خيار message:
ليعرض كيف يمكن تضمين قيمة الخصّيصة. من أجل خيارات مفصّلة/كاملة لمتغير الرسالة. رسالة الخطأ الافتراضيّة هى “is reversed”
2.5 الشكل/التصميم format
هذا المساعد يتحقق من قيم الخواص باختبار اذا ما كانوا تطابق تعبير اعتيادي معطى ، الذي يتم تحديده باستخدام خيار with:
.
class Product < ApplicationRecord
validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
message: "only allows letters" }
end
بدلًا من ذلك يمكنك اختيار ألا تطابق الخواص المحددة expression معين باستخدام خيار without:
. رسالة الخطأ الافتراضية هى “is invalid” .
2.6 التضمين inclusion
هذا المساعد يتحقق أن قيم الخواص متضمنة فى مجموعة معينة. هذه المجموعة يمكن أن تكون أي كائن غير معدود.
class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} is not a valid size" }
end
مساعد التضمين inclusion helper لديه خيار in:
الذي يستقبل مجموعة من القيم التي ستكون مقبولة. خيار in:
لديه اسم آخر هو within:
الذي يمكن استخدامه بدلًا منه لنفس الوظيفة. يستخدم المثال السابق خيار الـ message:
ليبين كيف يمكن تضمين قيمة الخصّيصة. رسالة الخطأ الافتراضية لهذا المساعد هي “is not included in the list”.
2.7 الطول
هذا المساعد يتحقق من طول قيم الخصائص. إنه يدعم خيارات مختلفة حتى يتسنّى للمستخدم تحديد قيود الطول بطرق مختلفة.
class Person < ApplicationRecord
validates :name, length: { minimum: 2 }
validates :bio, length: { maximum: 500 }
validates :password, length: { in: 6..20 }
validates :registration_number, length: { is: 6 }
end
خيارات قيود الطول المتاحة هي:
-
minimum:
(أقل حد) الخاصية لا يمكن أن تكون أقل من الطول المحدد -
maximum:
(أقصى حد) الخاصية لا يمكن أن تكون أكثر من الطول المحدد. -
in: (أو within:)
(في حدود) طول الخاصية يجب أن يكون متضمن في أبعاد معيّنة. قيمة هذا الخيار يجب أن يكون نطاق/مدى. -
is:
(يساوي) طول الخاصية يجب أن يكون مساويًا للقيمة المعطاه.
رسالة الخطأ الافتراضيّة تعتمد على نوع تحقيق الطول المُجرى. يمكنك تخصيص هذه الرسائل باستخدام خيارات wrong_length:
(طول خطأ) و too_long:
(طويل جدًا) و too_short:
(قصير جدًا) ، و {count}
كماسك للمكان للرقم المناظر لقيد الطول المُستخدم. يمكنك أيضًا استخدام خيار message:
لتحدد رسالة الخطأ.
class Person < ApplicationRecord
validates :bio, length: { maximum: 1000,
too_long: "%{count} characters is the maximum allowed" }
end
لاحظ أن رسائل الأخطاء هي جمع (على سبيل المثال “قصير جدًا( الحد الأدنى هو {count}
أحرف)”). لهذا السبب عندما يكون الحد الأدنى هو 1 يجب أن توفر رسالة مخصصة أو استخدم presence : true
بدلًا من ذلك. عندما يمتلك in:
أو within:
حد أدنى 1 ينبغى عليك إما توفير رسالة خطأ مخصصة أو استدعاء presence طبقًا لأولوية الطول.
2.8 العددية numericality
هذا المساعد يتحقق أن خواصّك بها قيم عددية فقط. افتراضيّا ، سوف يقوم بالتحقق من وجود رقم صحيح integer أو عدد عشري floating point number. لتحدد السماح بالأرقام الصحيحة فقط اضبط only_integer:
على true
. إذا قمت بضبط only_integer:
على true
، ستقوم باستخدام:
/\A[+-]?\d+\z/
عبارة اعتيادية للتحقق من قيمة الخصيصة. فيما عدا ذلك ستقوم بتحويل القيمة الى رقم باستخدام float
.
class Player < ApplicationRecord
validates :points, numericality: true
validates :games_played, numericality: { only_integer: true }
end
بجانب only_integer:
هذا المساعد يقبل أيضًا هذه الخيارات لإضافة قيود على القيم المقبولة:
-
greater_than:
تحديد القيمة الصُغرى للقيمة المُضافة -
greater_than_or_equal_to:
تحديد القيمة الصُغرى مع إمكانية المساواة -
equal_to:
القيمة المُضافة يجب أن تساوي -
less_than:
تحديد القيمة الكُبرى للقيمة المضافة -
less_than_or_equal_to:
تحديد القيمة الكُبرى مع إمكانية المساواة -
other_than:
القيمة المُضافة يجب ألّا تساوي تلك القيمة -
Odd:
القيمة المضافة يجب أن تكون فردية -
Even:
القيمة المضافة يجب أن تكون زوجية
اقتباسملاحظة: الضبط الافتراضي للعددية لا يسمح بقيم nil. يمكنك استخدام خيار
allow_nil: true
للسماح بها.
رسالة الخطأ الافتراضية هى “is not a number” (ليس رقمًا).
2.9 وجود presence
هذا المساعد يتحقق أن الخصائص المحددة ليست فارغة. إنها تستخدم طريقة ?blank
لتكتشف إذا كانت القيمة إما nil
أو سلسلة فارغة blank string – و التي تكون سلسلة فارغة أو تتكون من مساحة.
class Person < ApplicationRecord
validates :name, :login, :email, presence: true
end
إذا أردت أن تتأكد أن الارتباطات موجودة سوف تحتاج أن تختبر إذا ما كان الكائن نفسه موجودًا ، و ليس المفتاح الخارجي المستخدم لتنظيم الارتباط.
class LineItem < ApplicationRecord
belongs_to :order
validates :order, presence: true
end
يجب أن تحدد خيار inverse:
للرابطة حتى تتحقق من السجلّات المرتبطة التي يجب أن تكون موجودة.
class Order < ApplicationRecord
has_many :line_items, inverse_of: :order
end
إذا تحققت من وجود كائن من خلال علاقة has_one
أو has_many
سوف يفحص إذا ما كان الكائن ليس ?blank
(فارغ) ولا marked_for_destruction
(محدد للمحو)
بما أن ?false.blank
صحيح ، ينبغى أن تستخدم أحد التحقيقات التالية إذا أردت التحقق من وجود حقل Boolean:
validates :boolean_field_name, inclusion: { in: [true, false] }
validates :boolean_field_name, exclusion: { in: [nil] }
باستخدام أحد هذه التحقيقات سوف تتأكد أن القيمة لن تكون nil
، مما سينتج عنه قيمة NULL فى أغلب الحالات.
2.10 الغياب absence
هذا المساعد يتحقق من أن الخصائص المحددة غائبة. إنها تستخدم وسيلة ?present
لتكتشف إذا ما كانت القيمة ليست nil
أو balnk string
class Person < ApplicationRecord
validates :name, :login, :email, absence: true
end
إذا أردت التأكد أن التصادق غائب ، سوف تحتاج أن تختبر ما إذا كان الكائن نفسه غائبا أم المفتاح الخارجي المستخدم لتنظيم الارتباط.
class LineItem < ApplicationRecord
belongs_to :order
validates :order, absence: true
end
حتى تتحقق من السجلات المتصادقة التي يلزم غيابها يجب أن تحدد خيار inverse_of:
للمصادقة.
class Order < ApplicationRecord
has_many :line_items, inverse_of: :order
end
إذا تحققت من غياب كائن من خلال علاقة has_one
أو has_many
، سوف تفحص إذا ما كان الكائن ليس ?present
أو ?marked_for_destruction
مردودا كـ false
. لو أردت التحقق من غياب حقل Boolean
ينبغي أن تستخدم {[validates :field_name, exclusion: {in: [true, false
.
رسالة الخطأ الافتراضية هى “must be blank”. أى يجب أن يكون فارغًا.
2.11 التفرّد/التميّز uniqueness
هذا المساعد يتحقق أن قيمة الخصيصة فريدة قبل حفظ الكائن مباشرة. إنها لا تنشىء قيد تفرّد uniqueness constraint في قاعدة البيانات ، لذلك من الممكن أن ينشىء قاعدتي بيانات مختلفتين سجلين مختلفين بنفس القيمة لعمود كنت تقصد جعله فريدًا. حتى تتجنّب ذلك يجب أن تنشىء مؤشّر متفرّد على هذا العمود في قاعدة بياناتك.
class Account < ApplicationRecord
validates :email, uniqueness: true
end
التحقق يحدث بإجراء SQL query في جدول الوسائل ، بحثًا عن سجل موجود بنفس القيمة التي في الخاصية.
يوجد خيار scope:
الذي يمكن استخدامه لتحديد خاصية أو أكثر تستخدم لتحديد فحص التفرّد.
class Holiday < ApplicationRecord
validates :name, uniqueness: { scope: :year,
message: "should happen once per year" }
end
إذا كنت تأمل فى إنشاء قيود في قاعدة البيانات لمنع أي انتهاك لتحقيق التفرّد باستخدام خيار scope:
، فعليك إنشاء فهرس فريد لكلا العمودين في قاعدة بياناتك. انظر the SQL manual لتفاصيل أكثر عن فهارس العواميد المتعددة أو the PostgresSQL manual لأمثلة على قيود فريدة تنطبق على مجموعة من الأعمدة. يوجد أيضًا خيار case_sensitive:
الذي يمكنك استخدامه لتحديد ما إذا كان قيد التفرّد سيكون حساسًا لحالة الأحرف أم لا. الضبط الافتراضي للخيار يكون ساري/صحيح true
.
class Person < ApplicationRecord
validates :name, uniqueness: { case_sensitive: false }
end
اقتباستحذير: لاحظ أن بعض قواعد البيانات تكون مضبوطة أن تجري أبحاث
case-sensitive
على أي حال.
رسالة الخطأ الافتراضية هي “has already been taken”. أي تم أخده بالفعل.
2.12 يتحقق بـ validates_with
هذا المساعد ينقل السجل إلى فئة مختلفة من التصديق/التحقيق.
class GoodnessValidator < ActiveModel::Validator
def validate(record)
if record.first_name == "Evil"
record.errors[:base] << "This person is evil"
end
end
end
class Person < ApplicationRecord
validates_with GoodnessValidator
end
اقتباسملاحظة: الأخطاء المضافة إلى
[ record.errors[ :base
تتصل بحالة السجل ككل و ليس لخصّيصة معيّنة.
يأخذ مساعد validates_with
فئة أو قائمة من الفئات لاستخدامها للتحقيق. لا يوجد رسالة افتراضية لرسائل الخطأ لـ validates_with
. يجب عليك أن تضيف الأخطاء إلى مجموعة أخطاء السجل في فئة المحقق يدويًّا. لكي تنفّذ وسيلة التحقيق يجب أن تعرّف معامل السجل ، و الذي هو السجل الذي سيتم التحقق منه. على غرار باقي التحقيقات validates_with
تأخذ خيارات if:
و unless:
و on:
. إذا جرّبت أي خيار آخر سيقوم بإرسال تلك الخيارات إلى فئة المتحقق كخيارات متاحة.
class GoodnessValidator < ActiveModel::Validator
def validate(record)
if options[:fields].any?{|field| record.send(field) == "Evil" }
record.errors[:base] << "This person is evil"
end
end
end
class Person < ApplicationRecord
validates_with GoodnessValidator, fields: [:first_name, :last_name]
end
لاحظ أن المتحقق سوف يبدأ مرة واحدة فقط في دائرة عمر التطبيق ، و ليس لكل إجراء تحققي ؛ لذلك كن حذرًا عند استخدام متغيرات مقترحة/تجريبية بداخله. لو كان متحققك معقّد كفاية لدرجة أنك تريد متغيرات instance يمكنك استخدام plain old Ruby object بسهولة بدلاً من ذلك:
class Person < ApplicationRecord
validate do |person|
GoodnessValidator.new(person).validate
end
end
class GoodnessValidator
def initialize(person)
@person = person
end
def validate
if some_complex_condition_involving_ivars_and_private_methods?
@person.errors[:base] << "This person is evil"
end
end
# ...
End
2.13 تحقق من الكل validates_each
هذا المساعد يتحقق من الخصائص مقابل block. إنها لا تمتلك وظيفة تحقيق معينة ، يجب أن تنشىء واحدة باستخدام block و كل خاصية تمر إلى validates_each
سوف تُختبر في مقابلها. في المثال التالي لا نريد الأسماء و أسماء العائلات أن تبدأ بحروف صغيرة.
class Person < ApplicationRecord
validates_each :name, :surname do |record, attr, value|
record.errors.add(attr, 'must start with upper case') if value =~ /\A[[:lower:]]/
end
end
الـ block يستقبل السجل و اسم الخاصية و قيمة الخاصية. يمكنك فعل أي شىء ، مثل الكشف عن البيانات الصالحة داخل الـ block. إذا فشلت تحقيقاتك ينبغي عليك إضافة رسالة خطأ إلى النموذج، و من ثم جعله غير ساري.
سنتابع في الدروس القادمة بقية هذا الدليل التعليمي حول Active Record Validations.
المصدر:
توثيقات Ruby on Rails.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.