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

उप डोमेन के साथ रेल ऐप पर एक बहु-किरायेदार रूबी का निर्माण

मल्टीटेनेंसी की परिभाषा के अनुसार, जब कोई ऐप कई टैनेंट को सेवा देता है, तो इसका मतलब है कि उपयोगकर्ताओं के कुछ समूह हैं जो सॉफ़्टवेयर इंस्टेंस तक सामान्य पहुंच साझा करते हैं। मल्टीटेनेंसी का समर्थन करने वाले ऐप का एक उत्कृष्ट उदाहरण जीरा प्लेटफॉर्म है, जहां प्रत्येक कंपनी के पास सॉफ्टवेयर तक पहुंचने के लिए अपना सबडोमेन होता है, उदाहरण के लिए, mycompany.atlassian.net

इस लेख में, मैं आपको बहु-किरायेदारी के सैद्धांतिक और व्यावहारिक दोनों पहलुओं से परिचित कराने जा रहा हूँ। आपके आवेदन में एकाधिक किरायेदारों के लिए समर्थन लागू करने के लिए कुछ लोकप्रिय प्रकार के दृष्टिकोणों पर चर्चा करने के बाद, मैं आपको दिखाऊंगा कि आप अपने रेल आवेदन में उनमें से दो को कैसे कार्यान्वित कर सकते हैं। हम कई टेनेंट के साथ एक साधारण ऐप बनाएंगे, जहां प्रत्येक टेनेंट का अपना सबडोमेन होगा।

इस लेख को पढ़ने के बाद, आप निम्न में सक्षम होंगे:

  • विभिन्न प्रकार के मल्टी-टेनेंट ऐप्स पर चर्चा करें और बताएं कि दिया गया तरीका कब सही विकल्प है,
  • एकाधिक किरायेदारों के समर्थन के साथ रेल एप्लिकेशन पर रूबी बनाएं, और
  • Ruby on Rails एप्लिकेशन के अंदर अपने ग्राहकों के लिए कस्टम सबडोमेन का उपयोग करें।

इस लेख का अनुसरण करने और इसके अधिकांश लाभ प्राप्त करने के लिए रेल के बारे में एक बुनियादी ज्ञान की आवश्यकता है।

सिद्धांत में बहुलता

जैसा कि मैंने पहले उल्लेख किया है, हम कह सकते हैं कि ऐप मल्टीटेनेंसी का समर्थन करता है जब यह उन उपयोगकर्ताओं के कुछ समूहों की सेवा करता है जो एप्लिकेशन की सुविधाओं तक सामान्य पहुंच साझा करते हैं। ऐसे ऐप का एक अच्छा उदाहरण एक ब्लॉगिंग प्लेटफॉर्म है जहां प्रत्येक उपयोगकर्ता को मुख्य डोमेन में एक अलग उप डोमेन मिलता है। प्रत्येक ब्लॉग का अपना उप डोमेन होता है लेकिन अन्य ब्लॉगों की तरह ही सुविधाओं को साझा करता है:टिप्पणियाँ, लेख और व्यवस्थापन डैशबोर्ड।

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

डेटाबेस-पंक्ति स्तर

यदि आप अपने एप्लिकेशन में एकाधिक डेटाबेस का उपयोग नहीं करना चाहते हैं, तो आप एक ऐसा दृष्टिकोण चुन सकते हैं जो एक केंद्रीय डेटाबेस पर संचालित हो। डेटाबेस में प्रत्येक तालिका में tenant_id . होता है दिए गए टैनेंट से संबंधित डेटा खींचने के लिए एप्लिकेशन के अंदर की गई प्रत्येक क्वेरी में उपयोग किया जाने वाला कॉलम।

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

स्कीमा स्तर

आपके पास अभी भी एक केंद्रीय डेटाबेस हो सकता है लेकिन प्रत्येक टैनेंट के लिए अलग टेबल और स्कीमा के साथ। डेटाबेस-पंक्ति स्तर दृष्टिकोण के विपरीत, आपको क्वेरी को संशोधित करने के बजाय टैनेंट के बीच स्विच करते समय खोज पथ को तालिकाओं में बदलना होगा। PostgreSQL में, आप सेट का उपयोग कर सकते हैं search_path कथन, और MySQL में use स्कीमा के बीच स्विच करने के लिए कथन।

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

