ruby on rails 103 Active Record Validations: مساعدات التحقيقات


Muhammad Ashraf

في الدرس السابق ألقينا نظرة عامة حول التحقيقات في 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.





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن