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

Rails ऐप्स को बूस्ट करें: Elasticsearch के साथ फुल-टेक्स्ट खोज में महारत हासिल करें

Elasticsearch वहां सबसे लोकप्रिय सर्च इंजन में से एक है। कई बड़ी कंपनियों में जो इसे पसंद करती हैं और सक्रिय रूप से अपने प्रोडक्शन में इसका उपयोग करती हैं, Netflix, Medium, GitHub जैसे दिग्गज हैं।

Elasticsearch बहुत शक्तिशाली है, मुख्य उपयोग के मामलों में फुल-टेक्स्ट खोज, रीयल-टाइम लॉग, और सुरक्षा विश्लेषण शामिल हैं।

दुर्भाग्य से, Elasticsearch को Rails समुदाय से ज्यादा ध्यान नहीं मिलता है, इसलिए यह लेख दो लक्ष्यों को ध्यान में रखकर इसे बदलने का प्रयास करता है: पाठक को Elasticsearch अवधारणाओं से परिचित कराना और दिखाना कि इसे Ruby on Rails के साथ कैसे उपयोग करें।

आप एक उदाहरण प्रोजेक्ट का सोर्स कोड यहां पा सकते हैं जिसे हम बनाने जा रहे हैं। कमिट इतिहास इस लेख में खंडों के क्रम के कमोबेश मेल खाता है।

परिचय

व्यापक दृष्टिकोण से, Elasticsearch एक सर्च इंजन है जो

  • Apache Lucene के शीर्ष पर बनाया गया है;
  • JSON दस्तावेजों को प्रभावी ढंग से संग्रहीत और अनुक्रमित करता है;
  • ओपन-सोर्स है;
  • इसके साथ इंटरैक्ट करने के लिए REST APIs का एक सेट प्रदान करता है;
  • डिफ़ॉल्ट रूप से कोई सुरक्षा नहीं है (कोई भी सार्वजनिक एंडपॉइंट के माध्यम से इसे क्वेरी कर सकता है);
  • क्षैतिज रूप से काफी अच्छी तरह से स्केल करता है।

आइए कुछ बुनियादी अवधारणाओं पर एक त्वरित नज़र डालें।

Elasticsearch के साथ, हम दस्तावेजों को इंडेक्स में डालते हैं, जिन्हें तब डेटा के लिए क्वेरी किया जाता है।

एक इंडेक्स एक रिलेशनल डेटाबेस में एक टेबल के समान है; यह एक स्टोर है जहां हम दस्तावेज़ (पंक्तियाँ) डालते हैं जिन्हें बाद में क्वेरी किया जा सकता है।

एक दस्तावेज़ फील्ड्स का एक संग्रह है (एक रिलेशनल डेटाबेस में एक पंक्ति के समान)।

एक मैपिंग एक रिलेशनल डेटाबेस में स्कीमा परिभाषा की तरह है। मैपिंग को स्पष्ट रूप से परिभाषित किया जा सकता है या इंसर्ट समय पर Elasticsearch द्वारा अनुमानित किया जा सकता है; इंडेक्स मैपिंग को पहले से परिभाषित करना हमेशा बेहतर होता है।

इसे कवर करने के साथ, आइए अब अपना एनवायरनमेंट सेट अप करें।

Elasticsearch इंस्टॉल करना

macOS पर Elasticsearch इंस्टॉल करने का सबसे आसान तरीका brew का उपयोग करना है:

brew tap elastic/tap
brew install elastic/tap/elasticsearch-full

एक विकल्प के रूप में, हम इसे docker के माध्यम से चला सकते हैं:

docker run \
-p 127.0.0.1:9200:9200 \
-p 127.0.0.1:9300:9300 \
-e "discovery.type=single-node" \
docker.elastic.co/elasticsearch/elasticsearch:7.16.2

अन्य विकल्पों के लिए, कृपया आधिकारिक संदर्भ देखें।

Elasticsearch डिफ़ॉल्ट रूप से पोर्ट 9200 पर अनुरोध स्वीकार करता है। आप एक सरल curl अनुरोध (या ब्राउज़र में खोलें) के साथ जांच सकते हैं कि यह चल रहा है:

curl https://localhost:9200

APIs

