إن التهجير من أهم مزايا Active Record، حيث يسمح لك بتطوير قاعدة البيانات بسهولة مع مرور الزمن. فبدلًا من إعادة كتابة مُخططات قاعدة البيانات بسطور SQL من جديد، سيسمح لك التهجير باستعمال كود Ruby موحد المجال Domain – specific language لوصف التعديلات اللازمة التي ستقوم بها على جداولك.
1 نظرة عامة على التهجير
التهجير هو الطريقة الملائمة لتبديل أجزاء و مُخططات قاعدة البيانات بمرور الزمن بطريقة سهلة و متناسقة. ونقوم بإستعمال لُغة Ruby موحدة المجال DSL بدلًا من كتابة العديد من سطور SQL مما يسمح للتغيرات بأن تكون مُستقلة تمامًا عن قاعدة البيانات و لا تؤثر عليها سلبًا. يُمكنك التفكير في التهجير على أنه عمل تحديث جديد لقاعدة البيانات. ففي بداية الإسكيما تكون فارغة، ثُم بعد ذلك تقوم عمليات التهجير بإضافة الجداول، العواميد، أو المدخلات. و Active Record يقوم بعمل هذه التحديثات على الإسكيما من الحالة التي كانت عليها قبل التحديث (أو في النُسخة السابقة). كما سيقوم Active Record بتحديث ملف db/schema.rb
ليُناسب بناء قاعدة البيانات بعد التحديث.
مثال على التهجير
class CreateProducts < ActiveRecord::Migration[5.0] def change create_table :products do |t| t.string :name t.text :description t.timestamps end end end
في المثال السابق، قُمنا بعملية تهجير حيث أضفنا جدول جديد يُسمى products
يحتوي على عامود نصي يُسمى name
و عامود آخر يُسمى description
. وسيتم إضافة عامود مفتاح أساسي يُسمى id ضمنيًا، لأنه –كما علمنا من قبل- المفتاح الرئيسي الإفتراضي لجميع نماذج Active Record. آما أمر timestamps
يُضيف عامودين، صُنع في created_at
وتم تحديثه في updated_at
. و تلك العواميد الخاصة يتم إدارتها و تحديثها تلقائيًا بواسطة Active Record. لاحظ أن عملية التغير التي نقوم بها تتحرك أمامًا مع مرور الوقت، فقبل تشغيل التهجير run migration
لن يوجد لدينا ذلك الجدول، و بمجرد تشغيل كود التهجير سنحصل على الجدول، و العكس صحيح! فإن Active Record يُمكنه عكس عملية التهجير بإستخدام أمر العودة Roll back
و سيُحذف الجدول الجديد. بعض قواعد البيانات تدعم الصفقات Transactions* مع التغيرات التي تحدث للإسكيما. خاصية التهجير مُحاطة بتلك الصفقات Transactions. و لكن إذا كانت قاعدة البيانات لا تسمح بالصفقات، فإن التهجير سيقوم بإلغاء الأجزاء التي لم تطرأ عليها تلك التغيرات.
اقتباس*الصفقات Transaction هي سلسلة من العمليات تتم على وحدة مُفردة من قاعدة البيانات. و تكون مُستقلة تمامًا عن باقي العمليات.
اقتباسمثال: بعض السجلات Queries لا تعمل داخل تلك الصفقات، فيمكنك تعطيل خاصية تلك الصفقات Transactions بإستخدام الأمر
disable_ddl_transaction!
ثُم يُمكنك إستخدام التهجير بعد ذلك.
أما إذا رغبت بعمل التهجير على شيئًا ما، لا يدعم Active Record العمليات العكسية بهذا الشيئ، فُيمكنك إستخدام أمرreversible
.
class ChangeProductsPrice < ActiveRecord::Migration[5.0]
def change
reversible do |dir|
change_table :products do |t|
dir.up { t.change :price, :string }
dir.down { t.change :price, :integer }
end
end
end
end
و بدلًا من إستخدام أمر change
ستستخدم أوامر up
و down
.
class ChangeProductsPrice < ActiveRecord::Migration[5.0]
def up
change_table :products do |t|
t.change :price, :string
end
end
def down
change_table :products do |t|
t.change :price, :integer
end
end
end
2 إنشاء التهجير
2.1 إنشاء تهجير مُستقل و مُنفرد بنفسه
إن عمليات التهجير تكون مُخزنة داخل ملف يوجد في db/migrate
، و يوجد ملف لكل عملية تهجير حدثت على فئة مُعينة class
. إسم الملف يتخذ الصيغة الآتية YYYYMMDDHHMMSS_creat_products.rb
و هي تحتوي على صيغة الوقت التي حدث فيه التهجير، ثم علامة “_” ثم إسم عملية التهجير. إن هذا الإسم يجب أن يُطابق إسم الفئة class
التي لحق بها, فعلى سبيل المثال، إن كان إسم التهجير 20080906120000_creat_products.rb
فيجب أن يُعرف فئة class
إسمها CreatProducts. آما بالنسبة للوقت المُلحق بالإسم، فإن Rails تستعمله لترتيب التهجيرات و ترتيب كيفية عملها. لذلك إذا قُمت بنسخ تهجير ما من تطبيق آخر. فيجب أن تلتفت لهذا الأمر. و حساب الوقت بالضبط أي الدقيقة و الثانية لأمرٌ صعب. لذلك يوفر Active Record مولد لصُنع هذا الأمر.
$ bin/rails generate migration AddPartNumberToProducts
سيصنع الكود أعلاه تهجير فارغ، لكنه مُسمى بتسمية صحيحة.
class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
def change
end
end
إذا كان التهجير على هيئة AddXXXToYYY
أو RemoveXXXfromYYY
أي يحتوي على أوامر إضافة أو حذف و يحتوي أيضًا على عواميد تحتوي على الأسماء names
و الأنواع types
، فسيتم صُنع عواميد مُناسبة مثل add_column
و remove_column
. و الكود أدناه مثال على ذلك.
$ bin/rails generate migration AddPartNumberToProducts part_number:string
سينتج عنه:
class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :part_number, :string
end
end
و يُمكنك أيضًا عمل فهرسة للعواميد الجديدة.
$ bin/rails generate migration AddPartNumberToProducts part_number:string:index
سينتج عنه:
class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :part_number, :string
add_index :products, :part_number
end
end
و بنفس الطريقة يُمكنك عمل تهجير ليزيل عامود بإستخدام هذا الكود.
$ bin/rails generate migration RemovePartNumberFromProducts part_number:string
سينتج عنه:
class RemovePartNumberFromProducts < ActiveRecord::Migration[5.0]
def change
remove_column :products, :part_number, :string
end
end
كما أنك لست مُقيد بنوع واحد من العواميد لإنتاجه، مثال على ذلك
$ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
سينتج عنه
class AddDetailsToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :part_number, :string
add_column :products, :price, :decimal
end
end
لاحظ هُنا تحديد نوع البيانات الذي قُمنا به أما إذا كان التهجير يتخذ صيغة CreateXXX
و مُتبع بقائمة بأسماء و أنواع العواميد، فإن التهجير سيقوم بعمل جدول XXX
يحتوي على تلك العواميد، مثال:
$ bin/rails generate migration CreateProducts name:string part_number:string
و هذا سينتج عنه:
class CreateProducts < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.string :name
t.string :part_number
end
end
end
وكالعادة، فإنه يُمكنك تعديل ما يتم توليده من قبل التهجير عن طريق الإضافة و الحذف. عند طريق التعديل على هذا الملف db/migrate/YYYMMDDHHMMSS_add_details_to_products.rb
، على سبيل المثال:
$ bin/rails generate migration AddUserRefToProducts user:references
و هذا سينتج عنه:
class AddUserRefToProducts < ActiveRecord::Migration[5.0]
def change
add_reference :products, :user, foreign_key: true
end
end
هذا التهجير سوف يصنع عامود user_id
مع فهرس مُناسب. و هُناك أيضًا العديد من الخيارات الأخرى لدالة add_reference
سنتطرق إليها فيما بعد. هذا الكود سيولد جداول مُدمجة Join tables
إذا إستعملت JoinTable
كجزء من إسم التهجير، مثال:
الجداول المُدمجة Join Tables
هي تجميع لعدد معين من العواميد من جدول واحد أو أكثر من جدول.
$ bin/rails g migration CreateJoinTableCustomerProduct customer product
و هذا سوف ينتج التهجير الآتي:
class CreateJoinTableCustomerProduct < ActiveRecord::Migration[5.0]
def change
create_join_table :customers, :products do |t|
# t.index [:customer_id, :product_id]
# t.index [:product_id, :customer_id]
end
end
end
2.2 موالدات النماذج
إن مولدات النماذج و الإسكافولد Model and Scaffold Generators يُمكنها صُنع التهجير المُناسب لإضافة نموذج جديد. حيث سيحتوي التهجير على التعليمات اللازمة لصناعة الجداول المُناسبة. فإذا حددت العواميد التي تريدها، سيتم إضافة سطور الكود اللازمة لإضافة تلك العواميد، مثال:
اقتباس** الإسكافولد Scaffold هو جزء من النمط البرمجي MVC حيثُ يُمكنك إختيار جزء مُعين من قاعدة البيانات للعمل عليه.
** النموذج Model : -حتى لا ننسى- فإنه الجزء الرئيسي من النمط البرمجي MVC و هو الجزء المسئول عن البيانات، المنطق في التعامل و أوامر التطبيقات، و هو مُنفصل تمامًا عن قاعدة البيانات.
$ bin/rails generate model Product name:string description:text
و ذلك سوف يصنع هذا التهجير:
class CreateProducts < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
و بالطبع يُمكنك إضافة أي عدد تشاءه
2.3 تعدية المُعدلات
يُمكنك كتابة كود لتعدي المُعدلات Modifiers لأنهم قد تُقيدك. فإذا قُمت بتشغيل هذا الكود:
$ bin/rails generate migration AddDetailsToProducts 'price:decimal{5,2}' supplier:references{polymorphic}
سوف يُنتج هذا التهجير:
class AddDetailsToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :price, :decimal, precision: 5, scale: 2
add_reference :products, :supplier, polymorphic: true
end
end
سنتابع في الدروس القادمة بقية أجزاء دليل تعليم Active Record Migrations..
المصدر:
توثيقات Ruby on Rails.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.