কম্পিউটার

ActiveRecord বনাম EctoPart One

ডেটা বেশিরভাগ সফ্টওয়্যার অ্যাপ্লিকেশনগুলির একটি মূল অংশ। একটি ডাটাবেস থেকে ডেটা ম্যাপিং এবং অনুসন্ধান করা একজন বিকাশকারীর জীবনে একটি পুনরাবৃত্তিমূলক কাজ। এই কারণে, প্রক্রিয়াটি বোঝা গুরুত্বপূর্ণ এবং কাজটি সহজ করে এমন বিমূর্ততা ব্যবহার করতে সক্ষম হওয়া গুরুত্বপূর্ণ৷

এই পোস্টে, দুটি সিরিজের প্রথমটিতে, আপনি ActiveRecord (রুবি) এবং Ecto (Elixir) এর মধ্যে একটি তুলনা খুঁজে পাবেন। আমরা দেখব কিভাবে উভয় টুলই ডেভেলপারদের ডাটাবেস স্কিমা স্থানান্তর ও ম্যাপ করতে সক্ষম করে।

সুতরাং আমরা আপেল এবং কমলা তুলনা করব। (অরিজিনাল) ব্যাটগার্ল, যে ব্যাটম্যান বনাম একটি শব্দও বলার প্রয়োজন পড়েনি, স্পষ্টভাবে 'আমি ব্যাটম্যান' বলে। অন্তর্নিহিত, কনফিগারেশন ওভার কনভেনশন, বনাম স্পষ্ট উদ্দেশ্য। প্রথম রাউন্ড. যুদ্ধ!

ActiveRecord

এটি প্রকাশের পর থেকে 10 বছরেরও বেশি সময় ধরে, সম্ভাবনা রয়েছে, আপনি ইতিমধ্যে ActiveRecord সম্পর্কে শুনেছেন - বিখ্যাত ORM যা রুবি অন রেল প্রকল্পগুলির সাথে ডিফল্টভাবে পাঠানো হয়৷

ActiveRecord MVC-তে M হল - মডেল - যা ব্যবসার ডেটা এবং যুক্তি উপস্থাপনের জন্য দায়ী সিস্টেমের স্তর। ActiveRecord ব্যবসায়িক বস্তু তৈরি এবং ব্যবহারের সুবিধা দেয় যার ডেটা একটি ডাটাবেসে অবিরাম স্টোরেজ প্রয়োজন। এটি ActiveRecord প্যাটার্নের একটি বাস্তবায়ন যা নিজেই, একটি অবজেক্ট রিলেশনাল ম্যাপিং সিস্টেমের বর্ণনা৷

যদিও এটি বেশিরভাগই রেলের সাথে ব্যবহার করা হয় বলে জানা যায়, তবে ActiveRecord একটি স্বতন্ত্র সরঞ্জাম হিসাবেও ব্যবহার করা যেতে পারে, অন্যান্য প্রকল্পগুলিতে এমবেড করা হয়৷

Ecto

ActiveRecord-এর সাথে তুলনা করলে, Ecto হল বেশ নতুন (এবং এই মুহূর্তে তেমন বিখ্যাত নয়) টুল। এটি এলিক্সিরে লেখা এবং ফিনিক্স প্রকল্পে ডিফল্টরূপে অন্তর্ভুক্ত।

ActiveRecord এর বিপরীতে, Ecto একটি ORM নয়, কিন্তু একটি লাইব্রেরি যা এলিক্সির ব্যবহার করে প্রশ্ন লিখতে এবং ডাটাবেসের সাথে ইন্টারঅ্যাক্ট করতে সক্ষম করে।

Ecto এলিক্সিরে কোয়েরি লেখা এবং ডাটাবেসের সাথে ইন্টারঅ্যাক্ট করার জন্য একটি ডোমেন নির্দিষ্ট ভাষা।

ডিজাইন অনুসারে, Ecto হল একটি স্বতন্ত্র টুল, যা বিভিন্ন এলিক্সির প্রজেক্টে ব্যবহার করা হচ্ছে এবং কোন ফ্রেমওয়ার্কের সাথে সংযুক্ত নয়।

আপনি আপেল এবং কমলালেবুর তুলনা করছেন না?

হ্যাঁ আমরা! যদিও ActiveRecord এবং Ecto শব্দার্থগতভাবে আলাদা, কিন্তু সাধারণ বৈশিষ্ট্য যেমন ডাটাবেস মাইগ্রেশন, ডাটাবেস ম্যাপিং, প্রশ্ন এবং বৈধতা ActiveRecord এবং Ecto উভয় দ্বারা সমর্থিত। এবং আমরা উভয় সরঞ্জাম ব্যবহার করে একই ফলাফল অর্জন করতে পারি। রুবি ব্যাকগ্রাউন্ড থেকে যারা এলিক্সিরে আগ্রহী তাদের জন্য আমরা ভেবেছিলাম এটি একটি আকর্ষণীয় তুলনা হবে।