Elasticsearch हर संभावित प्रकार के कार्य के लिए इंटरैक्ट करने के लिए REST APIs का एक सेट प्रदान करता है। उदाहरण के लिए, मान लीजिए हम एक दस्तावेज़ बनाने के लिए JSON कंटेंट टाइप के साथ एक POST अनुरोध चलाते हैं:

curl -X POST https://localhost:9200/my-index/_doc \
-H 'Content-Type: application/json' \
-d '{"title": "Banana Cake"}'

इस मामले में, my-index एक इंडेक्स का नाम है (यदि मौजूद नहीं है, तो यह ऑटोमैटिकली बन जाता है)।

_doc एक सिस्टम रूट है (सभी सिस्टम रूट अंडरस्कोर से शुरू होते हैं)।

APIs के साथ इंटरैक्ट करने के कई तरीके हैं।

  1. कमांड-लाइन से curl का उपयोग करना (आप jq को उपयोगी पा सकते हैं)।
  2. ब्राउज़र से GET क्वेरी चलाना JSON प्रिटी प्रिंटिंग के लिए किसी एक्सटेंशन का उपयोग करके।
  3. Kibana इंस्टॉल करना और Dev Tools कंसोल का उपयोग करना, जो मेरा पसंदीदा तरीका है।
  4. अंत में कुछ बेहतरीन Chrome एक्सटेंशन भी हैं।

इस लेख के लिए, इससे कोई फर्क नहीं पड़ता कि आप कौन सा चुनते हैं—हम वैसे भी APIs के साथ सीधे इंटरैक्ट नहीं करने जा रहे हैं। इसके बजाय, हम एक जेम का उपयोग करेंगे, जो हुड के तहत REST API से बात करता है।

एक नया ऐप शुरू करना

विचार 26K+ गानों के सार्वजनिक डेटासेट का उपयोग करके एक गीत गीत एप्लिकेशन बनाने का है। प्रत्येक गीत में शीर्षक, कलाकार, शैली, और टेक्स्ट गीत फील्ड्स हैं। हम फुल-टेक्स्ट खोज के लिए Elasticsearch का उपयोग करेंगे।

आइए एक सरल Rails एप्लिकेशन बनाकर शुरू करें:

rails new songs_api --api -d postgresql

चूंकि हम इसे केवल API के रूप में उपयोग करेंगे, हम उपयोग किए जाने वाले मिडलवेयर के सेट को सीमित करने के लिए --api फ्लैग प्रदान करते हैं।

आइए अपने ऐप को स्कैफोल्ड करें:

bin/rails generate scaffold Song title:string artist:string genre:string lyrics:text

अब, माइग्रेशन चलाएं और सर्वर शुरू करें:

bin/rails db:create db:migrate
bin/rails server

उसके बाद, हम सत्यापित करते हैं कि GET एंडपॉइंट काम करता है:

curl https://localhost:3000/songs

यह एक खाली सरणी लौटाता है, जो कोई आश्चर्य नहीं है क्योंकि अभी तक कोई डेटा नहीं है।

Elasticsearch का परिचय

आइए मिश्रण में Elasticsearch जोड़ें। ऐसा करने के लिए, हमें elasticsearch-model जेम की आवश्यकता होगी। यह एक आधिकारिक Elasticsearch जेम है जो Rails मॉडल के साथ अच्छी तरह से एकीकृत होता है।

अपने Gemfile में निम्नलिखित जोड़ें:

gem 'elasticsearch-model'

डिफ़ॉल्ट रूप से, यह localhost पर पोर्ट 9200 से जुड़ेगा, जो हमें पूरी तरह से सूट करता है, लेकिन यदि आप इसे बदलना चाहते हैं, तो आप क्लाइंट को इनिशियलाइज़ करके कर सकते हैं

Song.__elasticsearch__.client = Elasticsearch::Client.new host: 'myserver.com', port: 9876

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

Elastisearch-संबंधित कोड को एक अलग मॉड्यूल में रखना हमेशा एक अच्छा विचार है, तो आइए app/models/concerns/searchable.rb पर एक कंसर्न बनाएं और जोड़ें

# app/models/concerns/searchable.rb
module Searchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
mapping do
# मैपिंग परिभाषा यहां जाती है
end
def self.search(query)
# खोज अनुरोध बनाएं और चलाएं
end
end
end

भले ही यह सिर्फ एक कंकाल है, यहां अनपैक करने के लिए कुछ है।

