الفرق بين المراجعتين لصفحة: «Rails/active model basics»
جميل-بيلوني (نقاش | مساهمات) إنشاء الصفحة. هذه الصفحة من مساهمات "دعاء فرح" |
جميل-بيلوني (نقاش | مساهمات) لا ملخص تعديل |
||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:أساسيات | <noinclude>{{DISPLAYTITLE:أساسيات Active Model في ريلز}}</noinclude> | ||
[[تصنيف:Rails]] | [[تصنيف:Rails]] | ||
[[تصنيف:Rails Models]] | [[تصنيف:Rails Models]] | ||
يجب أن يوفر لك هذا الدليل كل ما تحتاج إليه للبدء في استخدام أصناف | يجب أن يوفر لك هذا الدليل كل ما تحتاج إليه للبدء في استخدام أصناف Model. يسمح Active Model لمساعدي Action Pack بالتفاعل مع كائنات [[Ruby|روبي]] الصرفة. يساعد Active Model أيضًا على إنشاء [[Rails/active record basics#.D8.A7.D9.84.D8.B3.D8.AC.D9.84 .D8.A7.D9.84.D9.81.D8.B9.D8.A7.D9.84 .D9.83.D8.A5.D8.B7.D8.A7.D8.B1 .D8.B9.D9.85.D9.84 ORM|قواعد بيانات ORM]] مخصصة للاستخدام خارج إطار ريلز. | ||
بعد قراءة هذا الدليل، ستتعلم: | بعد قراءة هذا الدليل، ستتعلم: | ||
* كيف يعمل نموذج [[Rails/active record basics| | * كيف يعمل نموذج [[Rails/active record basics|Active Record]]. | ||
* كيف تعمل [[Rails/active record callbacks|ردود النداء]] و<nowiki/>[[Rails/active record validations|عمليات التحقق]]. | * كيف تعمل [[Rails/active record callbacks|ردود النداء]] و<nowiki/>[[Rails/active record validations|عمليات التحقق]]. | ||
* كيف تعمل المُسَلسِلات (serializers). | * كيف تعمل المُسَلسِلات (serializers). | ||
* كيف يتكامل | * كيف يتكامل Active Model مع [[Rails/i18n|إطار تدويل]] ريلز (i18n). | ||
== مقدمة == | == مقدمة == | ||
Active Model هو مكتبة تحتوي على وحدات مختلفة تستخدم في تطوير الأصناف التي تحتاج إلى بعض الميزات الموجودة في [[Rails/active record basics|Active Record]]. بعض هذه الوحدات مشروحة أدناه. | |||
=== توابع الخاصيات === | === توابع الخاصيات === | ||
سطر 42: | سطر 42: | ||
=== ردود النداء === | === ردود النداء === | ||
تعطي الوحدة <code>ActiveModel::Callbacks</code> ردود نداء بنمط | تعطي الوحدة <code>ActiveModel::Callbacks</code> ردود نداء بنمط Active Record. هذا يوفر القدرة على تحديد ردود النداء التي تعمل في الأوقات المناسبة. بعد تحديد ردود النداء، يمكنك تغليفها قبل، وبعد، وحول توابع مخصصة.<syntaxhighlight lang="rails"> | ||
class Person | class Person | ||
extend ActiveModel::Callbacks | extend ActiveModel::Callbacks | ||
سطر 154: | سطر 154: | ||
=== التحقق من الصحة === | === التحقق من الصحة === | ||
تضيف الوحدة <code>ActiveModel::Validations</code> القدرة على التحقق من صحة الكائنات كما في [[Rails/active record validations| | تضيف الوحدة <code>ActiveModel::Validations</code> القدرة على التحقق من صحة الكائنات كما في [[Rails/active record validations|Active Record]].<syntaxhighlight lang="rails"> | ||
class Person | class Person | ||
سطر 198: | سطر 198: | ||
=== الوحدة Model === | === الوحدة Model === | ||
تضيف الوحدة <code>ActiveModel::Model</code> المقدرة للصنف على العمل مع | تضيف الوحدة <code>ActiveModel::Model</code> المقدرة للصنف على العمل مع Action Pack و [[Rails/action view overview|Action View]] مباشرةً خارج الصندوق.<syntaxhighlight lang="rails"> | ||
class EmailContact | class EmailContact | ||
include ActiveModel::Model | include ActiveModel::Model | ||
سطر 216: | سطر 216: | ||
* الترجمة. | * الترجمة. | ||
* التحقق من الصحة. | * التحقق من الصحة. | ||
كما يمنحك القدرة على تهيئة كائن بجدول <code>[[Ruby/Hash|Hash]]</code> من الخاصيات، مثل أي كائن | كما يمنحك القدرة على تهيئة كائن بجدول <code>[[Ruby/Hash|Hash]]</code> من الخاصيات، مثل أي كائن Active Record:<syntaxhighlight lang="rails"> | ||
email_contact = EmailContact.new(name: 'David', | email_contact = EmailContact.new(name: 'David', | ||
email: 'david@example.com', | email: 'david@example.com', | ||
سطر 224: | سطر 224: | ||
email_contact.valid? # => true | email_contact.valid? # => true | ||
email_contact.persisted? # => false | email_contact.persisted? # => false | ||
</syntaxhighlight>يمكن استخدام أي صنف يتضمن <code>ActiveModel::Model</code> مع <code>form_for</code>، و <code>render</code>، وأي تابع مساعد آخر [[Rails/action view overview| | </syntaxhighlight>يمكن استخدام أي صنف يتضمن <code>ActiveModel::Model</code> مع <code>form_for</code>، و <code>render</code>، وأي تابع مساعد آخر [[Rails/action view overview|Action View]]، تمامًا مثل كائنات Active Record. | ||
=== السَلسَلة === | === السَلسَلة === | ||
سطر 246: | سطر 246: | ||
==== <code>ActiveModel::Serializers</code> ==== | ==== <code>ActiveModel::Serializers</code> ==== | ||
كما يوفر | كما يوفر Active Model الوحدة <code>ActiveModel::Serializers::JSON</code> لإجراء عملية السَلسَلة أو إلغائها مع صيغة JSON. يتضمن هذا النموذج تلقائيًا الوحدة <code>ActiveModel::Serialization</code> الذي تحدثنا عنه آنفًا. | ||
===== <code>ActiveModel::Serializers::JSON</code> ===== | ===== <code>ActiveModel::Serializers::JSON</code> ===== | ||
سطر 306: | سطر 306: | ||
=== اختبارات الأداة Lint === | === اختبارات الأداة Lint === | ||
يتيح لك النموذج <code>ActiveModel::Lint::Tests</code> التحقق ما إذا كان كائنٌ ما متوافقًا مع واجهة | يتيح لك النموذج <code>ActiveModel::Lint::Tests</code> التحقق ما إذا كان كائنٌ ما متوافقًا مع واجهة Active Model البرمجية: | ||
* الملف app/models/person.rb | * الملف app/models/person.rb | ||
<syntaxhighlight lang="rails"> | <syntaxhighlight lang="rails"> | ||
سطر 336: | سطر 336: | ||
6 runs, 30 assertions, 0 failures, 0 errors, 0 skips | 6 runs, 30 assertions, 0 failures, 0 errors, 0 skips | ||
</syntaxhighlight>الكائن غير مطلوب لتنفيذ جميع واجهات برمجة التطبيقات لكي يعمل مع | </syntaxhighlight>الكائن غير مطلوب لتنفيذ جميع واجهات برمجة التطبيقات لكي يعمل مع Action Pack. تعتزم هذه الوحدة فقط توفير الإرشاد في حال كنت تريد جميع الميزات من خارج الصندوق. | ||
=== <code>SecurePassword</code> === | === <code>SecurePassword</code> === |
مراجعة 17:53، 19 مارس 2019
يجب أن يوفر لك هذا الدليل كل ما تحتاج إليه للبدء في استخدام أصناف Model. يسمح Active Model لمساعدي Action Pack بالتفاعل مع كائنات روبي الصرفة. يساعد Active Model أيضًا على إنشاء قواعد بيانات ORM مخصصة للاستخدام خارج إطار ريلز.
بعد قراءة هذا الدليل، ستتعلم:
- كيف يعمل نموذج Active Record.
- كيف تعمل ردود النداء وعمليات التحقق.
- كيف تعمل المُسَلسِلات (serializers).
- كيف يتكامل Active Model مع إطار تدويل ريلز (i18n).
مقدمة
Active Model هو مكتبة تحتوي على وحدات مختلفة تستخدم في تطوير الأصناف التي تحتاج إلى بعض الميزات الموجودة في Active Record. بعض هذه الوحدات مشروحة أدناه.
توابع الخاصيات
تضيف الوحدة ActiveModel::AttributeMethods
البادئات واللاحقة المخصصة إلى توابع صنف. تُستخدَم عن طريق تحديد البادئات واللاحقات وأي توابع ستستخدمهم على الكائن.
class Person
include ActiveModel::AttributeMethods
attribute_method_prefix 'reset_'
attribute_method_suffix '_highest?'
define_attribute_methods 'age'
attr_accessor :age
private
def reset_attribute(attribute)
send("#{attribute}=", 0)
end
def attribute_highest?(attribute)
send(attribute) > 100
end
end
person = Person.new
person.age = 110
person.age_highest? # => true
person.reset_age # => 0
person.age_highest? # => false
ردود النداء
تعطي الوحدة ActiveModel::Callbacks
ردود نداء بنمط Active Record. هذا يوفر القدرة على تحديد ردود النداء التي تعمل في الأوقات المناسبة. بعد تحديد ردود النداء، يمكنك تغليفها قبل، وبعد، وحول توابع مخصصة.
class Person
extend ActiveModel::Callbacks
define_model_callbacks :update
before_update :reset_me
def update
run_callbacks(:update) do
# على كائن update يُستدعَى هذا التابع عند استدعاء
end
end
def reset_me
# على كائن update يُستدعى هذا التابع عند استدعاء
# before_update كما يعرف رد النداء
end
end
التحويلات
إذا عرَّف صنفٌ التابعين ?persisted
و id
، فيمكنك تضمين الوحدة ActiveModel::Conversion
في ذلك الصنف، واستدعاء توابع التحويل في ريلز على كائنات ذلك الصنف.
class Person
include ActiveModel::Conversion
def persisted?
false
end
def id
nil
end
end
person = Person.new
person.to_model == person # => true
person.to_key # => nil
person.to_param # => nil
التلوث
يصبح الكائن متلوثًا عندما يمر بتغيير واحد أو أكثر لإحدى خاصياته دون حفظها. تعطي الوحدة ActiveModel::Dirty
القدرة على التحقق ما إذا تغير كائن أم لا. كما أن لديه خاصية تستند على توابع الوصول (accessor methods). دعنا نفترض وجود الصنف Person
مع الخاصيتين first_name
و last_name
:
class Person
include ActiveModel::Dirty
define_attribute_methods :first_name, :last_name
def first_name
@first_name
end
def first_name=(value)
first_name_will_change!
@first_name = value
end
def last_name
@last_name
end
def last_name=(value)
last_name_will_change!
@last_name = value
end
def save
# do save work...
changes_applied
end
end
الاستعلام عن الكائن مباشرة من أجل قائمة جميع خاصياته التي تغيرت
person = Person.new
person.changed? # => false
person.first_name = "First Name"
person.first_name # => "First Name"
# إذا كان أي من الخاصيات تحتوي على تغييرات لم تحفظ true يعيد القيمة
person.changed? # => true
# يعيد قائمة بالخاصيات التي تغيرت قبل الحفظ
person.changed # => ["first_name"]
# للخاصيات التي تغيرت مع قيمها الأصلية Hash يعيد جدول
person.changed_attributes # => {"first_name"=>nil}
# للتغييرات، مع أسماء الخاصيات كمفاتيح Hash يعيد جدول
# والقيم كمصفوفة للقيم القديمة والجديدة لهذا الحقل
person.changes # => {"first_name"=>[nil, "First Name"]}
توابع الوصول المستندة على الخاصية
تتبع ما إذا كان قد تغيرت خاصية معينة أم لا:
# attr_name_changed?
person.first_name # => "First Name"
person.first_name_changed? # => true
تتبع القيمة السابقة للخاصية:
# attr_name_was accessor
person.first_name_was # => nil
تتبع كل من القيمة السابقة والحالية للخاصية التي تغيرت. يعيد التابع مصفوفة في حالة تغييرها، وإلا يعيد القيمة nil
:
# attr_name_change
person.first_name_change # => [nil, "First Name"]
person.last_name_change # => nil
التحقق من الصحة
تضيف الوحدة ActiveModel::Validations
القدرة على التحقق من صحة الكائنات كما في Active Record.
class Person
include ActiveModel::Validations
attr_accessor :name, :email, :token
validates :name, presence: true
validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i
validates! :token, presence: true
end
person = Person.new
person.token = "2b1f325"
person.valid? # => false
person.name = 'vishnu'
person.email = 'me'
person.valid? # => false
person.email = 'me@vishnuatrai.com'
person.valid? # => true
person.token = nil
person.valid? # => raises ActiveModel::StrictValidationFailed
التسمية
تضيف الوحدة ActiveModel::Naming
عددًا من توابع الأصناف التي تجعل من السهل إدارة التسمية والتوجيه. تحدد الوحدة تابع الصنف class_name
الذي سيعرِّف عددًا من توابع الوصول (accessors) باستخدام بعض توابع ActiveSupport::Inflector
.
class Person
extend ActiveModel::Naming
end
Person.model_name.name # => "Person"
Person.model_name.singular # => "person"
Person.model_name.plural # => "people"
Person.model_name.element # => "person"
Person.model_name.human # => "Person"
Person.model_name.collection # => "people"
Person.model_name.param_key # => "person"
Person.model_name.i18n_key # => :person
Person.model_name.route_key # => "people"
Person.model_name.singular_route_key # => "person"
الوحدة Model
تضيف الوحدة ActiveModel::Model
المقدرة للصنف على العمل مع Action Pack و Action View مباشرةً خارج الصندوق.
class EmailContact
include ActiveModel::Model
attr_accessor :name, :email, :message
validates :name, :email, :message, presence: true
def deliver
if valid?
# توصيل بريد إلكتروني
end
end
end
عند تضمين ActiveModel::Model
، تحصل على بعض الميزات مثل:
- استبطان اسم نموذج (model name introspection).
- التحويلات.
- الترجمة.
- التحقق من الصحة.
كما يمنحك القدرة على تهيئة كائن بجدول Hash
من الخاصيات، مثل أي كائن Active Record:
email_contact = EmailContact.new(name: 'David',
email: 'david@example.com',
message: 'Hello World')
email_contact.name # => 'David'
email_contact.email # => 'david@example.com'
email_contact.valid? # => true
email_contact.persisted? # => false
يمكن استخدام أي صنف يتضمن ActiveModel::Model
مع form_for
، و render
، وأي تابع مساعد آخر Action View، تمامًا مثل كائنات Active Record.
السَلسَلة
توفر الوحدة ActiveModel::Serialization
عملية السَلسَلة الأساسية للكائن الخاص بك. يلزمك التصريح عن خاصيات Hash
تحتوي على الخاصيات التي تريد إجراء عملية سَلسَلة (serialize) لها. يجب أن تكون الخاصيات سلاسل نصية، وليست رموزًا.
class Person
include ActiveModel::Serialization
attr_accessor :name
def attributes
{'name' => nil}
end
end
الآن يمكنك الوصول إلى جدول Hash مُسَلسَل لكائنك باستخدام التابع serializable_hash
:
person = Person.new
person.serializable_hash # => {"name"=>nil}
person.name = "Bob"
person.serializable_hash # => {"name"=>"Bob"}
ActiveModel::Serializers
كما يوفر Active Model الوحدة ActiveModel::Serializers::JSON
لإجراء عملية السَلسَلة أو إلغائها مع صيغة JSON. يتضمن هذا النموذج تلقائيًا الوحدة ActiveModel::Serialization
الذي تحدثنا عنه آنفًا.
ActiveModel::Serializers::JSON
لاستخدام ActiveModel::Serializers::JSON
، تحتاج فقط إلى تغيير الوحدة التي تضمِّنها من ActiveModel::Serialization
إلى ActiveModel::Serializers::JSON
.
class Person
include ActiveModel::Serializers::JSON
attr_accessor :name
def attributes
{'name' => nil}
end
end
التابع as_json
مشابه للتابع serializable_hash
، إذ يوفر جدول Hash يمثِّل النموذج.
person = Person.new
person.as_json # => {"name"=>nil}
person.name = "Bob"
person.as_json # => {"name"=>"Bob"}
يمكنك أيضًا تعريف الخاصيات لنموذج من سلسلة JSON نصية. ومع ذلك، تحتاج إلى تعريف التابع attributes=
في الصنف الخاصة بك:
class Person
include ActiveModel::Serializers::JSON
attr_accessor :name
def attributes=(hash)
hash.each do |key, value|
send("#{key}=", value)
end
end
def attributes
{'name' => nil}
end
end
الآن، من الممكن إنشاء نسخة من Person
وتعيين الخاصيات باستخدام from_json
.
json = { name: 'Bob' }.to_json
person = Person.new
person.from_json(json) # => #<Person:0x00000100c773f0 @name="Bob">
person.name # => "Bob"
الترجمة
توفر الوحدة ActiveModel::Translation
التكامل بين الكائن الخاص بك وإطار تدويل ريلز (i18n).
class Person
extend ActiveModel::Translation
end
باستخدام التابع human_attribute_name
، يمكنك تحويل أسماء الخاصيات إلى تنسيق أكثر قابلية للقراءة. يُعرف التنسيق القابل للقراءة في ملف(ات) المحلية الخاص بك.
- الملف config/locales/app.pt-BR.yml
pt-BR:
activemodel:
attributes:
person:
name: 'Nome'
Person.human_attribute_name('name') # => "Nome"
اختبارات الأداة Lint
يتيح لك النموذج ActiveModel::Lint::Tests
التحقق ما إذا كان كائنٌ ما متوافقًا مع واجهة Active Model البرمجية:
- الملف app/models/person.rb
class Person
include ActiveModel::Model
end
- الملف test/models/person_test.rb
require 'test_helper'
class PersonTest < ActiveSupport::TestCase
include ActiveModel::Lint::Tests
setup do
@model = Person.new
end
end
$ rails test
Run options: --seed 14596
# Running:
......
Finished in 0.024899s, 240.9735 runs/s, 1204.8677 assertions/s.
6 runs, 30 assertions, 0 failures, 0 errors, 0 skips
الكائن غير مطلوب لتنفيذ جميع واجهات برمجة التطبيقات لكي يعمل مع Action Pack. تعتزم هذه الوحدة فقط توفير الإرشاد في حال كنت تريد جميع الميزات من خارج الصندوق.
SecurePassword
توفر الوحدة ActiveModel::SecurePassword
طريقةً لتخزين أي كلمة مرور بشكل آمن في نموذج مشفر (encrypted form). عند تضمين هذه الوحدة، يُوفَّر تابع الصنف has_secure_password
الذي يعرِّف تابع الوصول password
مع بعض عمليات التحقق من الصحة عليه.
المتطلبات
تعتمد الوحدة ActiveModel::SecurePassword
على bcrypt، لذا ضمِّن هذه الجوهرة في Gemfile الخاص بك لاستخدام الوحدة ActiveModel::SecurePassword
بشكل صحيح. لجعلها تعمل، يجب أن يكون لدى النموذج تابع وصول يدعى password_digest
. سيضيف has_secure_password
عمليات التحقق التالية على تابع الوصول password
:
1 - كلمة المرور يجب أن تكون موجودة.
2 - يجب أن تكون كلمة المرور مساوية لتأكيدها (يُمرَّر password_confirmation
المعطى).
3 - الحد الأقصى لطول كلمة المرور هو 72 (مطلوب بواسطة bcrypt
التي تعتمد ActiveModel::SecurePassword
عليه).
أمثلة
class Person
include ActiveModel::SecurePassword
has_secure_password
attr_accessor :password_digest
End
person = Person.new
# عندما تكون كلمة المرور فارغة
person.valid? # => false
# عندما لا يتطابق التأكيد مع كلمة المرور
person.password = 'aditya'
person.password_confirmation = 'nomatch'
person.valid? # => false
# عندما يتجاوز طول كلمة المرور 72
person.password = person.password_confirmation = 'a' * 100
person.valid? # => false
# password_confirmation عندما تتوفر كلمة المرور فقط بدون
person.password = 'aditya'
person.valid? # => true
# عندما تُمرَّر جميع عمليات التحقق من الصحة
person.password = person.password_confirmation = 'aditya'
person.valid? # => true