চালান সিস্টেম

পোস্টের বাকি অংশ জুড়ে, একটি অনুমানমূলক চালান পদ্ধতি প্রদর্শনের জন্য ব্যবহার করা হবে। আসুন কল্পনা করুন আমাদের কাছে সুপার হিরোদের স্যুট বিক্রি করার একটি দোকান আছে। জিনিসগুলি সহজ রাখতে, চালান সিস্টেমের জন্য আমাদের কাছে শুধুমাত্র দুটি টেবিল থাকবে:ব্যবহারকারীরা এবং চালান .

নীচে সেই টেবিলগুলির গঠন, তাদের ক্ষেত্র এবং প্রকারগুলি সহ:

ব্যবহারকারীরা

ক্ষেত্র টাইপ
পূর্ণ_নাম স্ট্রিং
ইমেল স্ট্রিং
created_at (ActiveRecord) / inserted_at (Ecto) তারিখ সময়
updated_at তারিখ সময়

চালান

ক্ষেত্র টাইপ
user_id পূর্ণসংখ্যা
পেমেন্ট_পদ্ধতি স্ট্রিং
paid_at তারিখ সময়
created_at (ActiveRecord) / inserted_at (Ecto) তারিখ সময়
updated_at তারিখ সময়

ব্যবহারকারীর টেবিলে চারটি ক্ষেত্র রয়েছে:full_name , ইমেল , আপডেট করা হয়েছে এবং একটি চতুর্থ ক্ষেত্র যা ব্যবহৃত টুলের উপর নির্ভরশীল। ActiveRecord একটি created_at তৈরি করে ক্ষেত্র যখন Ecto একটি insert_at তৈরি করে ডাটাবেসে রেকর্ডটি প্রথম ঢোকানোর মুহূর্তটির টাইমস্ট্যাম্প প্রতিনিধিত্ব করার জন্য ক্ষেত্র৷

দ্বিতীয় টেবিলটির নাম চালান . এর পাঁচটি ক্ষেত্র রয়েছে:user_id , পেমেন্ট_পদ্ধতি , paid_at , আপডেট করা হয়েছে এবং, ব্যবহারকারীদের টেবিলের অনুরূপ, হয় created_at অথবা insert_at , ব্যবহৃত টুলের উপর নির্ভর করে।

ব্যবহারকারী এবং চালান সারণীতে নিম্নলিখিত অ্যাসোসিয়েশন রয়েছে:

  • একজন ব্যবহারকারীর অনেক ইনভয়েস আছে
  • একটি চালান একজন ব্যবহারকারীর অন্তর্গত

মাইগ্রেশন

মাইগ্রেশন ডেভেলপারদের একটি পুনরাবৃত্তিমূলক প্রক্রিয়া ব্যবহার করে সময়ের সাথে সাথে তাদের ডাটাবেস স্কিমাকে সহজেই বিকশিত করতে দেয়। ActiveRecord এবং Ecto উভয়ই ডেভেলপারদের সরাসরি SQL এর সাথে ডিল করার পরিবর্তে উচ্চ-স্তরের ভাষা (যথাক্রমে রুবি এবং এলিক্সির) ব্যবহার করে ডেটাবেস স্কিমা স্থানান্তর করতে সক্ষম করে।

চলুন এক নজরে দেখে নেওয়া যাক কিভাবে ActiveRecord এবং Ecto-এ মাইগ্রেশন কাজ করে ব্যবহারকারী এবং চালান টেবিল তৈরি করতে ব্যবহার করে।

ActiveRecord:ব্যবহারকারীদের টেবিল তৈরি করা

মাইগ্রেশন

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

ActiveRecord মাইগ্রেশন create_table ব্যবহার করে টেবিল তৈরি করতে সক্ষম করে পদ্ধতি যদিও created_at এবং updated_at ক্ষেত্রগুলি মাইগ্রেশন ফাইলে সংজ্ঞায়িত করা হয় না, t.timestamps এর ব্যবহার উভয় তৈরি করতে ActiveRecord ট্রিগার করে।

টেবিল কাঠামো তৈরি করা হয়েছে

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)

মাইগ্রেশন ইমেল ক্ষেত্রের জন্য একটি অনন্য সূচক তৈরির জন্যও দায়ী। বিকল্প index: {unique: true} ইমেল ক্ষেত্রের সংজ্ঞায় পাস করা হয়। এই কারণেই টেবিলটি "index_users_on_email" UNIQUE, btree (email) তালিকাভুক্ত করেছে এর কাঠামোর অংশ হিসাবে সূচক।