डेटाबेस स्तर

यदि आप हर बार अपने आवेदन में एक नया टैनेंट जोड़ते समय एक नए डेटाबेस की लागत वहन कर सकते हैं, तो यह दृष्टिकोण आपके लिए सही हो सकता है। जब नए किरायेदारों को जोड़ने की बात आती है तो यह दृष्टिकोण सभी चर्चित आर्किटेक्चर से सबसे धीमा है।

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

एप्लिकेशन कंकाल बनाना

हम दो अलग-अलग एप्लिकेशन बनाएंगे:एक एक डेटाबेस द्वारा समर्थित मल्टी-टेनेंसी के साथ और एक मल्टी-टेनेंसी के साथ मल्टीपल डेटाबेस द्वारा समर्थित। वे कई किरायेदारों से निपटने के लिए एक अलग दृष्टिकोण का प्रतिनिधित्व करते हैं, लेकिन कॉन्फ़िगरेशन चरण समान है।

इस लेख को लिखते समय रूबी का नवीनतम संस्करण रूबी ऑन रेल्स रत्न का 2.7.2 और 6.1 आरसी1 है। सुनिश्चित करें कि आपके सिस्टम में रूबी का सही संस्करण स्थापित है और ढांचे के सही संस्करण को स्थापित करने का प्रयास करें:

gem install rails -v 6.1.0.rc1

अब हम निम्न कमांड के साथ प्रोजेक्ट फाइल जेनरेट कर सकते हैं:

rails _6.1.0.rc1_ new tenantapp -d=mysql

प्रोजेक्ट निर्देशिका दर्ज करें, सर्वर चलाएं, और जांचें कि क्या आप स्वागत स्क्रीन देख सकते हैं ताकि हम जारी रख सकें:

cd tenantapp/
rails s

एक डेटाबेस के साथ बहु-किरायेदार रेल अनुप्रयोग

कुछ कोड करने का समय आ गया है। लेख का यह भाग आपको दिखाएगा कि अपने रेल आवेदन में बहु-किरायेदारी कैसे लागू करें। मैं एक डेटाबेस और एक स्कीमा के साथ दृष्टिकोण का उपयोग करने जा रहा हूँ।

योजना इस प्रकार है:

  • हम रूबी और रूबी ऑन रेल्स फ्रेमवर्क के नवीनतम उपलब्ध संस्करण का उपयोग करके रेल एप्लिकेशन के लिए एक कंकाल तैयार करेंगे
  • हम कुछ मॉडलों को उस डेटा के लिए तैयार करेंगे जिस पर हम काम कर सकते हैं
  • पिछले चरण में हमारे द्वारा बनाई गई कार्यक्षमता के लिए, हम अपने एप्लिकेशन में डेटाबेस टेबल और कोड को अपडेट करके मल्टीटेनेंसी के लिए समर्थन जोड़ेंगे
  • अंतिम चरण कस्टम उप डोमेन के लिए समर्थन जोड़ना होगा ताकि उपयोगकर्ता अपने किरायेदारों तक आसानी से पहुंच सकें
  • हम कुछ सुविधाओं के लिए उपाय तलाशेंगे जिन्हें आप बाद में स्वयं लागू कर सकते हैं

परीक्षण डेटा तैयार करना

आइए मान लें कि हम एक ब्लॉग प्लेटफ़ॉर्म बना रहे हैं जहाँ उपयोगकर्ता कई लेखकों द्वारा प्रकाशित लेख देख सकते हैं।

मैं पहले लेखक मॉडल बनाऊंगा, जो लेखक के डेटा को संग्रहीत करेगा:

rails g scaffold author slug:string name:string description:string
rake db:create
rake db:migrate

अब आप https://localhost:3000/authors के पते पर जा सकते हैं और कुछ लेखकों को जोड़ सकते हैं ताकि हम बाद में उन्हें लेखों में असाइन कर सकें।

अगला कदम लेख बनाना है:

rails g scaffold article title:string content:text
rake db:migrate

