Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रेल प्रवास विदारक

आज की पोस्ट में, हम रेल माइग्रेशन के बारे में गहराई से जानेंगे। हम माइग्रेशन को अलग-अलग हिस्सों में बांटेंगे, और इस प्रक्रिया में, प्रभावी माइग्रेशन लिखना सीखेंगे। हम सीखेंगे कि एकाधिक डेटाबेस के लिए माइग्रेशन कैसे लिखना है, साथ ही असफल माइग्रेशन और रोलबैक करने की तकनीकों को कैसे संभालना है।

पूरी पोस्ट को समझने के लिए, आपको डेटाबेस और रेल की बुनियादी समझ होनी चाहिए।

माइग्रेशन 101

रेल में प्रवासन हमें किसी एप्लिकेशन के जीवनकाल में डेटाबेस विकसित करने की अनुमति देता है। माइग्रेशन हमें एक सुंदर डीएसएल प्रदान करके डेटाबेस की स्थिति को बदलने के लिए सादा रूबी कोड लिखने की अनुमति देता है। हमें डेटाबेस-विशिष्ट SQL लिखने की आवश्यकता नहीं है क्योंकि माइग्रेशन डेटाबेस में हेरफेर करने के लिए एब्स्ट्रैक्शन प्रदान करते हैं और दृश्य के पीछे DSL को डेटाबेस-विशिष्ट SQL क्वेरी में परिवर्तित करने के बारीक-बारीक विवरणों का ध्यान रखते हैं। माइग्रेशन भी हमारे रास्ते से हट जाते हैं और जरूरत पड़ने पर डेटाबेस पर रॉ SQL को निष्पादित करने के तरीके प्रदान करते हैं।

बीस हजार लीग एक रेल डेटाबेस माइग्रेशन में

हम माइग्रेशन का उपयोग करके टेबल बना सकते हैं, कॉलम जोड़ या हटा सकते हैं और कॉलम पर इंडेक्स जोड़ सकते हैं।

<ब्लॉकक्वॉट>

प्रत्येक रेल ऐप की एक विशेष निर्देशिका होती है—db/migrate —जहां सभी माइग्रेशन संग्रहीत हैं।

आइए एक ऐसे माइग्रेशन से शुरू करें जो टेबल बनाता है events हमारे डेटाबेस में।

$ rails g migration CreateEvents category:string

यह आदेश एक टाइमस्टैम्प फ़ाइल उत्पन्न करता है 20200405103635_create_events.rb db/migrate . में निर्देशिका। फ़ाइल की सामग्री इस प्रकार है।

class CreateEvents < ActiveRecord::Migration[6.0]
  def change
    create_table :events do |t|
      t.string :category
 
      t.timestamps
    end
  end
end

आइए इस माइग्रेशन फ़ाइल को तोड़ते हैं।

  • रेल द्वारा जनरेट की जाने वाली प्रत्येक माइग्रेशन फ़ाइल में एक टाइमस्टैम्प होता है जो फ़ाइल नाम में मौजूद होता है। यह टाइमस्टैम्प महत्वपूर्ण है और रेल द्वारा यह पुष्टि करने के लिए उपयोग किया जाता है कि माइग्रेशन चला है या नहीं, जैसा कि हम बाद में देखेंगे।
  • माइग्रेशन में एक वर्ग है जो ActiveRecord::Migration[6.0] से इनहेरिट करता है . जैसा कि मैं रेल 6 का उपयोग कर रहा हूं, माइग्रेशन सुपरक्लास में [6.0] . है . अगर मैं रेल 5.2 का उपयोग कर रहा था, तो सुपरक्लास ActiveRecord::Migration[5.2] होगा . बाद में, हम चर्चा करेंगे कि रेल संस्करण सुपरक्लास नाम का हिस्सा क्यों है।
  • माइग्रेशन की एक विधि होती है change जिसमें डीएसएल कोड होता है जो डेटाबेस में हेरफेर करता है। इस मामले में, change विधि एक events बना रही है एक कॉलम के साथ तालिका category प्रकार का string
  • माइग्रेशन कोड का उपयोग करता है t.timestamps टाइमस्टैम्प जोड़ने के लिए created_at और updated_at events . के लिए टेबल.

