البحث في الموقع
المحتوى عن 'create_tables'.
-
في الدرس السابق ألقينا نظرة عامة على تهجير Active Record وكيفية إنشائه وسنتابع في هذا الدرس تعلّم كيفية كتابة أوامره عبر صنع الجداول وتعديلها وغيرها. 3 كتابة أوامر التهجير بمجرد استخدامك للمولدات لتوليد التهجير، فسيتحتم عليك البدء بالعمل الحقيقي و كتابة أوامر التهجير. 3.1 صُنع الجداول إن دالة create_tables هي الأساسية لصنع الجداول، و لكن في مُعظم الأوقات ستقوم المولدات بإنتاج تلك الجداول كما رأينا في الأمثلة السابقة. مثال على صُنع جدول create_table :products do |t| t.string :name end وهذا سوف يصنع جدول يُسمى products يحتوي على عامود نصي يُسمى name (وعامود مُفتاح رئيسي يُسمى id يتولد تلقائيًا كما ناقشنا من قبل) و تلقائيًا، ستنتج دالة create_table ستصنع عامود مُفتاح رئيسي id. يُمكنك تغيير إسم هذا المُفتاح باستخدام أمر primary_key: (ولا تنسَ أن تقوم بهذا التغيير في بقية النماذج models)، كما يُمكنك إلغاء وجود ذلك المُفتاح إن لم تحتاجه بإستخدام أمر id: false. أما إذا أردت تعديل تخطي بعض الخيارات الأخرى لقاعدة البيانات، فيُمكنك استخدام سطور SQL في خيار options: وعلى سبيل المثال: create_table :products, options: "ENGINE=BLACKHOLE" do |t| t.string :name, null: false end وهذا الكود سوف يُضيف ENGINE = BLACKHOLE إلى سطور SQL المسؤولة عن صُنع الجداول ( وفي حالة استعمال MySQL أو MariaDB، فإن الكود المُستخدم هو ENGINE = InnoDB). يُمكنك تعدي خيار comment: باستخدام أي وصف للجدول مُخزن في قاعدة البيانات نفسها و سيتم ظهور هذا الوصف أدوات إدارة قاعدة البيانات، مثل MySQL Workbench أو PgAdmin III. كما أنه من المُفضل لتوضيح التعليقات comments في التهجيرات المُستخدمة بتطبيقات قواعد البيانات الكبيرة. حيث سُتساعد من يقرأ قاعدة البيانات لفهم نماذج البيانات و عمل التوثيقات اللازمة لقاعدة البيانات. 3.2 صُنع الجداول المُدمجة إن دالة التهجير creat_join_table تقوم بصُنع جداول مُدمجة (HABTM-has and belongs to many) و التي كما عرفناها سابقًا عبارة عن عدة عواميد من جدول واحد أو جداول مُختلفة. مثال: create_join_table :products, :categories و هذا سوف يصنع جدول categories_products يحتوي على عامودين يُسميان category_id و product_id. وهذه العواميد تلقائيًا تُعطي قيمة false للأمر null: و يُمكن تخطي هذا الأمر بالتعديل على الخيار column_options:، مثال: create_join_table :products, :categories, column_options: { null: true } إسم الجدول المُدمج سيتكون من إسم العواميد المكونة له طبقًا لترتيبها الأبجدي، و لتغير ذلك يُمكنك إستخدام قواعد التسمية المُستخدمة في المقال السابق و بدالة table_name:، مثال: create_join_table :products, :categories, table_name: :categorization مما سينتج عن الكود السابق جدول يُسمى categorization. كما أن دالة create_join_table يُمكنها إضافة الفهارس و العواميد الإضافية (و لا يتم عمل ذلك بشكل تلقائي إذ يجب عليك تحديد الفهارس أو العواميد الإضافية) مثال: create_join_table :products, :categories do |t| t.index :product_id t.index :category_id end 3.3 تغيير الجداول إن دالة تغيير الجداول change_table مُشابهة لدالة صُنعها create_table عدا أن الثانية تُستخدم لتغير جداول موجودة مُسبقًا. و تعمل بنفس الطريقة و لكنك لن تحتاج إعادة تعريف كُل شيئ لأنه سيأخُذها من الجدول المُتغير منه. مثال على ذلك: change_table :products do |t| t.remove :description, :name t.string :part_number t.index :part_number t.rename :upccode, :upc_code end الكود السابق سوف يحذف العواميد description و columns. و سيصنع عامود نصي part_number وسيضيف فهرس إليه، و سيقوم أيضًا بإعادة تسمية عامود upccode. 3.4 تغيير الأعمدة توفر Rails أمر التهجير change_column و الذي يؤدي دور الأوامر remove_column و add_column. change_column :products, :part_number, :text الكود أعلاه سيُغير نوع العامود part_number في الجدول products ليُصبح حقل نصوص texts. لاحظ أن الدالة change_column لا يُمكن عكسها. وبجانب دالة change_column يوجد دوال change_column_null و change_column_default التي تُستخدم تحديدًا لتغيير القيم الإفتراضية default values للعامود. change_column_null :products, :name, false change_column_default :products, :approved, from: true, to: false الكود أعلاه سيقوم بتغيير الحقل name: في جدول products ليُصبح من نوع NOT NULL و القيمة الإفتراضية لحقل approved: من true إلى false. 3.5 مُعدلات الأعمدة إن مُعدلات الأعمدة Column Modifiers يُمكن أن تُطبق عند صُنع أو تغيير العواميد: limit : يقوم بتحديد أقصى مساحة للحقول من الأنواع string/text/binary/integer Precision : يُحدد دقة الأرقام العشرية بتحديد عدد الوحدات في الرقم الواحد قبل العلامة العشرية Scale : يُحدد دقة الأرقام العشرية بتحديد عدد الوحدات في الرقم الواحد بعد العلامة العشرية Polymorphic : يُضيف عامود type إلى رابطة belong_to Null : تسمح بإستخدام قيمة NULL أو عدم إستخدامها بالعامود. Default : يُتيح لك بتعيين قيمة إفتراضية بالعامود. مع مُلاحظة أنه عند إستخدامك قيمة ديناميكية (مثل التاريخ، فإنه سيتم تعيين القيمة الإفتراضية للتاريخ الذي تم صُنع التهجير عنده. Index : يُضيف فهرس للعامود Comment : يُضيف تعليق للعامود بعض المحولات adapters تدعم بعض الخيارات الإضافية: يُمكنك رؤية التوثيقات الخاصة بتلك المحولات لمعرفة المزيد عن هذا الأمر. 3.6 المفاتيح الأجنبية على الرغم من عدم إضطرارك لإضافة المفاتيح الأجنبية Foreign Keys إلا أنه يُمكنك فعل ذلك لضمان السلامة المرجعية لقاعدة البيانات. add_foreign_key :articles, :authors هذا سوف يُضيف مفتاح أجنبي جديد إلى عامود author_id في جدول articles. والمفتاح سيرمز إلى عامود id في جدول authors. أما إذا كانت أسماء الأعمدة لا يُمكن إشتقاقها من أسماء الجداول، فيُمكنك إستخدام الأوامر column: و primary_key:. إن Rails أيضًا ستقوم بتوليد إسم إفتراضي لكُل مُفتاح أجنبي، سيبدأ بـ fk_rails_ ثُم سيُتبع بعشرة حروف التي ستتولد تلقائيًا من أمر from_table و column. و يُمكنك أيضًا إستخدام name: لتعيين إسم مُختلف إذا أردت. حذف المفاتيح الأجنبية لهو أمر سهل أيضًا: # let Active Record figure out the column name remove_foreign_key :accounts, :branches # remove foreign key for a specific column remove_foreign_key :accounts, column: :owner_id # remove foreign key by name remove_foreign_key :accounts, name: :special_fk_name 3.7 إستخدام دالة التغيير change إن دالة التغيير change هي الطريقة الأساسية لكتابة أوامر التهجير (حيث كما علمنا فإن التهجير هو عبارة عن تغيير في الأساس). و في أغلب الحالات، فإن Active Record يُمكنه عكس تلك التهجيرات. حاليًا، يُمكنك إستخدام دالة التغيير على الدوال الآتية: add_column add_foreign_key add_index add_reference add_timestamps change_column_default (must supply a :from and :to option) change_column_null create_join_table create_table disable_extension drop_join_table drop_table (must supply a block) enable_extension remove_column (must supply a type) remove_foreign_key (must supply a second table) remove_index remove_reference remove_timestamps rename_column rename_index rename_table دالة change_table يُمكن عكسها في حالة أن الجدول لا يقوم بإستدعاء دالة change أو change_default أو remove. ودالة remove_column أيضًا يُمكن عكسها إذا قُمت بتوفير نوع العامود كعامل ثالث موفرًا أيضًا باقي خيارات العامود. وبدون ذلك فإن Rails لن تتمكن من عمل العامود عند إستخدام الأوامر العكسية: remove_column :posts, :slug, :string, null: false, default: '', index: true أما إذا أُضطررت لإستعمال دوال أخرى فعليك إستعمال أمر reversible أو كتابة أوامر up و down بدلًا من إستعمال دالة change. 3.9 إستعمال أمر العكس reversible إن التهجيرات المُعقدة تتطلب مُعالجة لا يستطيع Active Record عكسها. لذلك يُمكنك إستخدام أمر reversible لتحديد ماذا يحدث عند تشغيل التهجير و ماذا يحدث عند عكسه، مثال: class ExampleMigration < ActiveRecord::Migration[5.0] def change create_table :distributors do |t| t.string :zipcode end reversible do |dir| dir.up do # add a CHECK constraint execute <<-SQL ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT; SQL end dir.down do execute <<-SQL ALTER TABLE distributors DROP CONSTRAINT zipchk SQL end end add_column :users, :home_page_url, :string rename_column :users, :email, :email_address end end إن إستعمال دالة reversible سوف تتأكد من تنفيذ excute سطور الكود في الترتيب الصحيح. ففي المثال السابق، سيتم عكس التهجير بالترتيب، فسيتم تشغيل البلوك down بعد حذف عامود home_page_url و قبل إضافة جدول distributors. في بعض الأحيان، لن يُمكن عكس عملية التهجير. لأنه –وعلى سبيل المثال- قد تؤدي إلى تدمير بعض البيانات. في هذه الحالات يُمكنك إستخدام أمر ActiveRecord::IrreversibleMigration في البلوك down. و إذا حاول أحد عكس التهجير فإن رسالة خطأ error message ستُخبره بأن هذا الأمر غير مُمكن. 3.10 إستعمال دوال up/down يُمكنك إستعمال الأسلوب القديم للتهجير بدوال up و down بدلًا من إستعمال دالة change. فإن دالة up يجب أن تصف فيها التغيرات التي تريد عملها في الإسكيما. و دالة down ستقوم بعكس التغيير الذي قامت به دالة up. بإختصار، فإنك إذا قُمت بتطبيق دالة up ثُم بعد ذلك دالة down فيجب ألا يحدث تغيير على قاعدة البيانات. و من المُرجح أن تكون التغييرات التي ستقوم بها دالة up يُمكن عكسها بسهولة. المثال السابق ذكره في قسم (3.9 أمر العكس) سيؤدي وظيفته هذا المثال: class ExampleMigration < ActiveRecord::Migration[5.0] def up create_table :distributors do |t| t.string :zipcode end # add a CHECK constraint execute <<-SQL ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5); SQL add_column :users, :home_page_url, :string rename_column :users, :email, :email_address end def down rename_column :users, :email_address, :email remove_column :users, :home_page_url execute <<-SQL ALTER TABLE distributors DROP CONSTRAINT zipchk SQL drop_table :distributors end end في بعض الأحيان، لن يُمكن عكس عملية التهجير. لأنه –وعلى سبيل المثال- قد تؤدي إلى تدمير بعض البيانات. في هذه الحالات يُمكنك إستخدام أمر ActiveRecord::IrreversibleMigration في البلوك down. و إذا حاول أحد عكس التهجير فإن رسالة خطأ error message ستُخبره بأن هذا الأمر غير مُمكن. 3.11 عكس تهجيرات سابقة يُمكنك إستعمال دالة revert في Active Record لعكس التهجيرات السابقة: require_relative '20121212123456_example_migration' class FixupExampleMigration < ActiveRecord::Migration[5.0] def change revert ExampleMigration create_table(:apples) do |t| t.string :variety end end end دالة reverse أيضًا تقبل عكس مجموعة block من الأوامر. حيث إن هذا سيكون مُفيد في عكس أجزاء مُعينة فقط من تهجير قُمت به مُسبقًا. على سبيل المثال، إفترض أنك إحتحجت إستخدام تحقيقات السحل النشط على التهجير ExampleMigration في مكان إستخدام CHECK لتأكيد الرقم البريدي zipcode. class DontUseConstraintForZipcodeValidationMigration < ActiveRecord::Migration[5.0] def change revert do # copy-pasted code from ExampleMigration reversible do |dir| dir.up do # add a CHECK constraint execute <<-SQL ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5); SQL end dir.down do execute <<-SQL ALTER TABLE distributors DROP CONSTRAINT zipchk SQL end end # The rest of the migration was ok end end end إن نفس التهجير يُمكن كتابته بدون إستخدام revert و لكن ستقوم بعمل المزيد من الخطوات: عكس ترتيب الأمر create_table و الأمر reversible، و إستبدال الأمر create_table بالأمر drop_table، و أخيرًا ستقوم بعكس أمرين up و down و العكس صحيح. هذا كُله يتم عمله بواسطة دالة revert. سنتابع في الدرس التالي ما تبقى من هذا الدليل التعليمي حول تهجير Active Record المصدر: توثيقات Ruby on Rails.