मल्टीटेनेंसी सपोर्ट जोड़ना

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

डेटाबेस में उचित माइग्रेशन बनाएं

rails g migration AddTenantIdToArticle tenant_id:integer
rake db:migrate

उपरोक्त माइग्रेशन हमारे Article . में नया कॉलम जोड़ देगा नमूना। इस कॉलम का उपयोग किसी भी क्वेरी में केवल वर्तमान टैनेंट को असाइन किए गए डेटा तक पहुंच प्राप्त करने के लिए किया जाएगा।

किरायेदार को लेख सौंपें

इस चरण में, मैं कोड को अपडेट करने जा रहा हूं ताकि हम दिए गए लेखक को लेख में असाइन कर सकें और बाद में केवल चयनित लेखक के लिए लेख प्रस्तुत कर सकें। app/controllers/articles_controller.rb खोलें और निम्नलिखित परिवर्तन जोड़ें:

class ArticlesController < ApplicationController
 before_action :set_article, only: [:show, :edit, :update, :destroy]
 before_action :set_authors, only: [:edit, :update, :new, :create]
 
 # ...
 
 private
   # Only allow a list of trusted parameters through.
   def article_params
     params.require(:article).permit(:title, :content, :tenant_id)
   end
 
   def set_authors
     @authors = Author.all
   end
end

हमारे विचार में अब हम @authors . का उपयोग कर सकते हैं वेरिएबल जिसमें हमारे ऐप में जोड़े गए लेखकों का संग्रह है। अब हम उन चुनिंदा फ़ील्ड को जोड़ सकते हैं जिनमें लेखकों के नाम होंगे और एक उचित tenant_id assign असाइन कर सकते हैं . app/views/articles/_form.html.erb खोलें और निम्न अनुभाग जोड़ें:

<div className="field">
 <%= form.label :author %>
 <%= form.select :tenant_id, options_from_collection_for_select(@authors, 'id', 'name', article.tenant_id), include_blank: true %>
</div>

आगे बढ़ें और कुछ लेखक बनाएं और फिर कुछ लेख बाद में केवल दिए गए लेखक को सौंपे गए लेखों को प्रस्तुत करें।

कस्टम उप डोमेन के लिए समर्थन जोड़ना

हमने जॉन डो नाम से लेखक बनाया और स्लग मान को johndoe पर सेट किया . हमारा लक्ष्य https://johndoe.localhost:3000/ पते पर जाना है और इस मामले में केवल दिए गए किरायेदार, जॉन डो से संबंधित डेटा देखना है।

उपडोमेन कॉन्फ़िगरेशन

टेनेंट सेट होने पर हम लेखों को प्रबंधित करना और उन पर जाना चाहेंगे। हम config/routes.rb . को अपडेट करके इसे हासिल कर सकते हैं फ़ाइल और लेख संसाधन की परिभाषा को बाधा ब्लॉक में लपेटना:

Rails.application.routes.draw do
 constraints subdomain: /.*/ do
   resources :articles
 end
 
 resources :authors
end

डिफ़ॉल्ट रूप से, रेल ने शीर्ष-स्तरीय डोमेन लंबाई को 1 पर सेट किया है, लेकिन हम इस सेटिंग को 0 पर सेट करने के लिए लोकलहोस्ट का उपयोग करना चाहते हैं। हम फ़ाइल में निम्न पंक्ति जोड़कर ऐसा कर सकते हैं config/environments/development.rb :

config.action_dispatch.tld_length = 0

उप डोमेन को बहु-किरायेदारी के साथ काम करना

अब, किसी भी लेखक को लेख के लिए असाइन करना संभव है। उपडोमेन का उपयोग किए जाने पर यह संभव नहीं होना चाहिए। हमें ArticlesController . के व्यवहार को बदलना होगा , और सभी लेखकों को सेट करने के बजाय, हमें उस लेखक को सेट करना होगा जिसके लिए उप डोमेन का अनुरोध किया गया था:

 
class ArticlesController < ApplicationController
 before_action :set_author
 before_action :set_article, only: [:show, :edit, :update, :destroy]
 
 # GET /articles
 # GET /articles.json
 def index
   @articles = Article.where(tenant_id: @author.id)
 end
 
 # ...
 
 private
   def set_article
     @article = Article.find_by!(id: params[:id], tenant_id: @author.id)
   end
 
   # ...
 
   def set_author
     @author = Author.find_by!(slug: request.subdomain)
   end