जब यह माइग्रेशन rails db:migrate . का उपयोग करके चलाया जाता है कमांड, यह एक events बनाएगा category . के साथ तालिका प्रकार का स्तंभ string और टाइमस्टैम्प कॉलम created_at और updated_at

<ब्लॉकक्वॉट>

डेटाबेस के आधार पर वास्तविक डेटाबेस कॉलम प्रकार वर्चर या टेक्स्ट होगा।

माइग्रेशन टाइमस्टैम्प और स्कीमा_माइग्रेशन टेबल का महत्व

हर बार rails g migration . का उपयोग करके माइग्रेशन जेनरेट किया जाता है कमांड, रेल एक अद्वितीय टाइमस्टैम्प के साथ माइग्रेशन फ़ाइल उत्पन्न करता है। टाइमस्टैम्प YYYYMMDDHHMMSS . के प्रारूप में है .जब भी कोई माइग्रेशन चलाया जाता है, रेल माइग्रेशन टाइमस्टैम्प को आंतरिक तालिका schema_migrations में सम्मिलित करता है . जब हम अपना पहला माइग्रेशन चलाते हैं तो यह तालिका रेल द्वारा बनाई जाती है। तालिका में केवल कॉलम version . है , जो इसकी प्राथमिक कुंजी भी है। यह schema_migrations . की संरचना है टेबल।

CREATE TABLE IF NOT EXISTS "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);

अब जबकि हमने events . बनाने के लिए माइग्रेशन चला लिया है तालिका, देखते हैं कि रेल ने इस माइग्रेशन के एटिमस्टैम्प को schema_migrations में संग्रहीत किया है या नहीं टेबल।

sqlite> select * from schema_migrations;
20200405103635

यदि हम फिर से माइग्रेशन चलाते हैं, तो रेल पहले जांच करेगी कि schema_migrations में कोई प्रविष्टि मौजूद है या नहीं माइग्रेशन फ़ाइल के टाइमस्टैम्प के साथ तालिका, और ऐसी कोई प्रविष्टि न होने पर ही इसे निष्पादित करें। यह सुनिश्चित करता है कि हम समय के साथ डेटाबेस में क्रमिक रूप से परिवर्तन जोड़ सकते हैं और माइग्रेशन डेटाबेस पर केवल एक बार चलेगा।

डेटाबेस स्कीमा

जैसे-जैसे हम अधिक से अधिक माइग्रेशन चलाते हैं, डेटाबेस स्कीमा विकसित होता रहता है। रेल नवीनतम डेटाबेस स्कीमा को db/schema.rb . फ़ाइल में संग्रहीत करता है . यह फ़ाइल एप्लिकेशन के पूरे जीवन में आपके डेटाबेस पर सभी माइग्रेशन का रूबी प्रतिनिधित्व है। इस फ़ाइल के कारण, हमें पुरानी माइग्रेशन फ़ाइलों को कोडबेस में रखने की आवश्यकता नहीं है। रेल dump को कार्य प्रदान करता है डेटाबेस से नवीनतम स्कीमा schema.rb . में और load schema.rb . से डेटाबेस में स्कीमा . इसलिए पुराने माइग्रेशन को कोडबेस से सुरक्षित रूप से हटाया जा सकता है। हर बार जब हम एप्लिकेशन सेट करते हैं तो प्रत्येक माइग्रेशन को चलाने की तुलना में डेटाबेस में स्कीमा लोड करना भी तेज़ होता है।

<ब्लॉकक्वॉट>

रेल एसक्यूएल प्रारूप में डेटाबेस स्कीमा को स्टोर करने का एक तरीका भी प्रदान करता है। दो प्रारूपों की तुलना करने के लिए हमारे पास पहले से ही एक लेख है। आप इसके बारे में यहाँ और अधिक पढ़ सकते हैं।

प्रवास में रेल संस्करण

