البحث في الموقع
المحتوى عن 'مساعدات'.
-
في الدرس السابق ألقينا نظرة عامة حول التحقيقات في 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 هي “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: القيمة المضافة يجب أن تكون زوجية رسالة الخطأ الافتراضية هى “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 رسالة الخطأ الافتراضية هي “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 يأخذ مساعد 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.