কম্পিউটার টিউটোরিয়াল

অ্যাক্টিভরেকর্ড স্টোর মাস্টারিং: রেলসে স্ট্রাকচার্ড ডেটা হ্যান্ডলিংয়ের দক্ষ পদ্ধতি

রেলস একটি বিশাল ফ্রেমওয়ার্ক যেখানে নির্দিষ্ট পরিস্থিতির জন্য অনেক হ্যান্ডি বিল্ট-ইন টুল রয়েছে। এই সিরিজে আমরা রেলসের বিশাল কোডবেসে লুকানো কিছু কম পরিচিত টুল নিয়ে আলোচনা করব।

এই আর্টিকেলে আমরা অ্যাক্টিভরেকর্ডের store এবং store_accessor মেথড দুটোর ওপর ফোকাস করব। এই দুটো মেথডই ডাটাবেস কলামে স্ট্রাকচার্ড ডেটা (যেমন JSON বা YAML) সংরক্ষণের জন্য তৈরি। store_accessor আমাদের গেটার মেথড দিয়ে মডেলকে জটিল না করে এই ডেটা থেকে ভ্যালু বের করার সুবিধা দেয়, অন্যদিকে store এক ধাপ এবং এগিয়ে গিয়ে আমাদের পছন্দের ফরম্যাটে ডেটা ট্রান্সপэрেন্টলি সিরিয়ালাইজ/ডিসিরিয়ালাইজ করে। এটি কোথায় ইউজফুল সেটি বুঝতে আমরা রিলেশনাল ডাটাবেসে JSON স্টোর করার অপশনগুলো এবং এর কারণগুলোও দেখব।

ডাটাবেসে JSON

স্পষ্ট করি, এই আর্টিকেলে আমি 'ডাটাবেস' বলতে রিলেশনাল ডাটাবেস বুঝাচ্ছি, বিশেষ করে PostgreSQL এবং MySQL, কারণ রেলস কমিউনিটিতে এগুলো সবচেয়ে বেশি ব্যবহৃত।

কেউ জিজ্ঞাসা করতে পারে রিলেশনাল ডাটাবেসে JSON কেন রাখবেন। বস্তুত রিলেশনাল ডাটাবেসের সুবিধা নেওয়ার উপায় হলো ডেটা ভাগ করে রেখে তাদের মধ্যে রিলেশনশিপ এনফোর্স করা (যেমন ফরেন কী) এবং ডেটা ইনডেক্স করে কুয়েরি পারফরম্যান্স বাড়ানো।

রিলেশনাল ডাটাবেস মডেলের একটি ড্রব্যাক হলো ডেটা স্ট্রাকচার আগে থেকে জানা থাকতে হয় এবং একটি টেবিলের প্রতিটি রোয়ের জন্য সেটি একই হতে হয়। যদি আপনার অ্যাপ্লিকেশন এমন ডেটার ওপর তৈরি হয় যা এই শর্তগুলো পূরণ করে না, তবে আপনি NoSQL ডাটাবেস খুঁজতে পারেন। অধিকাংশ ওয়েব অ্যাপের জন্য, তবে, আমরা জানা রিলেশনাল ডাটাবেসই ব্যবহার করি অধিকাংশ ডেটার জন্য এবং শুধু এই ডাইনামিক ডেটা স্ট্রাকচারগুলো "সপ্রিংকল" করি বুঝবুঝ করে। এই কেসগুলোতে JSON কলাম খুবই মানে পারে।

JSON vs. JSONB

PostgreSQL-এ JSON কলাম দুটি টাইপ আছে: json এবং jsonb। মূল পার্থক্য হলো jsonb রাইট-টাইমে পার্স হয়, অর্থাৎ ডেটা এমন ফরম্যাটে স্টোর হয় যা ডাটাবেস দ্রুত কুয়েরি করতে পারে। ক্যাভিয়াট হলো যেহেতু JSON ইতিমধ্যে পার্সড, টেক্সট আউটপুট হিসেবে যাওয়ায় এটি একদম ইউজারের ইনপুটের মত নাও হতে পারে। উদাহরণস্বরূপ, ডুপ্লিকেট কী রিমুভ হয়ে যেতে পারে বা কী অর্ডার ওরিজিনালের সাথে মেলা নাও পারে।

PostgreSQL ডকুমেন্টেশন অনুযায়ী, অধিকাংশ কেসে jsonb হচ্ছে যা আপনার দরকার, যদি না কোনো ספেসিফিক কারণ থাকে।

MySQL-এর json কলাম PostgreSQL-এর jsonb-এর মতই আচরণ করে। 'যে ইনপুট দিয়েছে ইউজার' আউটপুট সাপোর্ট করতে হলে সম্ভবত varchar কলাম বা অনুরূপ কিছু ব্যবহার করতে হবে।

JSON vs. Text