हमारे द्वारा उत्पन्न प्रत्येक माइग्रेशन में सुपरक्लास के हिस्से के रूप में रेल संस्करण होता है। इसलिए रेल 6 ऐप द्वारा उत्पन्न माइग्रेशन में सुपरक्लास होता है ActiveRecord::Migration[6.0] जबकि रेल 5.2 ऐप द्वारा उत्पन्न माइग्रेशन में सुपरक्लास ActiveRecord::Migration[5.2] है . यदि आपके पास रेल 4.2 या उससे नीचे का पुराना ऐप है, तो आप देखेंगे कि सुपरक्लास में कोई संस्करण नहीं है। सुपरक्लास सिर्फ ActiveRecord::Migration है ।

रेल संस्करण को रेल 5 में माइग्रेशन सुपरक्लास में जोड़ा गया था। यह मूल रूप से सुनिश्चित करता है कि माइग्रेशनएपीआई रेल के पुराने संस्करणों द्वारा उत्पन्न माइग्रेशन को तोड़े बिना समय के साथ विकसित हो सकता है।

आइए एक events . बनाने के लिए उसी माइग्रेशन को देखकर इस पर गहराई से विचार करें एक रेल 4.2 ऐप में तालिका।

class CreateEvents < ActiveRecord::Migration
  def change
    create_table :events do |t|
      t.string :category
 
      t.timestamps null: false
    end
  end
end

अगर हम events . के स्कीमा को देखें तो एक रेल 6 माइग्रेशन द्वारा उत्पन्न तालिका, हम देख सकते हैं कि NOT NULL टाइमस्टैम्प कॉलम के लिए बाधा मौजूद है।

sqlite> .schema events
CREATE TABLE IF NOT EXISTS "events" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "category" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);

ऐसा इसलिए है, क्योंकि रेल 5 से शुरू होकर, माइग्रेशन एपीआई स्वचालित रूप से एक NOT NULL adds जोड़ता है माइग्रेशन फ़ाइल में स्पष्ट रूप से जोड़ने की आवश्यकता के बिना टाइमस्टैम्प कॉलम के लिए बाधा। सुपरक्लास नाम में रेल संस्करण यह सुनिश्चित करता है कि माइग्रेशन रेल संस्करण के माइग्रेशन एपीआई का उपयोग करता है जिसके लिए माइग्रेशन उत्पन्न हुआ था। यह रेल को पुराने माइग्रेशन के साथ पिछड़ा संगतता बनाए रखने की अनुमति देता है, साथ ही साथ माइग्रेशन API को विकसित करता है।

डेटाबेस स्कीमा बदलना

change प्रवासन में विधि प्राथमिक विधि है। जब कोई माइग्रेशन चलाया जाता है, तो वह change को कॉल करता है विधि और उसके अंदर कोड निष्पादित करता है।

साथ में create_table , रेल एक और शक्तिशाली तरीका भी प्रदान करता है—change_table जैसा कि नाम से पता चलता है, इसका उपयोग मौजूदा तालिका के स्कीमा को बदलने के लिए किया जाता है।

def change
  change_table :events do |t|
    t.remove :category
    t.string :event_type
    t.boolean :active, default: false
  end
end

यह माइग्रेशन category को हटा देगा events . से कॉलम तालिका में, एक नया स्ट्रिंग कॉलम जोड़ें events_type और एक नया बूलियन कॉलम active false . के डिफ़ॉल्ट मान के साथ ।

रेल कई अन्य सहायक विधियाँ भी प्रदान करता है जिनका उपयोग प्रवास के अंदर किया जा सकता है जैसे:

  • change_column
  • add_index
  • remove_index
  • rename_table

और भी कई। परिवर्तन के साथ उपयोग की जा सकने वाली सभी विधियों को यहां पाया जा सकता है

टाइमस्टैम्प

हमने देखा कि t.timestamps रेल द्वारा माइग्रेशन में जोड़ा गया था और इसने कॉलम जोड़ेcreated_at और updated_at events . के लिए मेज़। इन विशेष स्तंभों का उपयोग रेलस्टो द्वारा रिकॉर्ड बनाए जाने और अद्यतन किए जाने पर नज़र रखने के लिए किया जाता है। जब कोई रिकॉर्ड बनाया जाता है तो रेल इन स्तंभों में मान जोड़ता है और रिकॉर्ड अपडेट होने पर उन्हें अपडेट करना सुनिश्चित करता है। ये कॉलम डेटाबेस रिकॉर्ड के जीवनकाल को ट्रैक करने में हमारी मदद करते हैं।