पहली और सबसे महत्वपूर्ण बात Elasticsearch::Model है, जो ES के साथ इंटरैक्ट करने के लिए कुछ कार्यक्षमता जोड़ता है। Elasticsearch::Model::Callbacks मॉड्यूल यह सुनिश्चित करता है कि जब हम एक रिकॉर्ड अपडेट करते हैं, तो यह Elasticsearch में डेटा को ऑटोमैटिकली अपडेट करता है। mapping ब्लॉक वह जगह है जहां हम Elasticsearch इंडेक्स मैपिंग डालते हैं, जो परिभाषित करता है कि कौन से फील्ड Elasticsearch में संग्रहीत किए जाने वाले हैं और उनका प्रकार क्या होना चाहिए। अंत में, एक search मेथड है जिसका उपयोग हम वास्तव में गीत के बोल के लिए Elasticsearch को खोजने के लिए करेंगे। हम जिस जेम का उपयोग कर रहे हैं वह एक search मेथड प्रदान करता है जिसे Song.search("genesis") जैसे सरल क्वेरी के साथ उपयोग किया जा सकता है, लेकिन हम क्वेरी DSL का उपयोग करके निर्मित एक अधिक जटिल खोज क्वेरी के साथ इसका उपयोग करेंगे (इस पर बाद में)।

कंसर्न को अपने मॉडल क्लास में शामिल करना न भूलें:

# /app/models/song.rb
class Song < ApplicationRecord
include Searchable
end

मैपिंग्स

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

मैपिंग को REST एंडपॉइंट के माध्यम से PUT /my-index/_mapping का उपयोग करके अपडेट किया जा सकता है और GET /my-index/_mapping के माध्यम से पढ़ा जा सकता है, लेकिन elasticsearch जेम हमारे लिए इसे सारांशित करता है, इसलिए हमें केवल mapping ब्लॉक प्रदान करने की आवश्यकता है:

# app/models/concerns/searchable.rb
mapping do
indexes :artist, type: :text
indexes :title, type: :text
indexes :lyrics, type: :text
indexes :genre, type: :keyword
end

हम artist, title, और lyrics फील्ड्स को टेक्स्ट टाइप का उपयोग करके इंडेक्स करने जा रहे हैं। यह एकमात्र प्रकार है जिसे फुल-टेक्स्ट खोज के लिए अनुक्रमित किया जाता है। genre के लिए, हम कीवर्ड टाइप का उपयोग करेंगे, जो एक सटीक मूल्य द्वारा फ़िल्टर की गई खोज के लिए आदर्श है।

अब bin/rails console के साथ रेल्स कंसोल चलाएं और फिर चलाएं

Song.__elasticsearch__.create_index!

यह Elasticsearch में हमारा इंडेक्स बनाएगा। __elasticsearch__ ऑब्जेक्ट Elasticsearch दुनिया का हमारा प्रवेश द्वार है, जो Elasticsearch के साथ इंटरैक्ट करने के लिए कई उपयोगी मेथड से भरा हुआ है।

डेटा आयात करना

हर बार जब हम एक रिकॉर्ड बनाते हैं, तो यह ऑटोमैटिकली डेटा को Elasticsearch में भेज देगा। तो, हम गीत के बोल के साथ एक डेटासेट डाउनलोड करने जा रहे हैं और इसे अपने ऐप में आयात करेंगे। पहले, इसे इस लिंक से डाउनलोड करें (Creative Commons Attribution 4.0 International license के तहत एक डेटासेट)। इस CSV फाइल में 26,000 से अधिक रिकॉर्ड हैं, जिन्हें हम नीचे दिए गए कोड के साथ अपने डेटाबेस और Elasticsearch में आयात करेंगे:

require 'csv'
class Song < ApplicationRecord
include Searchable
def self.import_csv!
filepath = "/path/to/your/file/tcc_ceds_music.csv"
res = CSV.parse(File.read(filepath), headers: true)
res.each_with_index do |s, ind|
Song.create!(
artist: s["artist_name"],
title: s["track_name"],
genre: s["genre"],
lyrics: s["lyrics"]
)
end
end
end

