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

Noticed এবং CableReady দিয়ে Rails-এ রোবাস্ট সিস্টেম নোটিফিকেশন ইমপ্লিমেন্ট করুন

এই আর্টিকেল আংশিকভাবে লেখকের আগামী Advanced CableReady বইয়ের একটি চ্যাপ্টার থেকে অনুপ্রাণিত এবং AppSignal-এর জন্য এই গেস্ট পোস্টে টেইলর করা হয়েছে।

নোটিফিকেশন অনেক ওয়েব অ্যাপ্লিকেশনের একটি টিপিক্যাল cross-cutting concern।

Noticed gem নোটিফিকেশন ডেভেলপমেন্ট খুব সহজ করে দেয় ডেটাবেস-ব্যাকড মডেল এবং প্লাগেবল ডেলিভারি মেথড দিয়ে আপনার Ruby on Rails অ্যাপ্লিকেশনের জন্য। বিল্ট-ইন সাপোর্ট আছে মেইলার, websockets, এবং আরও কয়েকটি ডেলিভারি মেথডের জন্য।

আমরা CableReady gem-এর মেরিটও পরীক্ষা করব সিস্টেম নোটিফিকেশন ট্রিগার করার জন্য Ruby on Rails অ্যাপ্লিকেশনে।

পূর্বশর্ত এবং প্রয়োজনীয়তা

কখনো কখনো আপনার অ্যাপ থেকে সিস্টেম নোটিফিকেশন ট্রিগার করতে হতে পারে। Notifications API দিয়ে এটা করা যায়।

উদাহরণ: আপনার অ্যাপ্লিকেশন ইউজারদের বড় ফাইল আপলোড করতে দেয় যেগুলো ট্রান্সকোড হতে অনেক সময় নেয়। আপনি চাইলে ইউজারকে নোটিফাই করতে পারেন একবার তাদের ভিডিও আপলোড কমপ্লিট হলে। এতে তারা মিনিটখানি আপনার অ্যাপ খোলা রাখতে হবেনা, অন্য টাস্কে যেতে পারবে।

শুধু এই দুটি পূর্বশর্তে সহজে ইমপ্লিমেন্ট করা যায়:

  • Noticed-এ custom delivery methods সাপোর্ট (Noticed একটি সিম্পল API এক্সপোজ করে যেকোনো ট্রান্সপোর্ট মেকানিজম ইমপ্লিমেন্ট করতে — উদাহরণস্বরূপ Discord servers-এ পোস্ট করা)
  • CableReady-এ notification operation আছে

CableReady এবং Noticed-এর জন্য প্রয়োজনীয় লিস্ট ছোটো — আপনার শুধু ইনি লাগবে:

  • একটি ActionCable সার্ভার রানিং
  • একটি ActiveJob ব্যাকএন্ড (সাধারণত Noticed দ্বারা ব্যবহার করা হয়)

নোট: এই প্রজেক্টের পুরো স্যাম্পল কোড GitHub-এ উপলব্ধ। নিচে ধাপে ধাপে গাইড করছি।

Rails অ্যাপ্লিকেশনের জন্য CableReady Primer

CableReady জানি নেই। ২০১৭ সালে রিলিজ, এটি চিন্তা করা যায় "missing ActionCable standard library" হিসেবে।

Turbo আসার আগে, Ruby on Rails-এ রিয়েল-টাইম অ্যাপ্লিকেশন বানাতে একমাত্র পথ ছিল ActionCable। ActionCable হল Rails-এর নেটিভ র‍্যাপার WebSockets-এর চারদিকે, যা সার্ভার-সাইড এবং ক্লায়েন্ট-সাইড API দেয় পারসিস্টেন্ট কানেকশনের মাধ্যমে দুইদিকেই যেকোনো সময় মেসেজ পাঠানোর জন্য।

এই পদ্ধতির ডাউনসাইড: খুব বেশি boilerplate কোড লিখতে হতো।

এখানেই CableReady সাহায্য করে DOM অপারেশনগুলোর একটি abstraction layer দিয়ে যেগুলো সার্ভার থেকে ট্রিগার করা যায়। কিছু উদাহরণ:

  • DOM mutations (inner_html, insert_adjacent_html, morph, ইত্যাদি)
  • DOM element property mutations (add_css_class, remove_css_class, set_dataset_property, ইত্যাদি)
  • arbitrary DOM events dispatch করা
  • browser history manipulations
  • notifications (যেটা আমরা ব্যবহার করব)