Ecto:ব্যবহারকারীদের টেবিল তৈরি করা

মাইগ্রেশন

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

Ecto মাইগ্রেশন create() ফাংশনকে একত্রিত করে এবং table() ব্যবহারকারীদের টেবিল তৈরি করতে। Ecto মাইগ্রেশন ফাইলটি এর ActiveRecord সমতুল্য। ActiveRecord-এ টাইমস্ট্যাম্প ক্ষেত্রগুলি (created_at এবং updated_at ) t.timestamps দ্বারা তৈরি করা হয়েছে Ecto টাইমস্ট্যাম্প ক্ষেত্রগুলিতে থাকাকালীন (inserted_at এবং updated_at ) timestamps() দ্বারা তৈরি করা হয় ফাংশন।

কিভাবে সূচী তৈরি করা হয় উভয় সরঞ্জামের মধ্যে একটি ছোট পার্থক্য আছে। ActiveRecord-এ, সূচকটি তৈরি করা ক্ষেত্রটির বিকল্প হিসাবে সংজ্ঞায়িত করা হয়। Ecto 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 চালানোর জন্য তৈরি করা টেবিল অ্যাক্টিভরেকর্ড ব্যবহার করে তৈরি করা টেবিলে মাইগ্রেশনের একটি অভিন্ন কাঠামো রয়েছে।

ActiveRecord: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 পদ্ধতি, যেটি আগেরটিতে উপস্থিত ছিল না। এটি ব্যবহারকারীদের টেবিলের একটি রেফারেন্স তৈরি করতে ব্যবহৃত হয়। পূর্বে বর্ণিত হিসাবে, একজন ব্যবহারকারীর অনেক চালান আছে এবং একটি চালান একজন ব্যবহারকারীর অন্তর্গত। 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 ), যা ActiveRecord স্বয়ংক্রিয়ভাবে যোগ করে যখন t.references পদ্ধতি ব্যবহার করা হয়।

Ecto: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

Ecto references() ব্যবহার করে ডাটাবেস রেফারেন্স তৈরি করতেও সমর্থন করে ফাংশন ActiveRecord এর বিপরীতে, যা কলামের নাম অনুমান করে, Ecto-এর জন্য ডেভেলপারকে স্পষ্টভাবে user_id সংজ্ঞায়িত করতে হবে কলামের নাম। references() ফাংশনের জন্য ডেভেলপারকে স্পষ্টভাবে রেফারেন্সটি নির্দেশিত টেবিলটি সংজ্ঞায়িত করতে হবে, যা এই উদাহরণে, ব্যবহারকারীর টেবিল।