end

मैंने नियंत्रक में कुछ बदलाव किए हैं:

  • set_authors के बजाय विधि, मैंने परिभाषित किया set_author विधि, जो लेखक को उपडोमेन के माध्यम से अनुरोधित सेट करती है। इस विधि को before_filter . में कॉल करना महत्वपूर्ण है set_article . से पहले कहा जाता है। इससे पहले कि हम लेख सेट करने का प्रयास करें, लेखक को सौंपा जाना चाहिए।
  • मैंने set_article को अपडेट किया है दी गई आईडी और असाइन किए गए लेखक के साथ लेख देखने की विधि। हम टॉम द्वारा बनाए गए लेखों को प्रस्तुत नहीं करना चाहते, जबकि हमारे वर्तमान किरायेदार जॉन हैं।
  • मैंने केवल हमारे वर्तमान टैनेंट को असाइन किए गए लेखों का चयन करने के लिए अनुक्रमणिका क्रिया को अपडेट किया है।

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

नियंत्रक अद्यतन किया गया है, इसलिए अगला चरण प्रपत्र दृश्य को अद्यतन करना है। app/views/articles/_form.html.erb खोलें फ़ाइल करें और पिछले अनुभाग को साधारण छिपे हुए फ़ील्ड से बदलें:

<%= form.hidden_field :tenant_id, value: @author.id %>

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

अब आप हमारे द्वारा बनाए गए कोड का परीक्षण कर सकते हैं। उदाहरण के लिए, जॉन डो और स्लग नाम के साथ एक नया लेखक बनाएँ johndoe . https://johndoe.localhost:3000/articles/new पता पर जाएं और एक नया लेख जोड़ें। एक नया लेख जोड़ने के बाद, आप इसे उस सूची में देख सकते हैं जो https://johndoe.localhost:3000/articles के अंतर्गत उपलब्ध है।

बधाई हो! आपने अभी-अभी एक बहु-किरायेदार ऐप बनाया है जहाँ प्रत्येक लेखक का अपना उप डोमेन होता है।

आगे सुधार

अब आप नई सुविधाओं को जोड़कर एप्लिकेशन के कोड को बढ़ा सकते हैं। हमारा ब्लॉग मंच सीधा है; शायद कुछ टिप्पणी अनुभाग जोड़ने का समय आ गया है? कोई फर्क नहीं पड़ता कि आप कौन सी कार्यक्षमता जोड़ते हैं, आपको tenant_id जोड़ना याद रखना चाहिए नए मॉडल के लिए कॉलम और संसाधन की क्वेरी करते समय इसका उपयोग करें।

आप एक विशेष दायरा बना सकते हैं और इसे चिंता में लपेट सकते हैं:

module Tenantable
 extend ActiveSupport::Concern
 
 included do
   scope :for_author, -> (author) { where(tenant_id: author.id) }
 end
end

और फिर इसका उपयोग हर उस मॉडल में करें जिसमें किरायेदारों के लिए डेटा शामिल है:

class Article < ApplicationRecord
 include Tenantable
end
 
author = Author.find(1)
Article.for_author(author)

उपरोक्त दृष्टिकोण के साथ, tenant_id का नाम बदलने की स्थिति में आपको केवल एक स्थान को अपडेट करना होगा जब टेनेंट से संबंधित डेटा को क्वेरी करने की बात आती है तो कॉलम या अधिक शर्तें पेश करना।

एकाधिक डेटाबेस के साथ बहु-किरायेदार रेल अनुप्रयोग

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

अच्छी खबर यह है कि रूबी ऑन रेल्स फ्रेमवर्क के नवीनतम संस्करण में कई डेटाबेस के प्रबंधन के लिए अंतर्निहित समर्थन है। मैं इसका पता लगाऊंगा और आपको दिखाऊंगा कि आप इसका उपयोग कई डेटाबेस और कस्टम उप डोमेन के साथ एक बहु-किरायेदार रेल एप्लिकेशन बनाने के लिए कैसे कर सकते हैं।