CableReady Server এবং Client

CableReady কীভাবে ম্যাজিক করে? সংক্ষেপে, এটার দুটি পার্ট: server-side এবং client-side।

সার্ভার সাইডে, CableReady::Broadcaster মডিউল আপনার অ্যাপ্লিকেশনের যেকোনো পার্টে ইনক্লুড করা যায় যেটা এর জন্য কল করে। এটি হতে পারে একটি জব, মডেল কলব্যাক, বা প্লেইন কন্ট্রোলার। কিন্তু প্রথমে একটি ActionCable চ্যানেল থাকতে হবে। CableReady ডকুমেন্টেশন অনুযায়ী:

# app/channels/visitors_channel.rb
class VisitorsChannel < ApplicationCable::Channel
  def subscribed
    stream_from "visitors"
  end
end

visitors হল stream identifier। এটি ব্রড অডিয়েন্স বা স্পেসিফিক ক্লায়েন্ট টার্গেট করতে ব্যবহার করা যায় যারা আপনার চ্যানেল সাবস্ক্রাইব করেছে। উদাহরণ সমাপ্তি: Broadcaster মডিউল ইনক্লুড করে একটি মডেলে সাইন-আপের পর ক্লায়েন্টে console.log পাঠান।

ক্লায়েন্ট সাইডে লজিক সিম্পল। উপরের চ্যানেলে সাবস্ক্রিপশন তৈরি করুন। তারপর এর received hook-এ CableReady.perform কল করুন ওয়ায়ার 넘는 সব অপারেশনের ওপর।

// app/javascript/channels/visitors_channel.js
import consumer from "./consumer"
import CableReady from "cable_ready"

consumer.subscriptions.create("VisitorsChannel", {
  received(data) {
    CableReady.perform(data.operations)
  }
})

CableReady vs Turbo for Rails

সমার্প: কখন CableReady ব্যবহার করবেন, কখন এড়াবেন?

Turbo introducción-এ ওয়েব ডেভেলপমেন্ট কমিউনিটিকে একটি পাওয়ারফুল টুলবক্স মেলে সার্ভার-রেন্ডার্ড রিয়েকটিভ অ্যাপ্লিকেশন বানাতে। এটিএসেনশিয়ালি একটি ফ্রন্টএন্ড টেকনোলজি স্ট্রอง সার্ভার-সাইড বایندিংসহ Rails-এ, যা স্ট্যান্ডার্ড MVC স্ট্যাকে ফিট করে। তাই এটি আপনার টিপিক্যাল অ্যাপের অধিকাংশ রিকোয়ারমেন্ট কভার করতে পারে।

CableReady, অন্যদিকে, রিয়েল-টাইম Rails ডেভেলপমেন্টের Swiss army knife এবং সাবধানে ব্যবহার করা উচিত। এটি একটি পাওয়ারফুল abstraction যা খুব inviting লাগতে পারে pervasive-ly ব্যবহার করতে। কিন্তু যদি আপনি কল্পনা করেন আপনার DOM-এর প্রতিটি পার্ট যেকোনো লোকেশন থেকে মিউটেট করা যায়, তবে আপনি বুঝবেন এটি race conditions এবং hard-to-track-down bugs-এ 이끌তে পারে।

কিন্তু বর্তমান কেসের মত কিছু ক্ষেত্রে CableReady perfect sense করে কারণ এটি DOM-এর ওপর আরও ফাইন-গ্রেইন্ড কন্ট্রোল দেয়।

সিম্পল TLDR চাইলে: Turbo হল অ্যাপ্লিকেশন ডেভেলপারদের জন্য, CableReady হল লাইব্রেরি বিল্ডারদের জন্য। কিন্তু সেই মাঝপথে grey areas আছে।

Noticed — Ruby on Rails অ্যাপ্লিকেশনের জন্য সিম্পল নোটিফিকেশন

দ্বিতীয় লাইব্রেরি যা সিস্টেম নোটিফিকেশন ডেলিভার করতে ব্যবহার করব: Chris Oliver-এর Noticed gem। এর হৃদয়ে একটি ActiveRecord মডেল আছে যা একক নোটিফিকেশন একটি রিসিপিয়েন্টের জন্য মডেল করে। এটি কমন মেটাডেটা ধারণ করে:

  • নোটিফিকেশন কাকে পাঠানো হয়েছে (recipient)
  • নোটিফিকেশন কখন রিড হয়েছে
  • নোটিফিকেশনের সাথে জড়িত যেকোনো প্যারামিটার (সাধারণত অন্য মডেলের রেফারেন্স)