रेल्स कंसोल खोलें और Song.import_csv! चलाएं (इसमें कुछ समय लगेगा)। वैकल्पिक रूप से, हम अपने डेटा को बल्क में आयात कर सकते हैं, जो बहुत तेज है, लेकिन इस मामले में, हम यह सुनिश्चित करना चाहते हैं कि हम अपने PostgreSQL डेटाबेस और Elasticsearch में रिकॉर्ड बनाएं।

जब आयात समाप्त हो जाता है, तो हमारे पास अब खोजने के लिए बहुत सारे बोल हैं।

डेटा खोजना

elasticsearch-model जेम एक search मेथड जोड़ता है जो हमें सभी अनुक्रमित फील्ड्स में खोज करने की अनुमति देता है। आइए इसे अपने searchable कंसर्न में उपयोग करें:

# app/models/concerns/searchable.rb
# ...
def self.search(query)
self.__elasticsearch__.search(query)
end
# ...

रेल्स कंसोल खोलें और res = Song.search('genesis') चलाएं। प्रतिक्रिया ऑब्जेक्ट में बहुत सारी मेटा जानकारी होती है: अनुरोध में कितना समय लगा, किन नोड्स का उपयोग किया गया, आदि। हम res.response["hits"]["hits"] पर हिट्स में रुचि रखते हैं।

आइए अपने कंट्रोलर के index मेथड को ES के बजाय क्वेरी करने के लिए बदलें।

# app/controllers/songs_controller.rb
def index
query = params["query"] || ""
res = Song.search(query)
render json: res.response["hits"]["hits"]
end

अब हम इसे ब्राउज़र में लोड करने या curl https://localhost:3000/songs?query=genesis का उपयोग करके आज़मा सकते हैं। प्रतिक्रिया इस तरह दिखेगी:

[
{
"_index": "songs",
"_type": "_doc",
"_id": "22676",
"_score": 12.540506,
"_source": {
"id": 22676,
"title": "genesis",
"artist": "grimes",
"genre": "pop",
"lyrics": "heart know heart ...",
"created_at": "...",
"updated_at": "..."
}
},
...
]

जैसा कि आप देख सकते हैं, वास्तविक डेटा _source कुंजी के तहत लौटाया जाता है, अन्य फील्ड्स मेटाडेटा हैं, जिनमें से सबसे महत्वपूर्ण _score है जो दिखाता है कि दस्तावेज़ विशेष खोज के लिए कितना प्रासंगिक है। हम जल्द ही इस पर पहुंचेंगे, लेकिन पहले आइए सीखें कि क्वेरी कैसे बनाएं।

क्वेरी DSL

Elasticsearch क्वेरी DSL जटिल क्वेरी बनाने का एक तरीका प्रदान करता है, और हम इसे Ruby कोड से भी उपयोग कर सकते हैं। उदाहरण के लिए, आइए search मेथड को केवल artist फील्ड में खोजने के लिए संशोधित करें:

# app/models/concerns/searchable.rb
module Searchable
extend ActiveSupport::Concern
included do
# ...
def self.search(query)
params = {
query: {
match: {
artist: query,
},
},
}
self.__elasticsearch__.search(params)
end
end
end