योजना इस प्रकार है:

  • हम रूबी और रूबी ऑन रेल्स फ्रेमवर्क के नवीनतम उपलब्ध संस्करण का उपयोग करके रेल एप्लिकेशन के लिए एक कंकाल तैयार करेंगे
  • हम कुछ मॉडलों को उस डेटा के लिए तैयार करेंगे जिस पर हम काम कर सकते हैं
  • हम कस्टम उप डोमेन के लिए समर्थन जोड़ेंगे।
  • हम सीखेंगे कि नए डेटाबेस बनाकर और कॉन्फ़िगर करके नए किरायेदारों को कैसे जोड़ा जाए।
  • अंतिम चरण यह होगा कि दिए गए सबडोमेन का अनुरोध किए जाने पर डेटाबेस को स्विच करने के लिए एप्लिकेशन को अपडेट किया जाए।

परीक्षण डेटा तैयार करना

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

Author creating बनाने के साथ प्रारंभ करें मचान सुविधाओं के साथ मॉडल जो हमें नए लेखकों को देखने और बनाने में मदद करेगा:

rails g scaffold author slug:string name:string description:string
rake db:create
rake db:migrate

अब आप https://localhost:3000/authors पर जा सकते हैं और देख सकते हैं कि रेल ने हमारे लिए क्या बनाया है।

नया लेखक जोड़ना

मैंने जॉन डो और स्लग नाम के साथ एक नया लेखक बनाया johndoe . स्लग मान का उपयोग बाद में यह पता लगाने के लिए किया जाएगा कि हमें उपडोमेन का उपयोग करके किस लेखक को जानकारी प्रदर्शित करनी चाहिए।

क्योंकि प्रत्येक लेखक के पास एक अलग डेटाबेस होगा, हमें जॉन के लिए मैन्युअल रूप से नया डेटाबेस जोड़ना होगा। config/database.yml खोलें और निम्नलिखित परिवर्तन जोड़ें:

development:
 primary:
   <<: *default
   database: tenantapp_development
 primary_johndoe:
   <<: *default
   database: tenantapp_johndoe_development
   migrations_paths: db/tenants_migrations

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

rake db:create

लेख जोड़ना

अब हम Article . को मचान बना सकते हैं नियंत्रक और विचारों के साथ मॉडल:

rails g scaffold article title:string content:text --database primary_johndoe

मैंने --database . पास किया है परम रेल को यह बताने के लिए कि माइग्रेशन को डिफ़ॉल्ट db/migrations में नहीं रखा जाना चाहिए प्राथमिक डेटाबेस द्वारा उपयोग की जाने वाली निर्देशिका। अब हम माइग्रेट कमांड चला सकते हैं:

rake db:migrate

अभी, हमारे पास दो स्कीमा हैं:db/schema.rb और db/primary_johndoe_schema.rb . यदि आप किरायेदारों के लिए अलग-अलग टेबल बनाना चाहते हैं, तो आप एक अद्वितीय migrations_path सेट करके इसे प्राप्त कर सकते हैं। config/database.yml में मान दिए गए किरायेदार के लिए फ़ाइल। इस लेख में, हम चाहते हैं कि सभी टैनेंट के लिए समान टेबल हों, इसलिए माइग्रेशन का रास्ता एक जैसा होगा।

बहु-किरायेदारी सहायता जोड़ना

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

रेल्स 6.1 हॉरिजॉन्टल शार्डिंग के लिए बिल्ट-इन सपोर्ट के साथ आता है। Shard एक क्षैतिज डेटा विभाजन है जिसमें कुल डेटासेट का सबसेट होता है। हम एक डेटाबेस में सभी लेखकों के लिए लेखों को एक तालिका में संग्रहीत कर सकते हैं, लेकिन शार्डिंग के लिए धन्यवाद, हम डेटा को एक ही संरचना के साथ कई तालिकाओं में विभाजित कर सकते हैं लेकिन अलग डेटाबेस में रखा जा सकता है।