<ब्लॉकक्वॉट>

updated_at जब हम updated_all . निष्पादित करते हैं तो कॉलम अपडेट नहीं होता है रेल से विधि।

विफलताओं को संभालना

माइग्रेशन बुलेटप्रूफ नहीं हैं। वे असफल हो सकते हैं। इसका कारण गलत सिंटैक्स या अमान्य डेटाबेस क्वेरी हो सकता है। कारण जो भी हो, हमें विफलता को संभालना होगा और उससे उबरना होगा ताकि डेटाबेस असंगत स्थिति में न जाए। लेन-देन के अंदर प्रत्येक माइग्रेशन चलाकर रेल इस समस्या को हल करती है। यदि माइग्रेशन विफल हो जाता है, तो लेन-देन वापस ले लिया जाता है। यह सुनिश्चित करता है कि डेटाबेस असंगत स्थिति में नहीं जाता है।

<ब्लॉकक्वॉट>

यह केवल उन डेटाबेस के लिए किया जाता है जो डेटाबेस स्कीमा को अपडेट करने के लिए लेनदेन का समर्थन करते हैं। उन्हें डेटा डेफिनिशन लैंग्वेज (डीडीएल) लेनदेन के रूप में जाना जाता है। MySQL और PostgreSQL दोनों ही DDL लेनदेन का समर्थन करते हैं।

कभी-कभी, हम लेन-देन के अंदर कुछ माइग्रेशन निष्पादित नहीं करना चाहते हैं। PostgreSQL में समवर्ती अनुक्रमणिका जोड़ते समय एक सरल उदाहरण है। इस तरह के माइग्रेशन को डीडीएल लेनदेन के अंदर निष्पादित नहीं किया जा सकता है क्योंकि PostgreSQL टेबल पर ताले प्राप्त किए बिना इंडेक्स जोड़ने की कोशिश करता है ताकि हम डेटाबेस को नीचे ले जाए बिना लाइव प्रोडक्शन डेटाबेस पर इंडेक्स जोड़ सकें। रेल disable_ddl_transactions! के रूप में माइग्रेशन के अंदर लेनदेन से ऑप्ट-आउट करने का एक तरीका प्रदान करती है। ।

def change
  disable_ddl_transactions!
 
  add_index :events, :user_id, algorithm: :concurrently

यह किसी लेन-देन के अंदर माइग्रेशन नहीं चलाएगा। यदि ऐसा प्रवास विफल हो जाता है, तो हमें इसे स्वयं पुनर्प्राप्त करने की आवश्यकता है। इस मामले में, हम या तो REINDEX . कर सकते हैं या अनुक्रमणिका निकालें और इसे फिर से जोड़ने का प्रयास करें।

प्रतिवर्ती माइग्रेशन

रेल हमें निम्न आदेश के साथ डेटाबेस में परिवर्तनों को रोलबैक करने की अनुमति देता है।

rails db:rollback

यह आदेश डेटाबेस पर चलाए गए अंतिम माइग्रेशन को पूर्ववत करता है। अगर माइग्रेशन ने एक कॉलम जोड़ा हैevent_type फिर रोलबैक उस कॉलम को हटा देगा। अगर माइग्रेशन ने एक इंडेक्स जोड़ा है, तो रोलबैक उस इंडेक्स को हटा देगा।

<ब्लॉकक्वॉट>

पिछले माइग्रेशन को वापस रोल करने और उसे चलाने के लिए एक कमांड भी है। यह है rails db:redo

अधिकांश माइग्रेशन को उलटने का तरीका जानने के लिए रेल काफी स्मार्ट है। लेकिन हम रेलसन को up . प्रदान करके माइग्रेशन को वापस करने के संकेत भी दे सकते हैं और down change . का उपयोग करने के बजाय विधियों method.The up विधि का उपयोग तब किया जाएगा जब माइग्रेशन चलाया जाता है जबकि down विधि का उपयोग तब किया जाएगा जब माइग्रेशन वापस ले लिया जाए।

def up
  change_table :events do |t|
    t.change :price, :string
  end
