المكتبة Active Model في ريلز

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

يوفر Active Model مجموعة معروفة من الواجهات لاستعمالها في أصناف النماذج (model classes). إنها تسمح لمساعدي Action Pack بالتفاعل مع النماذج التي ليست من Active Record مثلًا. يساعد Active Model في بناء روابط ORM مخصصة (تقنية ربط الكائنات بالعلاقات) للاستعمال خارج إطار ريلز.

يمكنك قراءة المزيد حول Active Model في دليل أساسيات Active Model.

قبل الإصدار 3.0 من ريلز، إن رغبت جوهرة أو رغب مطور بامتلاك كائن يتفاعل مع مساعدي Action Pack، فإنه يتطلب إمَّا نسخ أجزاء من شيفرة ريلز، أو استخدام ترقيع القرد (monkey patch) على كامل المساعدين لجعلهم يتعاملون مع كائنات لا تتوافق تمامًا مع واجهة Active Record. سيؤدي هذا إلى تكرارٍ في الشيفرة والحصول على تطبيق ضعيف، لذا جاءت الإصدارات اللاحقة مع Active Model الذي يحل هذه المعضلة عبر تعريف واجهة برمجية واضحة. يمكنك قراءة المزيد حول الواجهة البرمجية في ActiveModel::Lint::Tests.

يوفر Active Model وحدة افتراضية تُنفِّذ الواجهة البرمجية الأساسية المطلوبة لدمج وتكامل Active Model بشكل خارج عن ما هو متعارف عليه: ActiveModel::Model.
class Person
  include ActiveModel::Model

  attr_accessor :name, :age
  validates_presence_of :name
end

person = Person.new(name: 'bob', age: '18')
person.name   # => 'bob'
person.age    # => '18'
person.valid? # => true
إنه يتضمن استبطان، وتحويل، وتبديل، والتحقق من اسم النموذج مما يؤدي إلى خلق صنف مناسب للاستعمال مع Action Pack. اطلع على ActiveModel::Model لمزيد من الأمثلة.

يوفر Active Model أيضًا الوظائف التالية لتأمين سلوك شبيه بسلوك ORM:

  • إضافة خاصية سحرية (attribute magic) إلى الكائنات:
class Person
  include ActiveModel::AttributeMethods

  attribute_method_prefix 'clear_'
  define_attribute_methods :name, :age

  attr_accessor :name, :age

  def clear_attribute(attr)
    send("#{attr}=", nil)
  end
end

person = Person.new
person.clear_name
person.clear_age
  • ردود نداء لعمليات محدَّدة:
class Person
  extend ActiveModel::Callbacks
  define_model_callbacks :create

  def create
    run_callbacks :create do
      # هنا create ضع توابع الإجراء
    end
  end
end
هذا يولد التوابع الصنفية before_create، و around_create، و after_create التي تغلف التابع create الخاص بك.
  • تعقّب تغيرات قيمة:
class Person
  include ActiveModel::Dirty

  define_attribute_methods :name

  def name
    @name
  end

  def name=(val)
    name_will_change! unless val == @name
    @name = val
  end

  def save
    # do persistence work
    changes_applied
  end
end

person = Person.new
person.name             # => nil
person.changed?         # => false
person.name = 'bob'
person.changed?         # => true
person.changed          # => ['name']
person.changes          # => { 'name' => [nil, 'bob'] }
person.save
person.name = 'robert'
person.save
person.previous_changes # => {'name' => ['bob, 'robert']}
  • إضافة الواجهة errors للكائنات:
عرض رسائل خطأ يسمح للكائنات بالتفاعل مع مساعدي Action Pack بسلاسة.
class Person

  def initialize
    @errors = ActiveModel::Errors.new(self)
  end

  attr_accessor :name
  attr_reader   :errors

  def validate!
    errors.add(:name, "cannot be nil") if name.nil?
  end

  def self.human_attribute_name(attr, options = {})
    "Name"
  end
end

person = Person.new
person.name = nil
person.validate!
person.errors.full_messages
# => ["Name cannot be nil"]
  • استبطان اسم النموذج:
class NamedPerson
  extend ActiveModel::Naming
end

NamedPerson.model_name.name   # => "NamedPerson"
NamedPerson.model_name.human  # => "Named person"
  • جعل الكائنات قابلة للسَلسَلة (serializable):
يوفر ActiveModel::Serialization واجهة قياسية لكائنك لتوفير السَلسَلة to_json.
class SerialPerson
  include ActiveModel::Serialization

  attr_accessor :name

  def attributes
    {'name' => name}
  end
end

s = SerialPerson.new
s.serializable_hash   # => {"name"=>nil}

class SerialPerson
  include ActiveModel::Serializers::JSON
end

s = SerialPerson.new
s.to_json             # => "{\"name\":null}"
class Person
  extend ActiveModel::Translation
end

Person.human_attribute_name('my_attribute')
# => "My attribute"
  • دعم التحقق من الصحة:
class Person
  include ActiveModel::Validations

  attr_accessor :first_name, :last_name

  validates_each :first_name, :last_name do |record, attr, value|
    record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
  end
end

person = Person.new
person.first_name = 'zoolander'
person.valid?  # => false
  • دعم عمليات تحقق مخصصة للصحة:
class HasNameValidator < ActiveModel::Validator
  def validate(record)
    record.errors.add(:name, "must exist") if record.name.blank?
  end
end

class ValidatorPerson
  include ActiveModel::Validations
  validates_with HasNameValidator
  attr_accessor :name
end

p = ValidatorPerson.new
p.valid?                  # =>  false
p.errors.full_messages    # => ["Name must exist"]
p.name = "Bob"
p.valid?                  # =>  true

التنزيل والتثبيت

يمكن تثبيت أحدث إصدار من Active Model مع RubyGems:
$ gem install activemodel
يمكن أيضًا تنزيل الشيفرة المصدرية كجزء من مشروع ريلز في GitHub.

مصادر