आइए सभी मॉडलों के लिए मूल वर्ग में हमारे शार्क को परिभाषित करें। वे app/models/application_record.rb . के अंतर्गत संग्रहीत हैं :

ActiveRecord::Base.connected_to(role: :reading, shard: :johndoe) do
  Article.all # get all articles created by John
end

हमारे कॉल को connected_to . में लपेटे बिना ब्लॉक, डिफ़ॉल्ट शार्ड का उपयोग किया जाएगा। इससे पहले कि हम आगे बढ़ें, हमें एक और बदलाव लाना होगा। चूंकि सभी शार्क समान डेटा संरचना साझा करते हैं, इसलिए हम app/models/primary_johndoe_record.rb को हटा सकते हैं मॉडल स्वचालित रूप से बनाया गया था जब हम लेखों को मचान कर रहे थे।

हमें app/models/article.rb . को भी संपादित करना होगा मॉडल और मूल वर्ग को PrimaryJohndoeRecord . से बदलें करने के लिए ApplicationRecord :

class Article < ApplicationRecord
end

अधिक किरायेदारों को जोड़ना

वर्तमान में, हमारे डेटाबेस में केवल एक लेखक है। हमारे किरायेदारों (डेटाबेस) के बीच स्विच करने की कार्यक्षमता का परीक्षण करने के लिए, हमें एक और लेखक जोड़ना होगा। https://localhost:3000/authors/new पता खोलें और एक नया लेखक जोड़ें। मैंने लेखक को टिम डो और स्लग नाम के साथ जोड़ा timdoe

हमारे पास नए लेखक के लिए एक रिकॉर्ड है, इसलिए हमें एक नया डेटाबेस परिभाषित करना होगा:

development:
 primary:
   <<: *default
   database: tenantapp_development
 primary_johndoe:
   <<: *default
   database: tenantapp_johndoe_development
   migrations_paths: db/tenants_migrations
 primary_timdoe:
   <<: *default
   database: tenantapp_timdoe_development
   migrations_paths: db/tenants_migrations

अब एक नया डेटाबेस बनाएं और माइग्रेशन चलाएं:

rake db:create
rake db:migrate

अंतिम चरण ApplicationRecord को अपडेट करना है मॉडल बनाएं और एक नया शार्ड परिभाषित करें:

class ApplicationRecord < ActiveRecord::Base
 self.abstract_class = true
 
 connects_to shards: {
   default: { writing: :primary, reading: :primary },
   johndoe: { writing: :primary_johndoe, reading: :primary_johndoe },
   timdoe: { writing: :primary_timdoe, reading: :primary_timdoe },
 }
end

अब आप प्रत्येक लेखक के लिए लेख बना सकते हैं:

ActiveRecord::Base.connected_to(role: :writing, shard: :johndoe) do
  Article.create!(title: 'Article from John', content: 'content')
end
 
ActiveRecord::Base.connected_to(role: :writing, shard: :timdoe) do
  Article.create!(title: 'Article from Tim', content: 'content')
end

कस्टम उप डोमेन के लिए समर्थन जोड़ना

हम अभी तक दिए गए लेखक के लिए लेखों की सूची पर नहीं जा सकते क्योंकि हमें नहीं पता कि हमें जॉन और टिम के लेख कब दिखाने चाहिए। हम कस्टम सबडोमेन लागू करके इस समस्या का समाधान करेंगे। https://johndoe.localhost:3000/articles पर जाने के दौरान, हमें जॉन के लेख देखने चाहिए, और टिम के https://timedoe.localhost:3000/लेखों पर जाने पर।

उपडोमेन कॉन्फ़िगरेशन

टेनेंट सेट होने पर हम लेखों को प्रबंधित करना और उन पर जाना चाहेंगे। हम config/routes.rb . को अपडेट करके इसे हासिल कर सकते हैं फ़ाइल और लेख संसाधन की परिभाषा को बाधा ब्लॉक में लपेटना:

Rails.application.routes.draw do
 constraints subdomain: /.*/ do
   resources :articles
 end
 
 resources :authors
end

