डेटा अधिकांश सॉफ्टवेयर एप्लिकेशन्स का एक मुख्य हिस्सा है। डेटाबेस से डेटा को मैप करना और क्वेरी करना एक डेवलपर के जीवन में एक आवर्ती कार्य है। इस वजह से, प्रक्रिया को समझना और उन एब्सट्रैक्शन्स का उपयोग करने में सक्षम होना महत्वपूर्ण है जो कार्य को सरल बनाते हैं।
इस पोस्ट में, जो दो की श्रृंखला में पहली है, आपको एक्टिवरिकॉर्ड (रूबी) और एक्टो (एलिक्सिर) के बीच तुलना मिलेगी। हम देखेंगे कि दोनों टूल्स डेवलपर्स को डेटाबेस स्कीमाज को माइग्रेट और मैप करने में कैसे सक्षम बनाते हैं।
तो हम सेब और संतरे की तुलना करेंगे। (मूल) बैटगर्ल, जिसे कभी एक शब्द कहने की ज़रूरत नहीं पड़ी, बनाम बैटमैन, जो स्पष्ट रूप से 'मैं बैटमैन हूँ' बताता है। इम्प्लिसिट, कॉन्फिगरेशन ओवर कन्वेंशन, बनाम एक्सप्लिसिट इरादा। राउंड वन। फाइट!
एक्टिवरिकॉर्ड
इसके रिलीज़ के बाद से 10 से अधिक वर्षों के साथ, संभावना है कि आप पहले ही एक्टिवरिकॉर्ड के बारे में सुन चुके हैं - प्रसिद्ध ORM जो डिफ़ॉल्ट रूप से रूबी ऑन रेल्स प्रोजेक्ट्स के साथ शिप होता है।
एक्टिवरिकॉर्ड MVC में M है - मॉडल - जो सिस्टम की वह लेयर है जो बिजनेस डेटा और लॉजिक को दर्शाने के लिए जिम्मेदार है। एक्टिवरिकॉर्ड उन बिजनेस ऑब्जेक्ट्स के निर्माण और उपयोग की सुविधा देता है जिनके डेटा को डेटाबेस में लगातार स्टोरेज की आवश्यकता होती है। यह एक्टिवरिकॉर्ड पैटर्न का एक कार्यान्वयन है जो स्वयं ऑब्जेक्ट रिलेशनल मैपिंग सिस्टम का विवरण है।
हालांकि यह ज्यादातर रेल्स के साथ उपयोग किए जाने के लिए जाना जाता है, एक्टिवरिकॉर्ड का उपयोग स्टैंडअलोन टूल के रूप में भी किया जा सकता है, जिसे अन्य प्रोजेक्ट्स में एम्बेड किया जा सकता है।
एक्टो
एक्टिवरिकॉर्ड की तुलना में, एक्टो एक काफी नया (और फिलहाल उतना प्रसिद्ध नहीं) टूल है। यह एलिक्सिर में लिखा गया है और डिफ़ॉल्ट रूप से फीनिक्स प्रोजेक्ट्स में शामिल है।
एक्टिवरिकॉर्ड के विपरीत, एक्टो ORM नहीं है, बल्कि एक लाइब्रेरी है जो क्वेरीज़ लिखने और डेटाबेस के साथ इंटरैक्ट करने के लिए एलिक्सिर के उपयोग को सक्षम बनाती है।
एक्टो एलिक्सिर में क्वेरीज़ लिखने और डेटाबेस के साथ इंटरैक्ट करने के लिए एक डोमेन स्पेसिफिक लैंग्वेज है।
डिज़ाइन द्वारा, एक्टो एक स्टैंडअलोन टूल है, जिसे विभिन्न एलिक्सिर प्रोजेक्ट्स में उपयोग किया जाता है और किसी फ्रेमवर्क से जुड़ा नहीं होता।
क्या आप सेब और संतरे की तुलना नहीं कर रहे?
हाँ हम कर रहे हैं! हालांकि एक्टिवरिकॉर्ड और एक्टो सिमेंटिकली अलग हैं, लेकिन डेटाबेस माइग्रेशन्स, डेटाबेस मैपिंग्स, क्वेरीज़ और वैलिडेशन्स जैसी सामान्य सुविधाएँ दोनों एक्टिवरिकॉर्ड और एक्टो द्वारा समर्थित हैं। और दोनों टूल्स का उपयोग करके समान परिणाम प्राप्त किए जा सकते हैं। रूबी बैकग्राउंड से आने वाले एलिक्सिर में रुचि रखने वालों के लिए हमने सोचा कि यह एक दिलचस्प तुलना होगी।
इनवॉइस सिस्टम
पोस्ट के बाकी हिस्सों में, प्रदर्शन के लिए एक काल्पनिक इनवॉइस सिस्टम का उपयोग किया जाएगा। आइए कल्पना करें कि हमारे पास एक स्टोर है जो सुपरहीरोज़ को सूट बेचता है। चीजों को सरल रखने के लिए, इनवॉइस सिस्टम के लिए हमारे पास केवल दो टेबल्स होंगे: users और invoices।
नीचे उन टेबल्स की संरचना है, उनके फील्ड्स और टाइप्स के साथ:
users
| Field | Type |
|---|---|
| full_name | string |
| string | |
| created_at (ActiveRecord) / inserted_at (Ecto) | datetime |
| updated_at | datetime |
invoices
| Field | Type |
|---|---|
| user_id | integer |
| payment_method | string |
| paid_at | datetime |
| created_at (ActiveRecord) / inserted_at (Ecto) | datetime |
| updated_at | datetime |
यूज़र्स टेबल में चार फील्ड्स हैं: full_name, email, updated_at और एक चौथा फील्ड जो उपयोग किए गए टूल पर निर्भर करता है। एक्टिवरिकॉर्ड created_at फील्ड बनाता है जबकि एक्टो रिकॉर्ड के पहली बार डेटाबेस में डाले जाने के क्षण के टाइमस्टैम्प को दर्शाने के लिए inserted_at फील्ड बनाता है।
दूसरी टेबल का नाम invoices है। इसमें पांच फील्ड्स हैं: user_id, payment_method, paid_at, updated_at और, यूज़र्स टेबल के समान, उपयोग किए गए टूल के आधार पर या तो created_at या inserted_at।
यूज़र्स और इनवॉइस टेबल्स में निम्नलिखित एसोसिएशन्स हैं:
- एक यूज़र के कई इनवॉइस होते हैं
- एक इनवॉइस एक यूज़र से संबंधित होता है
माइग्रेशन्स
माइग्रेशन्स डेवलपर्स को एक पुनरावृत्त प्रक्रिया का उपयोग करके समय के साथ अपने डेटाबेस स्कीमा को आसानी से विकसित करने की अनुमति देती हैं। एक्टिवरिकॉर्ड और एक्टो दोनों डेवलपर्स को SQL से सीधे निपटने के बजाय हाई-लेवल लैंग्वेज (क्रमशः रूबी और एलिक्सिर) का उपयोग करके डेटाबेस स्कीमा को माइग्रेट करने में सक्षम बनाते हैं।
आइए देखें कि एक्टिवरिकॉर्ड और एक्टो में माइग्रेशन्स कैसे काम करती हैं, उनका उपयोग करके users और invoices टेबल्स बनाकर।
एक्टिवरिकॉर्ड: Users टेबल बनाना
माइग्रेशन
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :full_name, null: false
t.string :email, index: {unique: true}, null: false
t.timestamps
end
end
end
एक्टिवरिकॉर्ड माइग्रेशन्स create_table मेथड का उपयोग करके टेबल्स के निर्माण को सक्षम करती हैं। हालांकि created_at और updated_at फील्ड्स माइग्रेशन फाइल में परिभाषित नहीं हैं, t.timestamps का उपयोग एक्टिवरिकॉर्ड को दोनों बनाने के लिए ट्रिगर करता है।
बनाई गई टेबल संरचना
CreateUsers माइग्रेशन चलाने के बाद, बनाई गई टेबल की निम्नलिखित संरचना होगी:
Column | Type | Nullable | Default
------------+-----------------------------+----------+-----------------------------------
id | bigint | not null | nextval('users_id_seq'::regclass)
full_name | character varying | not null |
email | character varying | not null |
created_at | timestamp without time zone | not null |
updated_at | timestamp without time zone | not null |
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"index_users_on_email" UNIQUE, btree (email)
माइग्रेशन email फील्ड के लिए एक यूनिक इंडेक्स के निर्माण के लिए भी जिम्मेदार है। index: {unique: true} विकल्प email फील्ड परिभाषा को पास किया जाता है। यही कारण है कि टेबल में इसकी संरचना के हिस्से के रूप में "index_users_on_email" UNIQUE, btree (email) इंडेक्स सूचीबद्ध है।
एक्टो: Users टेबल बनाना
माइग्रेशन
defmodule Financex.Repo.Migrations.CreateUsers do
use Ecto.Migration
def change do
create table(:users) do
add :full_name, :string, null: false
add :email, :string, null: false
timestamps()
end
create index(:users, [:email], unique: true)
end
end
एक्टो माइग्रेशन users टेबल बनाने के लिए create() और table() फंक्शन्स को जोड़ती है। एक्टो माइग्रेशन फाइल इसके एक्टिवरिकॉर्ड समकक्ष के समान है। एक्टिवरिकॉर्ड में टाइमस्टैम्प फील्ड्स (created_at और updated_at) t.timestamps द्वारा बनाए जाते हैं जबकि एक्टो में टाइमस्टैम्प फील्ड्स (inserted_at और updated_at) timestamps() फंक्शन द्वारा बनाए जाते हैं।
दोनों टूल्स में इंडेक्स कैसे बनाए जाते हैं, इसमें एक छोटा अंतर है। एक्टिवरिकॉर्ड में, इंडेक्स को बनाए जा रहे फील्ड के विकल्प के रूप में परिभाषित किया जाता है। एक्टो उस संयोजन को प्राप्त करने के लिए create() और index() फंक्शन्स के संयोजन का उपयोग करता है, जो टेबल बनाने के लिए संयोजन के उपयोग के अनुरूप है।
बनाई गई टेबल संरचना
Column | Type | Nullable | Default
-------------+-----------------------------+----------+-----------------------------------
id | bigint | not null | nextval('users_id_seq'::regclass)
full_name | character varying(255) | not null |
email | character varying(255) | not null |
inserted_at | timestamp without time zone | not null |
updated_at | timestamp without time zone | not null |
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"users_email_index" UNIQUE, btree (email)
Financex.Repo.Migrations.CreateUsers माइग्रेशन चलाने पर बनी टेबल की संरचना एक्टिवरिकॉर्ड का उपयोग करके बनाई गई टेबल के समान है।
एक्टिवरिकॉर्ड: invoices टेबल बनाना
माइग्रेशन
class CreateInvoices < ActiveRecord::Migration[5.2]
def change
create_table :invoices do |t|
t.references :user
t.string :payment_method
t.datetime :paid_at
t.timestamps
end
end
end
इस माइग्रेशन में t.references मेथड शामिल है, जो पिछले में मौजूद नहीं था। इसका उपयोग users टेबल के संदर्भ को बनाने के लिए किया जाता है। जैसा कि पहले वर्णित है, एक यूज़र के कई इनवॉइस होते हैं और एक इनवॉइस एक यूज़र से संबंधित होता है। t.references मेथड उस संदर्भ को रखने के लिए इनवॉइस टेबल में user_id कॉलम बनाता है।
बनाई गई टेबल संरचना
Column | Type | Nullable | Default
----------------+-----------------------------+----------+--------------------------------------
id | bigint | not null | nextval('invoices_id_seq'::regclass)
user_id | bigint | |
payment_method | character varying | |
paid_at | timestamp without time zone | |
created_at | timestamp without time zone | not null |
updated_at | timestamp without time zone | not null |
Indexes:
"invoices_pkey" PRIMARY KEY, btree (id)
"index_invoices_on_user_id" btree (user_id)
बनाई गई टेबल पहले बनाई गई टेबल के समान पैटर्न का पालन करती है। एकमात्र अंतर एक अतिरिक्त इंडेक्स (index_invoices_on_user_id) है, जिसे एक्टिवरिकॉर्ड स्वचालित रूप से जोड़ता है जब t.references मेथड का उपयोग किया जाता है।
एक्टो: invoices टेबल बनाना
माइग्रेशन
defmodule Financex.Repo.Migrations.CreateInvoices do
use Ecto.Migration
def change do
create table(:invoices) do
add :user_id, references(:users)
add :payment_method, :string
add :paid_at, :utc_datetime
timestamps()
end
create index(:invoices, [:user_id])
end
end
एक्टो भी references() फंक्शन का उपयोग करके डेटाबेस रेफरेंस के निर्माण का समर्थन करता है। एक्टिवरिकॉर्ड के विपरीत, जो कॉलम नाम का अनुमान लगाता है, एक्टो को डेवलपर को स्पष्ट रूप से user_id कॉलम नाम को परिभाषित करने की आवश्यकता होती है। references() फंक्शन को डेवलपर को उस टेबल को स्पष्ट रूप से परिभाषित करने की भी आवश्यकता होती है जिस पर रेफरेंस इंगित कर रहा है, जो इस उदाहरण में users टेबल है।
बनाई गई टेबल संरचना
Column | Type | Nullable | Default
----------------+-----------------------------+----------+--------------------------------------
id | bigint | not null | nextval('invoices_id_seq'::regclass)
user_id | bigint | |
payment_method | character varying(255) | |
paid_at | timestamp without time zone | |
inserted_at | timestamp without time zone | not null |
updated_at | timestamp without time zone | not null |
Indexes:
"invoices_pkey" PRIMARY KEY, btree (id)
"invoices_user_id_index" btree (user_id)
Foreign-key constraints:
"invoices_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
दोनों माइग्रेशन्स भी काफी समान हैं। जब references फीचर को संभालने के तरीके की बात आती है, तो कुछ अंतर हैं:
एक्टो
user_idफील्ड पर एक फॉरेन-की कंस्ट्रेंट बनाता है ("invoices_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)), जो users और invoices टेबल्स के बीच रेफरेंशियल इंटीग्रिटी को बनाए रखता है।एक्टिवरिकॉर्ड स्वचालित रूप से
user_idकॉलम के लिए एक इंडेक्स बनाता है। एक्टो को डेवलपर को इसके बारे में स्पष्ट होने की आवश्यकता होती है। यही कारण है कि माइग्रेशन मेंcreate index(:invoices, [:user_id])स्टेटमेंट है।
एक्टिवरिकॉर्ड: डेटा मैपिंग और एसोसिएशन्स
एक्टिवरिकॉर्ड अपने "कन्वेंशन ओवर कॉन्फिगरेशन" आदर्श वाक्य के लिए जाना जाता है। यह डिफ़ॉल्ट रूप से मॉडल क्लास नाम का उपयोग करके डेटाबेस टेबल नामों का अनुमान लगाता है। User नाम की एक क्लास, डिफ़ॉल्ट रूप से, अपने स्रोत के रूप में users टेबल का उपयोग करती है। एक्टिवरिकॉर्ड टेबल के सभी कॉलम्स को इंस्टेंस एट्रिब्यूट के रूप में मैप करता है। डेवलपर्स से केवल टेबल्स के बीच एसोसिएशन्स को परिभाषित करने की आवश्यकता होती है। इनका उपयोग एक्टिवरिकॉर्ड द्वारा शामिल क्लासेस और टेबल्स का अनुमान लगाने के लिए भी किया जाता है।
एक नज़र डालें कि एक्टिवरिकॉर्ड का उपयोग करके users और invoices टेबल्स को कैसे मैप किया जाता है:
users
class User < ApplicationRecord
has_many :invoices
end
invoices
class Invoice < ApplicationRecord
belongs_to :user
end
एक्टो: डेटा मैपिंग और एसोसिएशन्स
दूसरी ओर, एक्टो को डेवलपर को डेटा स्रोत और उसके फील्ड्स के बारे में स्पष्ट होने की आवश्यकता होती है। हालांकि एक्टो में समान has_many और belongs_to फीचर्स हैं, लेकिन यह डेवलपर्स को संबद्ध टेबल और उस स्कीमा मॉड्यूल के बारे में स्पष्ट होने की भी आवश्यकता होती है जिसका उपयोग उस टेबल स्कीमा को संभालने के लिए किया जाता है।
यह है कि एक्टो users और invoices टेबल्स को कैसे मैप करता है:
users
defmodule Financex.Accounts.User do
use Ecto.Schema
schema "users" do
field :full_name, :string
field :email, :string
has_many :invoices, Financex.Accounts.Invoice
timestamps()
end
end
invoices
defmodule Financex.Accounts.Invoice do
use Ecto.Schema
schema "invoices" do
field :payment_method, :string
field :paid_at, :utc_datetime
belongs_to :user, Financex.Accounts.User
timestamps()
end
end
समापन
इस पोस्ट में, हमने बिना पलक झपकाए सेब और संतरे की तुलना की। हमने तुलना की कि एक्टिवरिकॉर्ड और एक्टो डेटाबेस माइग्रेशन्स और मैपिंग को कैसे संभालते हैं। मौन मूल बैटगर्ल बनाम स्पष्ट 'मैं बैटमैन हूँ' बैटमैन की लड़ाई।
"कन्वेंशन ओवर कॉन्फिगरेशन" के लिए धन्यवाद, एक्टिवरिकॉर्ड का उपयोग करना आमतौर पर कम लिखना शामिल करता है। एक्टो विपरीत दिशा में जाता है, डेवलपर्स को उनके इरादों के बारे में अधिक स्पष्ट होने की आवश्यकता होती है। "कम कोड" सामान्य रूप से बेहतर होने के अलावा, एक्टिवरिकॉर्ड में कुछ इष्टतम डिफ़ॉल्ट होते हैं जो डेवलपर को हर चीज पर निर्णय लेने से और सभी अंतर्निहित कॉन्फिगरेशन्स को समझने से भी बचाते हैं। शुरुआती लोगों के लिए, एक्टिवरिकॉर्ड एक अधिक उपयुक्त समाधान है, क्योंकि यह डिफ़ॉल्ट रूप से "काफी अच्छा" निर्णय लेता है जब तक आप सख्ती से इसके मानक का पालन करते हैं।
एक्टो का स्पष्ट पहलू कोड के एक टुकड़े के व्यवहार को पढ़ना और समझना आसान बनाता है, लेकिन यह डेवलपर को डेटाबेस प्रॉपर्टीज और उपलब्ध सुविधाओं के बारे में अधिक समझने की भी आवश्यकता होती है। जो पहली नज़र में एक्टो को बोझिल लग सकता है, वह इसके गुणों में से एक है। एक्टिवरिकॉर्ड और एक्टो दोनों दुनिया में मेरे व्यक्तिगत अनुभव के आधार पर, एक्टो की स्पष्टता "बिहाइंड द सीन" प्रभावों और अनिश्चितता को हटा देती है जो एक्टिवरिकॉर्ड के साथ प्रोजेक्ट्स में आम है। एक डेवलपर कोड में जो पढ़ता है, वही एप्लिकेशन में होता है और कोई अंतर्निहित व्यवहार नहीं है।
"एक्टिवरिकॉर्ड बनाम एक्टो" श्रृंखला में दो भागों में कुछ हफ्तों में दूसरे ब्लॉग में, हम कवर करेंगे कि क्वेरीज़ और वैलिडेशन्स दोनों एक्टिवरिकॉर्ड और एक्टो में कैसे काम करते हैं।
हम जानना चाहेंगे कि आपने इस लेख के बारे में क्या सोचा। हम कवर करने के लिए नए विषयों की तलाश में हमेशा रहते हैं, इसलिए यदि आपके पास कोई विषय है जिसके बारे में आप अधिक जानना चाहते हैं, तो कृपया @AppSignal पर हमें बताने में संकोच न करें!