ডেটা প্রি-পার্সড রাখার সুবিধার পাশাপাশি, টেক্সট ফিল্ডে একই ডেটা স্টোর করার বদলে JSON কলাম ব্যবহার করলে ডেটা দিয়ে কুয়েরি করা যায়। উদাহরণস্বরূপ, আপনি কুয়েরি করতে পারেন সকল রিকর্ড যেখানে কলামে একটি নির্দিষ্ট কী-ভ্যালু পেয়ার আছে। মনে রাখবেন রেলস নিজে অনেক (যদি কোনো) JSON-স্পেসিফিক কুয়েরি সাপোর্ট করে না, কারণ এগুলো ডাটাবেস-স্পেসিফিক। তাই আপনি যদি এই ফিচারগুলো লিভারেজ করতে চান, তবে SQL কুয়েরি লিখতে হবে।

রেলসে JSON কলাম

রেলসে মাইগ্রেশনে json (এবং PostgreSQL-এ jsonb) কলাম তৈরি করার সাপোর্ট রয়েছে:

class CreateItems < ActiveRecord::Migration[7.0] def change create_table :items do |t| t.jsonb :user_attributes ... end end end 

এই কলাম পড়লে রিটার্নড রেজাল্ট হয় একটি Hash:

> Item.first.user_attributes Item Load (0.6ms) SELECT "items".* FROM "items" ORDER BY "items"."id" ASC LIMIT $1 [["LIMIT", 1]] => {"color"=>"text-red-400"} > Item.first.update!(user_attributes: {color: "text-blue-400"}) > Item.first.user_attributes.dig(:color) => "text-blue-400" 

এখন যেহেতু আমাদের একটি Hash অ্যাট্রিবিউট আছে, আপনি মডেলে কিছু হেল্পার মেথড যোগ করে ভ্যালু রিড/রাইট করতে প্রলুব্ধ হতে পারেন:

class Item < ApplicationRecord def color=(value) self.user_attributes["color"] = value end def color user_attributes.dig("color") end end 

এই মেথডগুলো ভালো কাজ করে কিন্তু যদি আপনার অনেক JSON কী হ্যান্ডেল করতে হয় তবে দ্রুত অসহজ হয়ে যাবে; خوشব@extends রেলস আমাদের কভার করেছে।

অ্যাক্টিভরেকর্ডের store এবং store_accessor

ডাটাবেসে JSON স্টোর করার দুটি দিক আছে: সিরিয়ালাইজেশন এবং এক্সেস। আপনি যদি ডাটাবেসে json-টাইপ কলাম ব্যবহার করেন, তবে সিরিয়ালাইজেশন দিকটি চিন্তা করতে হবে না। রেলস এবং ডাটাবেস অ্যাডাপ্টার এটি হ্যান্ডেল করবে (আপনি সরাসরি store_accessor-এ যেতে পারেন)। আপনি যদি ডেটা টেক্সট কলামে স্টোর করেন, তবে অ্যাক্টিভরেকর্ডের store মেথড আপনার জন্য, যা নিশ্চিত করে যে আপনি কলামে যা লিখছেন সেটি আপনার পছন্দের ফরম্যাটে সিরিয়ালাইজ হচ্ছে।

অ্যাক্টিভরেকর্ডের store

অ্যাক্টিভরেকর্ডের একটি store মেথড আছে যা আমরা আমাদের কলামে পড়ি বা লিখি সেটি অটোমেটিক্যালি সিরিয়ালাইজ করে:

class Item < ApplicationRecord store :user_attributes, accessors: [:color], coder: JSON end 

এখানে, :user_attributes হলো আমরা যে কলামটি ব্যবহার করতে চাই, accessors হলো আমরা যে কীগুলো এক্সেস করতে চাই তার লিস্ট (এখানে শুধু color), এবং শেষে আমরা সপেসিফাই করি ডেটা কীভাবে এনকোড করতে চাই। আমরা JSON ব্যবহার করছি, কিন্তু আপনি যেকোনো কিছু ব্যবহার করতে পারেন, যেমন YAML বা কাস্টম এনকোডিং। এই মেথড শুধু সিরিয়ালাইজেশন (আপনার চয়েন কোডারের সাথে) হ্যান্ডেল করে এবং আন্ডার দ হুড store_accessor কল করে।

অ্যাক্টিভরেকর্ডের store_accessor

আমরা store_accessor ব্যবহার করে আমাদের মডেলে গেট/সেট মেথড তৈরি করি:

class Item < ApplicationRecord store_accessor :user_attributes, :color store_accessor :user_attributes, :name, prefix: true store_accessor :user_attributes, :location, prefix: 'primary' end 

এখানেও, user_attributes হলো ডাটাবেস কলাম, তারপর JSON ডেটাতে যে কীটি ব্যবহার করতে চাই, এবং শেষে প্রিফিক্স (অথবা সাফিক্স) ব্যবহার করার অপশন। মনে রাখবেন store_accessor নেস্টেড ডেটা সাপোর্ট করে না, শুধু টপ-লেভেল কী-ভ্যালু পেয়ার। prefix এবং suffix অপশনগুলো বুলিয়ান, স্ট্রিং বা সিম্বল নিতে পারে। বুলিয়ান true পাস করলে কলামের নামই প্রিফিক্স/সাফিক্স হিসেবে ব্যবহার হয়।