end
 
def down
  change_table :events do |t|
    t.change :price, :integer
  end
end

इस उदाहरण में, हम price बदल रहे हैं events . का कॉलम integer . से करने के लिए string . हम निर्दिष्ट करते हैं कि इसे down . में कैसे वापस लाया जाना चाहिए विधि।

इसी माइग्रेशन को change . का उपयोग करके भी लिखा जा सकता है विधि।

def change
  reversible do |direction|
    change_table :events do |t|
      direction.up { t.change :price, :string }
      direction.down { t.change :price, :integer }
    end
  end
end

रेल्स revert . का उपयोग करके पिछले माइग्रेशन को पूरी तरह से वापस करने का एक तरीका भी प्रदान करता है विधि।

def change
  revert CreateEvents
 
  create_table :events do
   ...
  end
end

revert विधि आंशिक रूप से माइग्रेशन को वापस करने के लिए ब्लॉक को भी स्वीकार करती है।

def change
  revert do
    reversible do |direction|
      change_table :events do |t|
        direction.up { t.remove :event_type }
        direction.down { t.string :event_type }
      end
    end
  end
end

इसे कच्चा निष्पादित करना

कभी-कभी, हम माइग्रेशन के अंदर जटिल SQL निष्पादित करना चाहते हैं। ऐसे मामलों में, हम विशिष्ट माइग्रेशन DSL को भूल सकते हैं और इसके बजाय कच्चे SQL को निम्नानुसार निष्पादित कर सकते हैं।

def change
  execute <<-SQL
    ....
  SQL
end

एकाधिक डेटाबेस और माइग्रेशन

रेल 6 ने एक ही रेल एप्लिकेशन के भीतर कई डेटाबेस का उपयोग करने के लिए समर्थन जोड़ा। यदि हम कई डेटाबेस का उपयोग करना चाहते हैं, तो हम उन्हें database.yml में कॉन्फ़िगर करते हैं। फ़ाइल।

development:
  primary:
    <<: *default
    database: db/development.sqlite3
  analytics:
    adapter: sqlite3
    database: db/analytics_dev.sqlite3

यह कॉन्फ़िगरेशन रेल को बताता है कि हम दो डेटाबेस का उपयोग करना चाहते हैं-primary और analytics .जैसा कि हमने पहले देखा, माइग्रेशन db/migrate . में स्टोर हो जाते हैं डिफ़ॉल्ट रूप से निर्देशिका। लेकिन इस मामले में, हम एक ही निर्देशिका के अंदर दोनों डेटाबेस के माइग्रेशन को नहीं जोड़ सकते। हम analytics . के माइग्रेशन नहीं चलाना चाहते हैं primary . पर डेटाबेस डेटाबेस और इसके विपरीत। यदि हम एकाधिक डेटाबेस का उपयोग कर रहे हैं, तो दूसरे डेटाबेस के लिए माइग्रेशन संग्रहीत करने के लिए पथ प्रदान करने की आवश्यकता होगी। यह एक migrations_paths . प्रदान करके किया जा सकता है database.yml . में ।

development:
  primary:
    <<: *default
    database: db/development.sqlite3
  analytics:
    adapter: sqlite3
    database: db/analytics_dev.sqlite3
    migrations_paths: db/analytics_migrate

फिर हम analytics . के लिए माइग्रेशन बना सकते हैं डेटाबेस इस प्रकार है।

rails generate migration AddExperiments rule:string active:boolean --db=analytics

इससे db/analytics_migrate . के अंदर माइग्रेशन बन जाएगा , और हम इसे निम्नानुसार चला सकते हैं।

rails db:migrate --db=analytics

अगर हम केवल rails db:migrate चलाते हैं , यह सभी डेटाबेस के लिए माइग्रेशन निष्पादित करेगा।

<ब्लॉकक्वॉट>

analytics डेटाबेस का अपना schema_migrations होगा यह ट्रैक रखने के लिए कि कौन से माइग्रेशन चल रहे हैं और कौन से नहीं हैं।

तैनाती के दौरान माइग्रेशन चलाना