डिफ़ॉल्ट रूप से, रेल ने शीर्ष-स्तरीय डोमेन लंबाई को 1 पर सेट किया है, लेकिन हम इस सेटिंग को 0 पर सेट करने के लिए लोकलहोस्ट का उपयोग करना चाहते हैं। हम फ़ाइल में निम्न पंक्ति जोड़कर ऐसा कर सकते हैं config/environments/development.rb :

config.action_dispatch.tld_length = 0

उप डोमेन को बहु-किरायेदारी के साथ काम करना

वर्तमान टैनेंट के लिए डेटाबेस को पढ़ने का मानकीकरण करने के लिए, मैं Tenantable . नामक एक नियंत्रक चिंता बनाऊंगा . यह read_with_tenant . प्रदान करता है विधि, जो एक ब्लॉक को स्वीकार करती है और अनुरोधित किरायेदार के संदर्भ में इसे निष्पादित करती है:

module Tenantable
 extend ActiveSupport::Concern
 
 private
 
 def read_with_tenant(&block)
   author = Author.find_by!(slug: request.subdomain)
 
   ActiveRecord::Base.connected_to(role: :reading, shard: author.slug.to_sym) do
     block.call
   end
 end
end

इस फ़ाइल को app/controllers/concerns/tenantable.rb . के रूप में सहेजें और ArticlesController . में शामिल करें :

class ArticlesController < ApplicationController
 include Tenantable
 
 before_action :set_article, only: [:show, :edit, :update, :destroy]
 
 def index
   read_with_tenant do
     @articles = Article.all
   end
 end
 # ...
end

अब आप https://johndoe.localhost:3000/articles या https://timdoe.localhost:3000/articles पर जा सकते हैं, और आप सूची में प्रदर्शित विभिन्न लेख देखेंगे।

यदि आप फ़ॉर्म का उपयोग करके नए लेख बनाना चाहते हैं, तो आपको write_with_tenant नामक एक नई विधि को परिभाषित करना होगा और ArticlesController . के अंदर Tenantable चिंता और विधियों को अपडेट करें तदनुसार।

आगे सुधार

ऊपर प्रस्तुत दृष्टिकोण सिर्फ एक साधारण आवरण विधि है जो डेटाबेस से दिए गए कनेक्शन के भीतर एक ब्लॉक में लिपटे कोड को निष्पादित करता है। इसे और अधिक सार्वभौमिक बनाने के लिए, आप एक मिडलवेयर बना सकते हैं जो उपडोमेन को पार्स करेगा और किसी भी कोड को निष्पादित करने से पहले एक कनेक्शन स्थापित करेगा:

ActiveRecord::Base.establish_connection(:primary_timdoe)

अंतिम समाधान आपकी आवश्यकताओं और उन स्थानों की संख्या पर निर्भर करता है जहां आप किसी विशिष्ट टैनेंट को असाइन किए गए डेटा का उपयोग करना चाहते हैं।

सारांश

बधाई हो, आपने अभी-अभी एक बहु-किरायेदार रेल एप्लिकेशन के दो संस्करण बनाए हैं और एक आधुनिक वेब एप्लिकेशन में एकाधिक टैनेंट से निपटने के विभिन्न तरीकों के बारे में ज्ञान प्राप्त किया है।

आइए संक्षेप में संक्षेप में बताएं कि हमने इस लेख के दौरान क्या सीखा:

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

मुझे आशा है कि आपको यह लेख पढ़ने और रेल अनुप्रयोगों पर बहु-किरायेदार रूबी बनाने में मज़ा आया होगा।

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


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

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

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

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

  1. रूबी के साथ कमांड-लाइन एप्लिकेशन (सीएलआई) कैसे बनाएं?

    बहुत से लोग भूल जाते हैं कि रूबी ऐसे काम कर सकती है जो वेब एप्लिकेशन नहीं हैं। इस लेख में, मैं आपको दिखाना चाहता हूं कि इसका समाधान करने में मदद के लिए एक कमांड-लाइन एप्लिकेशन कैसे बनाया जाए! यहां कुछ कमांड-लाइन एप्लिकेशन दिए गए हैं जिनसे आप परिचित हो सकते हैं: psql rails bundler gem git कम