=>item = Item.create!(color: 'red', user_attributes_name: 'Jonathan', primary_location: 'New Zealand') >#<Item:0x000055d63f4f0360 id: 4, user_attributes: {"color"=>"red", "name"=>"Jonathan", "location"=>"New Zealand"}> =>item.color >"red" => item.user_attributes_name >"Jonathan" => item.name >NoMethodError: undefined method `name'... => item.primary_location >"New Zealand" 

রিয়েল-ওয়ার্ল্ড ইউসেজ

আমি কদাচিত কদাচিতই টিপিক্যাল নন-নOWN-আহেড-অফ-টাইম রিলেশনাল ডাটাবেস স্কিমা থেকে ভিন্ন কিছু করতে হয়েছি। যেখানে হয়েছে, সেখানে ডাটাবেস স্ট্রাকচার অপেক্ষাকৃত ক্লিনার এবং সিম্পলার হয়েছে।

একটা উদাহরণ আমি পেয়েছি মাল্টিপাল API সাপোর্ট করার সময় যেখানে ইউজার নিজের একাউন্ট কানেক্ট করে। এটি טרিকি হয়ে যায় যখন API গুলো একই অথেন্টিকেশন স্কিম ব্যবহার করে না। কিছু ইউজারনেম+পাসওয়ার্ড ব্যবহার করতে পারে, অন্যগুলো API কী, আর আরও কিছু API কী, সিক্রেট এবং মার্চেন্ট আইডি ব্যবহার করতে পারে। একটি আপ preocupación হলো টেবিলে কলাম যোগ করতে থাকা, যেখানে অধিকাংশ প্রোভাইডারের জন্য সেগুলো null থাকবে। JSON ব্যবহার করলে আমরা শুধু সেই API যেটি দরকার সেটির ভ্যালুগুলো স্টোর করতে পারি।

একটি সাইড প্রজেক্টে আমি JSON স্টোরেজ ব্যবহার করছি যাতে ইউজাররা আইটেমসে আর্বিট্রারি অ্যাট্রিবিউট সেট করতে পারে, ইউজার-ডিফাইনড অ্যাট্রিবিউটসহ। এই ডেটার ফ্লুইড এবং অনপ্রিডিক্টেবল প্রকৃতির কারণে, JSON স্টোরেজ (জানা অ্যাট্রিবিউটের জন্য store_accessorসহ) একটি ন্যাচারাল ফিট।

সারসংক্ষেপ

JSON ডেটা (এবং এর চারপাশে অ্যাক্টিভরেকর্ডের হেল্পারগুলো) খুবই ইউজফুল যখন ডেটা এবং ডেটা স্ট্রাকচার চেঞ্জেবল বা অজানা। অবশ্য, এই ধরণের ডেটা স্টোরেজ অন্যান্য সবকিছুর মত একটি ট্রেড-অফ। আপনি পার্টিকুলার রেকর্ডের জন্য ডেটা স্ট্রাকচারে খুব ফ্লেক্সিবিলিটি পান, কিন্তু ডাটাবেস কনস্ট্রেইন্টস যা ডেটা ইন্টিগ্রিটি দেয় সেটি কিছুটা হারান। আপনি টিপিক্যাল অ্যাক্টিভরেকর্ড কুয়েরি, জয়েন ইত্যাদি দিয়ে রেকর্ড জুড়ে কুয়েরি করার ক্ষমতাও কমিয়ে দেন।

কয়েকটা রুল অফ থাম্ব, যদি আপনি:

  1. জানেন যে JSON কীগুলো সব রোয়ের জন্য একই থাকবে, অথবা
  2. কোনো অন্য ডাটাবেস টেবিলের আইডি (প্রাইমারি কী) স্টোর করছেন, অথবা
  3. JSON-এ এমন ভ্যালু স্টোর করছেন যেটি টেবিল থেকে রিকর্ড লুকআপ করতে ব্যবহৃত হয়

তবে, আপনি ভালো করবেন একটি নতুন টেবিল তৈরি করে যা ডাটাবেসকে ডেটা ইন্টিগ্রিটি এনফোর্স করতে দেবে। যদি তবে, আপনি রো-স্পেসিফিক ডেটা স্টোর করেন যা সরাসরি অন্য টেবিলের সাথে রিলেটেড নয়, তবে JSON আপনার ডাটাবেস স্ট্রাকচার সিম্পলিফাই করতে সাহায্য করতে পারে।


  1. জাভাস্ক্রিপ্টে টেক্সটএরিয়াতে JSON ডেটা প্রিটিফাই করা

  2. এন্ড্রয়েডে JSON মান অবজেক্টে সংরক্ষণ করার উপায়

  3. JSON কীভাবে Excel-এ কনভার্ট করবেন?

  4. গুগল প্লে স্টোরে ২০২২ সালের টপ ৫ অ্যাওয়ার্ড-বিজয়ী হিডেন জেম অ্যাপস