क्वेरी-मैच निर्माण हमें केवल एक विशेष फील्ड (इस मामले में, artist) में खोज करने की अनुमति देता है। अब, यदि हम गानों को फिर से "genesis" के साथ क्वेरी करते हैं (इसे https://localhost:3000/songs?query=genesis लोड करके आज़माएं), तो हमें केवल बैंड "Genesis" के गाने मिलेंगे, न कि उनके शीर्षक में "genesis" वाले गाने। यदि हम कई फील्ड्स में क्वेरी करना चाहते हैं, जो अक्सर होता है, तो हम मल्टी-मैच क्वेरी का उपयोग कर सकते हैं:

# app/models/concerns/searchable.rb
def self.search(query)
params = {
query: {
multi_match: {
query: query,
fields: [ :title, :artist, :lyrics ]
},
},
}
self.__elasticsearch__.search(params)
end

फ़िल्टरिंग

क्या होगा यदि हम केवल, कहते हैं, रॉक गानों में खोज करना चाहते हैं? फिर, हमें शैली द्वारा फ़िल्टर करने की आवश्यकता है! यह हमारी खोज को थोड़ा अधिक जटिल बनाने जा रहा है, लेकिन चिंता न करें—हम सब कुछ चरण दर चरण समझाएंगे!

def self.search(query, genre = nil)
params = {
query: {
bool: {
must: [
{
multi_match: {
query: query,
fields: [ :title, :artist, :lyrics ]
}
},
],
filter: [
{
term: {
genre: genre
}
}
]
}
}
}
self.__elasticsearch__.search(params)
end

पहला नया कीवर्ड bool है, जो कई क्वेरी को एक में जोड़ने का एक तरीका है। हमारे मामले में, हम must और filter को जोड़ रहे हैं। पहला (must) स्कोर में योगदान देता है और इसमें वही क्वेरी होती है जिसे हमने पहले ही उपयोग किया है। दूसरा (filter) स्कोर में योगदान नहीं देता, यह सिर्फ वही करता है जो यह कहता है: उन दस्तावेजों को फ़िल्टर करता है जो क्वेरी से मेल नहीं खाते। हम अपने रिकॉर्ड को शैली द्वारा फ़िल्टर करना चाहते हैं, इसलिए हम टर्म क्वेरी का उपयोग करते हैं।

यह ध्यान रखना महत्वपूर्ण है कि filter-term संयोजन का फुल-टेक्स्ट खोज से कोई लेना-देना नहीं है। यह सिर्फ सटीक मूल्य द्वारा एक नियमित फ़िल्टर है, उसी तरह जैसे SQL में WHERE क्लॉज काम करता है (WHERE genre = 'rock')। term फ़िल्टरिंग का उपयोग करना जानना अच्छा है, लेकिन हमें यहां इसकी आवश्यकता नहीं होगी।

स्कोरिंग

खोज परिणाम _score द्वारा क्रमबद्ध होते हैं जो दिखाता है कि कोई आइटम विशेष खोज के लिए कितना प्रासंगिक है। स्कोर जितना अधिक होगा, दस्तावेज़ उतना ही अधिक प्रासंगिक होगा। आपने शायद देखा होगा कि जब हमने शब्द genesis खोजा, तो पहला परिणाम जो सामने आया वह Grimes का गाना था, जबकि मैं वास्तव में Genesis बैंड में अधिक रुचि रखता था। तो, क्या हम स्कोरिंग तंत्र को बदल सकते हैं ताकि artist फील्ड पर अधिक ध्यान दिया जाए? हां हम कर सकते हैं, लेकिन ऐसा करने के लिए, हमें पहले अपनी क्वेरी को 조정 करने की आवश्यकता है:

def self.search(query)
params = {
query: {
bool: {
should: [
{ match: { title: query }},
{ match: { artist: { query: query, boost: 5 } }},
{ match: { lyrics: query }},
],
}
},
}
self.__elasticsearch__.search(params)
end

यह क्वेरी अनिवार्य रूप से पूर्ववर्ती के बराबर है सिवाय इसके कि यह bool कीवर्ड का उपयोग कर रहा है, जो कई क्वेरी को एक में जोड़ने का एक तरीका है। हम should का उपयोग करते हैं, जिसमें तीन क्वेरी अलग-अलग होती हैं (प्रति फील्ड एक): वे अनिवार्य रूप से तार्किक OR का उपयोग करके संयुक्त होते हैं। यदि हम must का उपयोग करते, तो वे तार्किक AND का उपयोग करके संयुक्त होते। हमें प्रति फील्ड एक अलग मैच की आवश्यकता क्यों है? ऐसा इसलिए है क्योंकि अब हम बूस्ट प्रॉपर्टी निर्दिष्ट कर सकते हैं, जो एक गुणांक है जो विशेष क्वेरी से स्कोर को गुणा करता है:

def self.search(query)
params = {
query: {
bool: {
should: [
{ match: { title: query }},
{ match: { artist: { query: query, boost: 5 } }},
{ match: { lyrics: query }},
],
}
},
}
self.__elasticsearch__.search(params)
end

अन्य सभी चीजें समान होने पर, यदि क्वेरी artist से मेल खाती है तो हमारा स्कोर पांच गुना अधिक होगा। https://localhost:3000/songs?query=genesis के साथ genesis क्वेरी को फिर से आज़माएं, और आप Genesis बैंड के गानों को पहले आते हुए देखेंगे। मीठा!

हाइलाइटिंग

Elasticsearch की एक और उपयोगी विशेषता दस्तावेज़ के भीतर मैच को हाइलाइट करने में सक्षम होना है, जो उपयोगकर्ता को बेहतर ढंग से समझने की अनुमति देता है कि कोई विशेष परिणाम खोज में क्यों दिखाई दिया।

HTML में, इसके लिए एक विशेष HTML टैग है, और Elasticsearch स्वचालित रूप से उसे जोड़ सकता है।

आइए searchable.rb कंसर्न को फिर से खोलें और एक नया कीवर्ड जोड़ें:

def self.search(query)
params = {
query: {
bool: {
should: [
{ match: { title: query }},
{ match: { artist: { query: query, boost: 5 } }},
{ match: { lyrics: query }},
],
}
},
highlight: {
fields: {
title: {},
artist: {},
lyrics: {}
}
}
}
self.__elasticsearch__.search(params)
end

नया highlight फील्ड निर्दिष्ट करता है कि किन फील्ड्स को हाइलाइट किया जाना चाहिए। हम उन सभी का चयन करते हैं। अब, यदि हम https://localhost:3000/query=genesis लोड करते हैं, तो हमें "हाइलाइट" नामक एक नया फील्ड देखना चाहिए जिसमें मिलान वाले वाक्यांश em टैग में लिपटे हुए दस्तावेज़ फील्ड्स हों।

हाइलाइटिंग पर अधिक के लिए, कृपया आधिकारिक गाइड देखें।

फज़ीनेस

ठीक है, क्या होगा यदि हम गलती से genesis के बजाय benesis लिखते हैं? यह कोई परिणाम नहीं लौटाएगा, लेकिन हम Elasticsearch को कम चुनिंदा होने और फज़ी खोज की अनुमति देने के लिए कह सकते हैं, इसलिए यह genesis परिणाम भी प्रदर्शित करेगा।

यहां बताया गया है कि यह कैसे किया जाता है। बस artist क्वेरी को { match: { artist: { query: query, boost: 5 } }} से { match: { artist: { query: query, boost: 5, fuzziness: "AUTO" } }} में बदलें। सटीक फज़ीनेस मैकेनिक्स को कॉन्फ़िगर किया जा सकता है। अधिक विवरण के लिए कृपया आधिकारिक डॉक्स देखें।

आगे कहां जाएं?

मुझे आशा है कि इस लेख ने आपको आश्वस्त किया है कि Elasticsearch एक शक्तिशाली टूल है जिसका उपयोग किया जा सकता है और किया जाना चाहिए जब आपको एक गैर-तुच्छ खोज लागू करने की आवश्यकता हो। यदि आप अधिक सीखने के लिए तैयार हैं, तो यहां कुछ उपयोगी लिंक हैं:

संसाधन

  • आधिकारिक Elasticsearch संदर्भ
  • Ruby जेम
  • Rails जेम
  • व्यावहारिक ज्ञान से भरी एक बहुत अच्छी किताब
  • ऑटोकंप्लीट बनाना

वैकल्पिक जेम्स

  • Searchkick
  • Chewy
  1. Hotwire के साथ Rails ऐप्स को तेज़ करें: JavaScript के बिना सर्वर-साइड रेंडरिंग Hotwire के साथ Rails ऐप्स को तेज़ करें: JavaScript के बिना सर्वर-साइड रेंडरिंग

    यदि आप पेज परिवर्तनों और फॉर्म सबमिशन को तेज़ करने और जटिल पेज को बिना कोई JavaScript कोड लिखे घटकों में विभाजित करने का तरीका ढूंढ रहे हैं, तो यह पोस्ट आपको Hotwire के साथ Rails को अगले स्तर पर ले जाने में मदद करेगी। यह लेख आपको सर्वर-साइड रेंडरिंग के लिए एक टूल का उपयोग करना सिखाएगा। Hotwire क्या

  1. रूबी ऑन रेल्स में टेलविंड CSS जोड़ें: एक व्यावहारिक चरण-दर-चरण गाइड रूबी ऑन रेल्स में टेलविंड CSS जोड़ें: एक व्यावहारिक चरण-दर-चरण गाइड

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

  1. Angular को Rails 5 के साथ इंटीग्रेट करना: एक सहज फुल-स्टैक दृष्टिकोण Angular को Rails 5 के साथ इंटीग्रेट करना: एक सहज फुल-स्टैक दृष्टिकोण

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