ActiveStorage/ActionText meta-tables কীভাবে কাজ করে সেটা জানলে এটি খুব সিমিলার লাগবে।

এছাড়া Noticed POROs (Plain Old Ruby Objects, অর্থাৎ Rails বা অন্যান্য ফ্রেমওয়ার্কের সাথে কোনো কানেকশন নেই এমন অবজেক্ট) ব্যবহার করে যেগুলো আসল নোটিফিকেশনদের জন্য ব্লুপ্রিন্ট হিসেবে কাজ করে। এগুলোকেও ভুলে Notifications বলা হয় এবং লজিক ধারণ করে কীভাবে রেন্ডার এবং ডিস্ট্রিবিউট করতে হয়। README-র একটি উদাহরণ:

class CommentNotification < Noticed::Base
  deliver_by :database
  deliver_by :action_cable
  deliver_by :email, mailer: "CommentMailer"

  param :comment
  # ...
end

deliver_by invocation-গুলো স্পেশাল ইন্টারেস্টের কারণ এগুলো নির্ধারণ করে কোন ডেলিভারি মেথড এই নোটিফিকেশন ব্যবহার করবে:

  • deliver_by :database — Notification রেকর্ড স্টোর করে (উপরোক্ত মডেল) লেটার অ্যাক্সেসের জন্য
  • deliver_by :action_cable — ডিফাইন করা ActionCable চ্যানেল এবং stream দিয়ে পাঠায় (ডিফল্ট Noticed::NotificationChannel)
  • deliver_by :email — মেইলার স্পেসিফাই করে যা নোটিফিকেশন পাঠাবে। উদাহরণে দেখানো হয়েছে রিসিপিয়েন্টের preference ফ্যাক্টর ইন করা।

এই আর্টিকেলের বাকি অংশের লক্ষ্য: একটি কাস্টম ডেলিভারি মেথড ইমপ্লিমেন্ট করা যা সিস্টেম নোটিফিকেশন পাঠাবে।

কাস্টম ডেলিভারি মেথড: Notifications API দিয়ে সিস্টেম নোটিফিকেশন

১. Recipients প্রস্তুত করুন

Noticed-এ User মডেল লাগে recipient হিসেবে। সংক্ষেপে Devise পুল ইন করুন এবং User মডেল জেনারেট করুন।

Rails console-এ স্যাম্পল ইউজার তৈরি করুন।

২. Noticed যোগ করুন

$ bundle add noticed
$ rails g noticed:model
$ rails db:migrate

User মডেলে polymorphic has_many অ্যাসোসিয়েশন যোগ করুন।

ব্লুপ্রিন্ট PORO তৈরি করুন:

# app/notifications/new_comment_notification.rb
class NewCommentNotification < Noticed::Base
  deliver_by :database
  # placeholder message
  def message
    "New comment received"
  end
end

Rails console-এ ডেমো:
NewCommentNotification.deliver(user: user) — ডেটাবেস ইনসার্ট হবে। user.notifications দিয়ে সব নোটিফিকেশন গ্র্যাব করুন।

সিম্পল ইনডেক্স ভিউ বানান লগড-ইন ইউজারের সব ডেলিভারড নোটিফিকেশন লিস্ট করতে। bin/dev চালিয়ে লগইন করে https://localhost:3000/notifications-এ যান।

Noticed এবং CableReady দিয়ে Rails-এ রোবাস্ট সিস্টেম নোটিফিকেশন ইমপ্লিমেন্ট করুন

৩. CableReady ইনস্টল করুন

$ bundle add cable_ready
$ rails g cable_ready:install

NotificationChannel জেনারেট করুন মেসেজ ডেলিভার করতে:

$ rails g channel Notification

এটি মিসিং ActionCable (JavaScript) dependencies অ্যাড করবে এবং চ্যানেল ফাইল স্কাফফোল্ড করবে।

সার্ভার-সাইড চ্যানেলে Noticed::NotificationChannel-এর থেকে ইনহেরিট করুন।

ActionCable Devise ইউজারদের জন্য authenticated হওয়া দরকার। 보일ারপ্লেট:

# config/initializers/action_cable.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    private

    def find_verified_user
      # Devise current_user লজিক
    end
  end
end

StimulusReflex ডক্স দেখুন অন্যান্য অপশনের জন্য।

ক্লায়েন্ট সাইড সেটআপ কোড যোগ করুন।

নোট: ActionCable-র জন্য Redis দরকার, বাকি আর্টিকেলে লোকাল সার্ভার রানিং আছে ধরা হয়েছে।

৪. Delivery Method Implementation

সিস্টেম নোটিফিকেশন ব্রডকাস্ট করতে নতুন ডেলিভারি মেথড জেনারেট করুন:

$ rails g noticed:delivery_method SystemNotification

স্কাফফোল্ডেড ক্লাস:

class DeliveryMethods::SystemNotification < Noticed::DeliveryMethods::Base
  def deliver
    # implementation
  end
end

deliver মেথড কীভাবে কাজ করবে সেটা ড্রাফ্ট করুন:

def deliver
  channel = self.class.channel || "Noticed::NotificationsChannel"
  CableReady[channel].notification(
    title: notification.title,
    body: notification.message,
    icon: notification.icon
  ).broadcast_to(notification.recipient)
end

channel মেথড বিল্ট-ইন ActionCable ডেলিভারি মেথড থেকে আংশিকভাবে বরো করা। ক্লাস মেথড অপশন দিয়ে চ্যানেল পাস করা যায়, না হলে ডিফল্ট Noticed::NotificationsChannel-এ ফলব্যাক।

CableReady-এর notification মেথড ব্যবহার করে respective instance ব্রডকাস্ট করুন recipient-এ।

নোটিফিকেশন PORO-এ কানেক্ট করুন:

class NewCommentNotification < Noticed::Base
  deliver_by :database
  deliver_by :system_notification
  # ...
end

৫. কাজে লাগান

Rails console-এ আবার চালান:

NewCommentNotification.deliver(user: user)

ব্রাউজার প্রথমে পারমিশন চাইবে নোটিফিকেশন রিসিভ করার জন্য:

Noticed এবং CableReady দিয়ে Rails-এ রোবাস্ট সিস্টেম নোটিফিকেশন ইমপ্লিমেন্ট করুন

কনফার্ম করলে সুন্দর পপ-আপ নোটিফিকেশন দেখবেন:

Noticed এবং CableReady দিয়ে Rails-এ রোবাস্ট সিস্টেম নোটিফিকেশন ইমপ্লিমেন্ট করুন

উপসংহার

CableReady এবং Noticed দিয়ে একটি ফাস্ট লেন টুর নেওয়া হয়েছে, নেটিভ ব্রাউজার API আপনার অ্যাপে ইন্টিগ্রেট করার পদ্ধতি দেখানো হয়েছে। ফলাফল: ইউজারদের সিস্টেম নোটিফিকেশন ডেলিভার করার একটি সিম্পল, কোহেরেন্ট পদ্ধতি।

এই ইউজ কেস ইলাস্ট্রেট করে কীভাবে সহজে CableReady আপনার ইউজ কেসে মিক্স করা যায়। এক ধাপ আগে চিন্তা করলে ড্রাফটেড ডেলিভারি মেথড লাইব্রেরি হিসেবে ডিকাপল করা কঠিন নয়।

আশা করি এটি আপনাকে আপনার অ্যাপে vertical reactive problem domains খুঁজে বের করতে এবং CableReady ট্রাই করতে ইনস্পাইর করবে।

আরো পড়তে চাইলে আমার নতুন বই Advanced CableReady কিনুন।

Coupon code: APPSIGNAL-PROMO দিয়ে $10 বাঁচান!

Happy coding!

P.S. Ruby Magic পোস্টগুলি প্রকাশ होते সাথে সাথে পেতে আমাদের Ruby Magic নিউজলেটার সাবস্ক্রাইব করুন!

  1. Oracle GoldenGate মাস্টার করুন: কোর কনসেপ্ট ও প্র্যাকটিক্যাল অ্যাপ্লিকেশন

  2. পাইথনে দেওয়া ইনডেক্স অনুযায়ী স্ট্রিং শাফল করার প্রোগ্রাম

  3. HTML DOM Video height প্রোপার্টি

  4. Spring Boot-এ application.properties দিয়ে লোকাল MySQL কানেক্ট করা