টেবিল কাঠামো তৈরি করা হয়েছে

     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 ভাবে আসে বৈশিষ্ট্য পরিচালনা করা হয়, কিছু পার্থক্য আছে:

  1. Ecto user_id-এ একটি বিদেশী-কী সীমাবদ্ধতা তৈরি করে ক্ষেত্র ("invoices_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ), যা ব্যবহারকারী এবং চালান টেবিলের মধ্যে রেফারেন্সিয়াল অখণ্ডতা বজায় রাখে।

  2. ActiveRecord স্বয়ংক্রিয়ভাবে user_id-এর জন্য একটি সূচক তৈরি করে কলাম Ecto-এর জন্য ডেভেলপারকে সে সম্পর্কে স্পষ্ট হতে হবে। এই কারণেই মাইগ্রেশনে create index(:invoices, [:user_id]) আছে বিবৃতি।

ActiveRecord:ডেটা ম্যাপিং এবং অ্যাসোসিয়েশনগুলি

ActiveRecord তার "কনভেনশন ওভার কনফিগারেশন" নীতিবাক্যের জন্য পরিচিত। এটি ডিফল্টরূপে মডেল শ্রেণীর নাম ব্যবহার করে ডাটাবেস টেবিলের নাম অনুমান করে। User নামের একটি ক্লাস , ডিফল্টরূপে, User ব্যবহার করে তার উত্স হিসাবে টেবিল। ActiveRecord একটি উদাহরণ বৈশিষ্ট্য হিসাবে টেবিলের সমস্ত কলাম ম্যাপ করে। ডেভেলপারদের শুধুমাত্র টেবিলের মধ্যে অ্যাসোসিয়েশন নির্ধারণ করতে হবে। এগুলি ActiveRecord দ্বারা জড়িত ক্লাস এবং টেবিলগুলি অনুমান করতেও ব্যবহৃত হয়৷

ActiveRecord ব্যবহার করে কিভাবে ব্যবহারকারী এবং চালান টেবিল ম্যাপ করা হয় তা দেখুন:

ব্যবহারকারীরা

class User < ApplicationRecord
  has_many :invoices
end

চালান

class Invoice < ApplicationRecord
  belongs_to :user
end

ইক্টো:ডেটা ম্যাপিং এবং অ্যাসোসিয়েশনগুলি

অন্যদিকে, Ecto-এর জন্য ডেভেলপারকে ডেটা উৎস এবং এর ক্ষেত্রগুলি সম্পর্কে স্পষ্ট হতে হবে। যদিও Ecto এর অনুরূপ has_many আছে এবং belongs_to বৈশিষ্ট্যগুলির জন্য, এর জন্য ডেভেলপারদের সংশ্লিষ্ট টেবিল এবং স্কিমা মডিউল সম্পর্কে স্পষ্ট হতে হবে যা সেই টেবিল স্কিমা পরিচালনা করতে ব্যবহৃত হয়৷

এইভাবে Ecto ব্যবহারকারী এবং চালান টেবিল ম্যাপ করে:

ব্যবহারকারীরা

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

চালান

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

রেপ আপ

এই পোস্টে, আমরা এক পলক ছাড়াই আপেল এবং কমলার তুলনা করেছি। আমরা তুলনা করেছি কিভাবে ActiveRecord এবং Ecto ডাটাবেস মাইগ্রেশন এবং ম্যাপিং পরিচালনা করে। অন্তর্নিহিত স্লিয়েন্ট আসল ব্যাটগার্ল বনাম স্পষ্ট 'আমি ব্যাটম্যান' ব্যাটম্যানের যুদ্ধ।

"কনভেনশন ওভার কনফিগারেশন" এর জন্য ধন্যবাদ, অ্যাক্টিভরেকর্ড ব্যবহারে সাধারণত কম লেখা জড়িত থাকে। Ecto বিপরীত দিকে যায়, ডেভেলপারদের তাদের উদ্দেশ্য সম্পর্কে আরও স্পষ্ট হতে হবে। "কম কোড" সাধারণভাবে ভাল হওয়া ছাড়া, ActiveRecord-এ কিছু সর্বোত্তম ডিফল্ট রয়েছে যা বিকাশকারীকে সবকিছুর বিষয়ে সিদ্ধান্ত নিতে এবং সমস্ত অন্তর্নিহিত কনফিগারেশনগুলি বুঝতে হতে বাঁচায়। নতুনদের জন্য, ActiveRecord হল আরও উপযুক্ত সমাধান, কারণ এটি ডিফল্টভাবে "যথেষ্ট ভালো" সিদ্ধান্ত নেয় যতক্ষণ না আপনি কঠোরভাবে এর মান অনুসরণ করেন।

Ecto-এর সুস্পষ্ট দিকটি কোডের একটি অংশের আচরণ পড়া এবং বোঝা সহজ করে তোলে, তবে এটি ডেভেলপারকে ডেটাবেস বৈশিষ্ট্য এবং উপলব্ধ বৈশিষ্ট্যগুলি সম্পর্কে আরও বোঝার প্রয়োজন। Ectoকে প্রথম নজরে যা কষ্টকর দেখাতে পারে, তা হল এর অন্যতম গুণ। ActiveRecord এবং Ecto উভয় জগতেই আমার ব্যক্তিগত অভিজ্ঞতার উপর ভিত্তি করে, Ecto-এর স্পষ্টতা "দৃশ্যের পিছনে" প্রভাব এবং অনিশ্চয়তা দূর করে যা ActiveRecord-এর সাথে প্রজেক্টে সাধারণ। একজন ডেভেলপার কোডে যা পড়েন, সেটিই অ্যাপ্লিকেশনে ঘটে এবং কোন অন্তর্নিহিত আচরণ নেই।

কয়েক সপ্তাহের মধ্যে একটি দ্বিতীয় ব্লগে, "ActiveRecord vs Ecto" সিরিজের দুটি অংশে, ActiveRecord এবং Ecto উভয় ক্ষেত্রে প্রশ্ন এবং বৈধতা কীভাবে কাজ করে তা আমরা কভার করব।

আপনি এই নিবন্ধটি সম্পর্কে কি ভেবেছিলেন তা জানতে আমরা চাই। আমরা সর্বদা কভার করার জন্য নতুন বিষয়গুলির সন্ধানে থাকি, তাই যদি আপনার কাছে এমন একটি বিষয় থাকে যা আপনি আরও জানতে চান, অনুগ্রহ করে আমাদের @AppSignal-এ জানাতে দ্বিধা করবেন না!


  1. ডাটাবেসে বাইনারি সম্পর্ক

  2. ডাটাবেসে N-ary সম্পর্ক

  3. ইআর ডায়াগ্রামের মিনিমাইজেশন

  4. ঠিক করুন:Err_Connection_Closed