चूंकि माइग्रेशन डेटाबेस की स्थिति को बदल सकते हैं, और हमारा कोड उन परिवर्तनों पर निर्भर हो सकता है, इसलिए यह अत्यंत महत्वपूर्ण है कि नए कोड लागू होने से पहले माइग्रेशन चलाए जाएं।

Heroku आधारित परिनियोजन में, माइग्रेशन release . में चलाया जा सकता है Procfile का चरण ।

# Profile
web: bin/puma -C config/puma.rb
release: bundle exec rake db:migrate

यह सुनिश्चित करता है कि ऐप डायनोस के पुनरारंभ होने से पहले माइग्रेशन चलाए जाते हैं।

Capistrano आधारित परिनियोजन में, सर्वर के पुनरारंभ होने से पहले माइग्रेशन चलना चाहिए।

डॉकटर आधारित परिनियोजन में, हम ऐप के पुनरारंभ होने से पहले माइग्रेशन चलाने के लिए एक साइडकार कंटेनर चला सकते हैं। यह बहुत महत्वपूर्ण है क्योंकि अन्यथा, नए कंटेनर असंगत स्थिति में जा सकते हैं यदि वे उस नए कोड के लिए डेटाबेस परिवर्तन लागू करने से पहले नए कोड का उपयोग करना शुरू करते हैं।

निष्कर्ष

इस पोस्ट में, हमने रेल में डेटाबेस माइग्रेशन लिखने के विभिन्न पहलुओं को देखा। हमने यह भी देखा कि माइग्रेशन क्या होता है और साथ ही विफलताओं से कैसे निपटा जाए और जरूरत पड़ने पर माइग्रेशन को वापस कैसे लाया जाए। रेल 6 हमें कई डेटाबेस का उपयोग करने की अनुमति देता है और प्रत्येक के लिए माइग्रेशन को अलग से जोड़ने की आवश्यकता होती है। अंत में, हमने संक्षेप में देखा कि परिनियोजन के दौरान माइग्रेशन को कैसे चलाया जाए ताकि किसी भी नए कोड का उपयोग शुरू करने से पहले डेटाबेस परिवर्तन ठीक से लागू हो जाएं।

पी.एस. यदि आप रूबी मैजिक की पोस्ट प्रेस से छूटते ही पढ़ना चाहते हैं, तो हमारे रूबी मैजिक न्यूजलेटर की सदस्यता लें और एक भी पोस्ट मिस न करें!


  1. रेल सुरक्षा खतरे:इंजेक्शन

    यदि आप उपयोगकर्ता डेटा से निपटते हैं, तो आपको यह सुनिश्चित करना होगा कि यह सुरक्षित है। हालांकि, अगर आप सुरक्षा के लिए नए हैं, तो यह मुश्किल, उबाऊ और जटिल लग सकता है। यह लेख श्रृंखला में पहला है जो आपको सामान्य प्रकार की सुरक्षा कमजोरियों के बारे में सिखाएगा और वे रेल विकास को कैसे प्रभावित करते है

  1. रेल पर प्रतिक्रिया:एक साधारण ऐप बनाना

    कंपनियां जो अपने अनुप्रयोगों के पूरे फ्रंट-एंड साइड का निर्माण करती हैं, अक्सर बैक-एंड बनाने के लिए रेल जैसे समान ढांचे का चयन करती हैं। कई वर्षों से, यह सबसे अच्छा और सबसे विश्वसनीय विकल्प रहा है। आज, लगातार विकसित हो रहे फ्रंट-एंड ब्रह्मांड में, ढेर सारे पुस्तकालय और ढांचे, डेवलपर्स को बैक और फ्र

  1. रेल के साथ कोणीय का उपयोग करना 5

    आपने पहले कहानी सुनी है। आपके पास पहले से ही आपके विकेन्द्रीकृत और पूरी तरह से काम कर रहे बैक-एंड एपीआई और किसी भी सामान्य टूलसेट से बने फ्रंट-एंड पर चलने वाला एक एप्लिकेशन है। अब, आप कोणीय पर आगे बढ़ना चाहते हैं। या, शायद आप अपनी रेल परियोजनाओं के साथ एंगुलर को एकीकृत करने का एक तरीका ढूंढ रहे हैं