रिएक्ट से प्रेरित, ViewComponents रूबी ऑब्जेक्ट हैं जिनका उपयोग दृश्य प्रस्तुत करने के लिए मार्कअप बनाने के लिए किया जाता है। ViewComponent रेल में पुन:प्रयोग करने योग्य, परीक्षण योग्य और इनकैप्सुलेटेड व्यू घटकों के निर्माण के लिए एक ढांचा है। आम तौर पर, पुन:प्रयोज्य दृश्य आंशिक का उपयोग करके रेल में बनाए जाते हैं और फिर आवश्यकतानुसार अलग-अलग दृश्यों में प्रस्तुत किए जाते हैं, लेकिन ViewComponent मणि की शुरूआत के साथ, आंशिक रूप से दृश्य घटकों के लिए स्वैप किया जा सकता है, क्योंकि वे अधिक लाभ प्रदान करते हैं। आइए जानें कि ये फायदे क्या हैं।
मुझे ViewComponents का उपयोग कब और क्यों करना चाहिए?
जैसा कि पहले कहा गया है, दृश्य घटक पुन:प्रयोज्य और परीक्षण योग्य हैं। इसलिए, जब भी किसी दृश्य का पुन:उपयोग किया जाना हो या सीधे परीक्षण किए जाने से लाभ हो, तो उन्हें लागू किया जा सकता है। इसके दस्तावेज़ीकरण में बताए गए घटकों को देखने के कुछ लाभों में निम्नलिखित शामिल हैं:
- वे आंशिक भागों की तुलना में ~10x तेज हैं।
- वे रूबी ऑब्जेक्ट हैं; इसलिए, उनकी प्रारंभिक विधि स्पष्ट रूप से परिभाषित करती है कि दृश्य प्रस्तुत करने के लिए क्या आवश्यक है। इसका मतलब है कि उन्हें समझना और कई अन्य विचारों में पुन:उपयोग करना आसान है। इसके अलावा, रूबी कोड के गुणवत्ता मानकों को लागू किया जा सकता है, जिससे बग का जोखिम कम होता है।
- रेल के पारंपरिक विचारों के विपरीत उन्हें इकाई परीक्षण किया जा सकता है, जिसके लिए एकीकरण परीक्षणों की आवश्यकता होती है जो दृश्य के अलावा रूटिंग और नियंत्रक परतों का भी प्रयोग करते हैं।
ViewComponent कार्यान्वयन
ViewComponents ViewComponent::Base
. के उपवर्ग हैं और app/components
. में रहते हैं . उनके नाम - Component
. में समाप्त होते हैं , और उनका नाम उनके द्वारा प्रस्तुत किए जाने के लिए रखा जाना चाहिए, न कि जो वे स्वीकार करते हैं। हम मैन्युअल रूप से या घटक जनरेटर के माध्यम से एक दृश्य घटक उत्पन्न कर सकते हैं, लेकिन हमारे जेमफाइल में मणि को जोड़े बिना और एक bundle install
चलाए बिना नहीं। पहले।
gem "view_component", require: "view_component/engine"
जनरेटर का उपयोग करने के लिए, निम्न आदेश चलाएँ:
rails generate component <Component name> <arguments needed for initialization>
उदाहरण के लिए, यदि हम सीखने के मंच पर उपलब्ध इन-क्लास पाठ्यक्रमों की सूची प्रदर्शित करने के लिए जिम्मेदार एक घटक उत्पन्न करना चाहते हैं, तो हम इस कमांड का उपयोग कर सकते हैं:
rails g component Course course
हम course
पास कर रहे हैं कमांड के लिए तर्क क्योंकि हम इस रूबी ऑब्जेक्ट को उस पाठ्यक्रम के साथ आरंभ करेंगे जिसकी हम इसे प्रदर्शित करने की उम्मीद करते हैं, और हमने इसे Course
नाम दिया है क्योंकि यह एक पाठ्यक्रम प्रदान करता है। क्या संयोग है!
जैसा कि हम ऊपर देख सकते हैं, घटक और उसके अनुरूप दृश्य app/components
. में बनाए जाते हैं एक परीक्षण फ़ाइल के साथ फ़ोल्डर।
ViewComponent में erb
. के लिए टेम्पलेट जेनरेटर शामिल हैं , haml
, और slim
टेम्प्लेट इंजन लेकिन डिफ़ॉल्ट रूप से जो भी टेम्प्लेट इंजन config.generators.template_engine
में निर्दिष्ट है .फिर भी, आप निम्न का उपयोग करके अपने पसंदीदा टेम्पलेट इंजन को इंगित कर सकते हैं:
rails generate component Course course --template-engine <your template engine>
आइए अपना पाठ्यक्रम मॉडल और प्रदर्शित करने के लिए कुछ पाठ्यक्रम बनाने के लिए आगे बढ़ें।
rails g model Course title:string price:decimal location:string
rails db:migrate
हमारे कंसोल में, हम जल्दी से दो नए पाठ्यक्रम बना सकते हैं:
Course.create(title: 'The Art of Learning', price: 125.00, location: 'Denmark')
Course.create(title: 'Organizing your Time', price: 55.00, location: 'London')
course_component.rb
फ़ाइल इनिशियलाइज़ विधि के साथ उत्पन्न होती है, जैसा कि नीचे दिखाया गया है।
हमें एक पाठ्यक्रम नियंत्रक बनाने की आवश्यकता है जो हमें पाठ्यक्रमों की सूची में ले जाए।
rails g controller Courses index
हमारे routes.rb
. में फ़ाइल में, हम निम्नलिखित जोड़कर अपना रूट रूट इंगित करते हैं:
root 'courses#index'
अब जबकि हम पूरी तरह से तैयार हैं, अगला चरण व्यू क्रिएशन है। यह पहले से जेनरेट किए गए course_component.html.erb
. में किया जाता है ।
<div>
<h2><%= @course.title %></h2>
<h4><%= number_to_currency(@course.price, :unit => "€") %></h4>
<h4><%= @course.location %></h4>
</div>
हमारे विचार में, हम @course
. का उपयोग करके पाठ्यक्रम का शीर्षक, मूल्य और स्थान प्रदर्शित करते हैं वेरिएबल, जो पहले से ही हमारे कोर्सकंपोनेंट की प्रारंभिक विधि में परिभाषित किया गया था। यह वैसा ही है जैसा कि आप नियंत्रक विधि में एक चर बनाते हैं, और फिर यह एक दृश्य में उपलब्ध होता है।
यह जानते हुए कि नियंत्रक कैसे काम करते हैं, हमें संबंधित index.html.erb
पर भेजा जाएगा। हमारे सूचकांक विधि का। इसलिए, यह वह जगह है जहां हम अपने घटक प्रस्तुत करते हैं।
#app/views/courses/index.html.erb
<%= render(CourseComponent.new(course: Course.find(1))) %>
जैसा कि ऊपर देखा गया है, हम अपने कोर्सकंपोनेंट का एक नया उदाहरण प्रस्तुत करते हैं, इसे उस पाठ्यक्रम के साथ प्रारंभ करते हैं जिसे हम इसके विचार में प्रस्तुत करना चाहते हैं। यह कोर्स @course
बन जाता है चर course_component.html.erb
. को उपलब्ध कराया गया फ़ाइल।
इस घटक को सीधे हमारे नियंत्रक से प्रस्तुत करना भी संभव है, जिससे अनुक्रमणिका फ़ाइल दृश्य को दरकिनार किया जा सकता है:
class CoursesController < ApplicationController
def index
render(CourseComponent.new(course: Course.find(1)))
end
end
आप चाहे जो भी तरीका चुनें, यह सर्वर पर दिखाई देगा:
अतिरिक्त सामग्री को निम्न में से किसी एक तरीके से घटक को पास किया जा सकता है:
<%= render(CourseComponent.new(course: Course.find(1))) do %>
container
<% end %>
<%= render(CourseComponent.new(course: Course.find(1)).with_content("container")) %>
हमारे व्यू कंपोनेंट फ़ाइल में, हम जहाँ चाहें सामग्री शामिल कर सकते हैं। इस मामले में, हम इस तरह दिखने के लिए हमारे div को संपादित करके इसे एक वर्ग के रूप में शामिल करेंगे:
<div class=<%= content %>>
अतिरिक्त सामग्री को प्रस्तुत करने के उपरोक्त सभी तरीकों से नीचे की छवि मिलती है:
एक संग्रह को रेंडर करना
क्या होगा यदि हम अपने पाठ्यक्रमों की पूरी सूची प्रस्तुत करना चाहते हैं? ViewComponent with_collection
. का उपयोग करके ऐसा करने का एक बहुत ही सीधा तरीका प्रदान करता है उपनाम। .new
. का उपयोग करके घटक को प्रारंभ करने के बजाय , इसे .with_collection
. का उपयोग करके प्रारंभ किया जाता है , और संग्रह को एक चर के रूप में पास किया जाता है, जैसा कि नीचे दिखाया गया है।
CourseComponent.with_collection(Course.all)
यह निम्नलिखित देता है:
एक with_collection_parameter
. भी है यदि हम संग्रह को किसी भिन्न नाम से संबोधित करना चाहते हैं तो टैग उपलब्ध है।
class CourseComponent < ViewComponent::Base
with_collection_parameter :item
def initialize(item:)
@item = item
end
end
उपरोक्त मामले में, पाठ्यक्रम पैरामीटर को item
. के रूप में संबोधित किया गया है . इसलिए, संबंधित दृश्य में, @course
@item
. से बदल दिया जाएगा एक ही परिणाम देने के लिए।
संग्रह में अतिरिक्त पैरामीटर भी जोड़े जा सकते हैं। ये पैरामीटर संग्रह में प्रति आइटम प्रदर्शित किए जाएंगे। आइए एक Buy Me
जोड़ें इस विधि के माध्यम से प्रत्येक आइटम को टेक्स्ट करें।
#app/views/courses/index.html.erb
<%= render(CourseComponent.with_collection(Course.all, notice: "Buy Me")) %>
# app/components/course_component.rb
class CourseComponent < ViewComponent::Base
with_collection_parameter :item
def initialize(item:, notice:)
@item = item
@notice = notice
end
end
हम app/components/course_component.html.erb
में एक नया पैराग्राफ़ जोड़ते हैं नए जोड़े गए नोटिस चर के पाठ को इंगित करने के लिए फ़ाइल।
<p><a href='#'> <%= @notice %> </a></p>
यह निम्नलिखित देता है:
अंत में, संग्रह के तहत, हमारे पास एक काउंटर वेरिएबल है जिसे आइटम को एक दृश्य में संख्याबद्ध करने के लिए सक्षम किया जा सकता है। इसे _counter
. जोड़कर सक्षम किया गया है संग्रह पैरामीटर के लिए और इसे इनिशियलाइज़ विधि के माध्यम से विचारों के लिए उपलब्ध कराना।
#app/components/course_component.rb
def initialize(item:, notice:, item_counter:)
@item = item
@notice = notice
@counter = item_counter
end
हमारे विचार में, आइटम शीर्षक के साथ, हम अपना काउंटर जोड़ते हैं:
<h2><%= @counter %>. <%= @item.title %></h2>
आइए काउंटर घटना को बेहतर ढंग से समझने के लिए कंसोल से तीसरा कोर्स तैयार करें।
Course.create(title: 'Understanding Databases', price: '100', location: 'Amsterdam')
यह निम्नलिखित उत्पन्न करता है
सशर्त रेंडरिंग
ViewComponent में एक render?
. है हुक, जो, जब उपयोग किया जाता है, यह निर्धारित करता है कि एक दृश्य प्रस्तुत किया जाना चाहिए या नहीं। इसे लागू करने के लिए, हम 100 यूरो के बराबर या अधिक कीमतों वाले पाठ्यक्रमों के लिए 10% की छूट देने जा रहे हैं। आइए इस उद्देश्य के लिए एक घटक बनाएं।
rails generate component Discount item
जैसा कि नीचे देखा गया है, यह घटक पहले से ही स्वचालित रूप से उस आइटम के साथ आरंभ किया गया है जिसके लिए इसे छूट प्रदर्शित करनी चाहिए।
इसलिए, discount_component.html.erb
. में फ़ाइल, हम वह पाठ जोड़ते हैं जिसे हम प्रदर्शित करना चाहते हैं।
<p class="green"> A 10% discount is available on this course </p>
वर्ग जोड़ने में संकोच न करें green
अपनी सीएसएस फ़ाइल में और इसे अपनी पसंद के हरे रंग की कोई भी छाया असाइन करें। इसके अलावा, हमारे discount_component.rb
. में फ़ाइल में, हम render?
. जोड़ते हैं यह निर्धारित करने की विधि कि इस घटक को कब प्रस्तुत किया जाना चाहिए।
def render?
@item.price >= 100
end
अब, हम आगे बढ़ सकते हैं और छूट घटक को उस दृश्य के भीतर प्रस्तुत कर सकते हैं जो प्रत्येक पाठ्यक्रम को प्रस्तुत करता है।
# app/components/course_component.html.erb
<%= render(DiscountComponent.new(item: @item)) %>
यह निम्नलिखित देता है:
क्या यह कमाल नहीं है?
सहायक
पारंपरिक रेल विचारों में, हम अपने विचारों में विधि नाम को कॉल करके आसानी से अपने सहायकों को प्लग इन कर सकते हैं, लेकिन यह दृश्य घटकों के साथ अलग तरह से काम करता है। दृश्य घटकों में, सहायक विधियों को सीधे विचारों में नहीं कहा जा सकता है, लेकिन एक घटक में शामिल किया जा सकता है। हमारे पास पहले से ही एक courses_helper.rb
है फ़ाइल जो स्वचालित रूप से तब उत्पन्न हुई थी जब पाठ्यक्रम नियंत्रक बनाया गया था, तो चलिए इसका लाभ उठाते हैं। सबसे पहले, आइए एक सहायक विधि बनाते हैं जो हमें बताती है कि अब तक कितने लोगों ने एक कोर्स में दाखिला लिया है। आइए मान को कीमत का एक चौथाई बना दें :)।
module CoursesHelper
def count_enrollees(course)
count = (course.price / 4).round()
tag.p "#{count} enrollees so far"
end
end
इसके बाद, हम एक कंपोनेंट बनाएंगे जिसमें हम हेल्पर को कॉल करेंगे। यह वह घटक है जिसे हमारे विचार में प्रस्तुत किया जाएगा। इसमें, हम एक include
. जोड़ देंगे कथन, सहायक सहित, और फिर हम इस घटक के भीतर सहायक में किसी भी विधि को कॉल कर सकते हैं।
# app/components/enrollee_component.rb
class EnrolleeComponent < ViewComponent::Base
include CoursesHelper
def total_enrollees(course)
count_enrollees(course)
end
end
अंतिम चरण हमारे पाठ्यक्रमों को प्रदर्शित करने वाले दृश्य में EnrolleeComponent को जोड़ रहा है।
# app/components/course_component.html.erb
<%= EnrolleeComponent.new.total_enrollees(@item) %>
ध्यान दें कि हम EnrolleeComponent के लिए रेंडर शब्द का उपयोग नहीं कर रहे हैं, क्योंकि इसमें कोई दृश्य नहीं है, और इसका आउटपुट हेल्पर मेथड कहलाता है। यह निम्नलिखित देता है:
हेल्पर्स का उपयोग आइकन, ग्रेविटर, या जो कुछ भी आप चुन सकते हैं, के लिए किया जा सकता है। ViewComponent सहायकों के उपयोग को नहीं बदलता है; यह बस बदलता है कि हम उन्हें अपने घटकों में कैसे कहते हैं।
पहले_रेंडर विधि
ViewComponent एक before_render
. प्रदान करता है विधि जिसे किसी घटक को प्रस्तुत करने से पहले बुलाया जा सकता है। आइए हमारे डिस्काउंट नोटिस के बगल में एक सितारा जोड़ें। हम एक सहायक विधि जोड़कर शुरू करते हैं जो स्टार को प्राप्त करती है; एक star.png
छवि को भी डाउनलोड किया गया है और app/assets/images
में रखा गया है फ़ोल्डर।
#app/helpers/courses_helper.rb
def star_icon
image_tag("/assets/star.png", width: "1%")
end
आइए एक before_render
जोड़ें हमारे डिस्काउंट घटक के लिए विधि जो इस सहायक विधि को कॉल करती है।
# app/components/discount_component.rb
def before_render
@star_icon = helpers.star_icon
end
जैसा कि हम ऊपर देख सकते हैं, हेल्पर्स को कॉल करने का एक और तरीका पेश किया गया है। हेल्पर्स को helpers.method
. का उपयोग करके भी बुलाया जा सकता है घटक.आरबी फ़ाइल में। फिर, डिस्काउंटकंपोनेंट के लिए हमारी रेंडर विधि में, हम अपने स्टार आइकन को इनपुट करते हैं, जो अब @star_icon
के माध्यम से उपलब्ध कराया गया है। चर।
# app/components/discount_component.html.erb
<p class="green"> <%= @star_icon %> A 10% discount is available on this course </p>
यह निम्नलिखित देता है:
जरूरी नहीं कि हमें before_render
. के लिए हेल्पर्स का इस्तेमाल करना पड़े काम करने की विधि। मैंने हेल्पर्स का उपयोग हेल्पर विधियों को कॉल करने के लिए एक और दृष्टिकोण पेश करने के लिए किया है।
पूर्वावलोकन
एक्शन मेलर की तरह, व्यूकंपोनेंट घटकों का पूर्वावलोकन करना संभव बनाता है। इसे पहले config/application.rb
. में इनेबल करना होगा फ़ाइल।
config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
पूर्वावलोकन घटक test/components/previews
. में स्थित हैं और एक घटक का पूर्वावलोकन करने के लिए इस्तेमाल किया जा सकता है जिसमें कई अलग-अलग इनपुट पास हुए हैं। हम अपने डिस्काउंटकंपोनेंट का पूर्वावलोकन करेंगे।
# test/components/previews/discount_component_preview.rb
class DiscountComponentPreview < ViewComponent::Preview
def with_first_course
render(DiscountComponent.new(item: Course.find(1)))
end
def with_second_course
render(DiscountComponent.new(item: Course.find(2)))
end
end
विभिन्न परिदृश्यों में डिस्काउंटकंपोनेंट का पूर्वावलोकन करने के लिए दो तरीके जोड़े गए हैं। इसे देखने के लिए, https://localhost:3000/rails/view_components
पर जाएं , जहां हमें बनाए गए सभी पूर्वावलोकन घटक और उनके तरीके मिलते हैं। हम उनमें से किसी पर भी क्लिक करके देख सकते हैं कि वे कैसे दिखते हैं, जैसा कि नीचे दिखाया गया है।
जैसा कि आप ऊपर दिए गए वीडियो में देख सकते हैं, पहला कोर्स छूट घटक प्रस्तुत करता है, लेकिन दूसरे पाठ्यक्रम के लिए कुछ भी प्रदान नहीं किया जाता है। क्या आप जानते हैं ऐसा क्यों हुआ? render?
विधि जाँच हुई। पहला परिदृश्य तब है जब लागत मूल्य 100 यूरो (पहला कोर्स) से अधिक है, लेकिन दूसरे कोर्स के लिए लागत 100 यूरो से कम है। विधि के नाम अधिक वर्णनात्मक नहीं थे ताकि आप यहां पर प्रकाश डालने से पहले कारण का पता लगा सकें :)।
पूर्वावलोकन को किसी भी परिवेश में show_previews
. का उपयोग करके सक्षम या अक्षम किया जा सकता है विकल्प, लेकिन विकास और परीक्षण वातावरण में, वे डिफ़ॉल्ट रूप से सक्षम होते हैं।
# config/environments/test.rb
config.view_component.show_previews = false
JS और CSS समावेश
जावास्क्रिप्ट और सीएसएस को घटकों के साथ शामिल करना संभव है, जिन्हें कभी-कभी "साइडकार" संपत्ति या फाइलें कहा जाता है। यह अभी भी एक प्रायोगिक विशेषता है। इसलिए, हम इस लेख में इसकी आंतरिक कार्यप्रणाली पर ध्यान नहीं देंगे, लेकिन आप यहां इस ViewComponent सुविधा के बारे में अधिक जानकारी प्राप्त कर सकते हैं।
टेम्प्लेट
एक दृश्य घटक के टेम्पलेट को कई तरीकों से परिभाषित किया जा सकता है। सरल विकल्प दृश्य और घटक को उसी फ़ोल्डर में सम्मिलित करना है, जैसा कि नीचे दिखाया गया है।
जैसा कि हम यहां देख सकते हैं, हमारे पास app/components
. में हर कंपोनेंट और व्यू है फ़ोल्डर।
एक अन्य विकल्प दृश्य और अन्य संपत्तियों को घटक के समान नाम वाली उपनिर्देशिका में रखना है। इस प्रकार, app/components
. में फ़ोल्डर, हमारे पास component.rb
. है फ़ाइल, जिसमें घटक होता है, और फिर एक अलग course_component
फ़ोल्डर, जिसमें दृश्य होता है course_component.html.erb
और course_component से संबंधित हर दूसरी संपत्ति।
कमांड लाइन से इस तरह से कंपोनेंट फाइल जेनरेट करने के लिए, --sidecar
ध्वज आवश्यक है:
rails g component Example name --sidecar
यह आपको अपनी css और js फ़ाइलों को घटक फ़ोल्डर में जोड़ने में सक्षम बनाता है। ViewComponents एक call
को परिभाषित करके टेम्पलेट फ़ाइल के बिना भी प्रस्तुत कर सकते हैं तरीका। इसका एक उदाहरण अगले भाग में दिया गया है, जहां हम स्लॉट . पर चर्चा करते हैं ।
स्लॉट
स्लॉट . का उपयोग करके सामग्री के एकाधिक ब्लॉक एकल ViewComponent को पास किए जा सकते हैं . has_one
. के समान और has_many
रेल मॉडल में विशेषताएँ, स्लॉट को renders_one
. के साथ परिभाषित किया गया है और renders_many
:
- renders_one एक स्लॉट को परिभाषित करता है जिसे प्रति घटक अधिकतम एक बार रेंडर किया जाएगा:renders_one :header.
- renders_many एक स्लॉट को परिभाषित करता है जिसे प्रति-घटक कई बार रेंडर किया जा सकता है:renders_many :titles.
कल्पना कीजिए कि हम एक ऐसा पृष्ठ चाहते हैं जो हमारे पास उपलब्ध सभी पाठ्यक्रमों के शीर्षलेख और शीर्षक प्रस्तुत करे; इसे स्लॉट . का उपयोग करके प्राप्त किया जा सकता है . आइए एक ListComponent बनाएं , जिसमें एक हेडर होगा जो केवल एक बार रेंडर किया गया है, और एक TitleComponent , जो कई शीर्षक प्रदान करता है।
#app/components/list_component.rb
class ListComponent < ViewComponent::Base
renders_one :header, "HeaderComponent"
# `HeaderComponent` is defined within this component, so we refer to it using a string.
renders_many :titles, TitleComponent
# `titleComponent` will be defined in another file, so we can refer to it by class name.
class HeaderComponent < ViewComponent::Base
def call
content_tag :h1, content
end
end
end
उपरोक्त घटक में, हमने कहा है कि शीर्षलेख एक बार प्रस्तुत किया जाता है, लेकिन शीर्षक कई बार प्रस्तुत किए जाते हैं, क्योंकि इस पृष्ठ में कई शीर्षक होंगे। हमने ListComponent के भीतर HeaderComponent को भी परिभाषित किया है। हाँ, यह ViewComponent के साथ संभव है; एक वर्ग को दूसरे वर्ग के भीतर परिभाषित किया जा सकता है। आइए पहले टेम्प्लेट अनुभाग के तहत चर्चा की गई कॉल विधि पर भी ध्यान दें और यह कैसे एक h1 टैग को प्रस्तुत करने के लिए HeaderComponent में उपयोग किया जा रहा है, जिससे संबंधित दृश्य (html.erb फ़ाइल) की आवश्यकता समाप्त हो जाती है। ListComponent के लिए संबंधित HTML फ़ाइल में निम्नलिखित शामिल होंगे;
#app/components/list_component.html.erb
<div>
<%= header %> <!-- renders the header component -->
<% titles.each do |title| %>
<div>
<%= title %> <!-- renders an individual course title -->
</div>
<% end %>
</div>
एचटीएमएल फाइल में, हमने हेडर शामिल किया है, घटक में पारित सभी शीर्षकों के माध्यम से पुनरावृत्त किया गया है, और उन्हें प्रस्तुत किया है। जैसा कि आप देख सकते हैं, हमें सूची दृश्य फ़ाइल में प्रस्तुत किए जाने वाले घटक का नाम निर्दिष्ट करने की आवश्यकता नहीं है; हमारे स्लॉट्स ने इसका ध्यान रखा है। इसलिए, हम उन्हें केवल header
. के रूप में पहचानते हैं और title
।
अगला कदम हमारी टाइटलकंपोनेंट और इसकी संबंधित एचटीएमएल फाइल बनाना है, क्योंकि यह वही है जो पारित किए गए प्रत्येक शीर्षक के लिए प्रस्तुत किया जाएगा।
# app/components/title_component.rb
class TitleComponent < ViewComponent::Base
def initialize(title:)
@title = title
end
end
# app/components/title_component.html.erb
<div>
<h3> <%= @title %> </h3>
</div>
अंत में, हमारे index.html
. में फ़ाइल, आइए अस्थायी रूप से हमारे पास जो कुछ है उसे मिटा दें और इसे ListComponent रेंडर से बदलें।
#app/views/courses/index.html.erb
<%= render ListComponent.new do |c| %>
<% c.header do %>
<%= link_to "List of Available Courses", root_path %>
<% end %>
<%= c.title(title: "First title") %>
<%= c.title(title: "Second title!") %>
<% end %>
अब, आइए अपने पाठ्यक्रमों को इस दृष्टिकोण में एक संग्रह के रूप में पारित करें। एक संग्रह को एक स्लॉट में पास करने के लिए, हमें संग्रह को वस्तुओं की एक सरणी के रूप में पास करना होगा जिसमें आरंभीकरण के लिए आवश्यक चर शामिल हैं। जैसा कि हम देख सकते हैं, पारित किए गए प्रत्येक पाठ्यक्रम को शीर्षक तर्क के साथ प्रारंभ किया जाना चाहिए। हम अपने डीबी में सभी पाठ्यक्रमों के शीर्षक हैश की एक सरणी में निकाल सकते हैं और इसे प्रस्तुत कर सकते हैं।
अब हम कई शीर्षकों की अपनी सूची को एक c.titles
. से बदल सकते हैं एक संग्रह के लिए और इसे हमारे शीर्षकों के हैश में पास करें, जिसे हम चर course_titles
का उपयोग करके परिभाषित करते हैं ।
# app/views/courses/index.html.erb
<% course_titles = Course.all.pluck(:title).map { |title| {title: title}} %>
<% c.titles(course_titles) %>
यह निम्नलिखित देता है:
यह ठीक इसी तरह से स्लॉट काम करता है:एक ही व्यूकंपोनेंट के भीतर कई घटकों को प्रस्तुत करना। स्लॉट कई अन्य तरीकों से प्रस्तुत किए जा सकते हैं, और आप यहां अधिक जानकारी प्राप्त कर सकते हैं।
परीक्षण
परीक्षण फ़ाइल में "view_component/test_case" की आवश्यकता और render_inline
का उपयोग करके परीक्षण दृश्य घटकों को किया जाता है परीक्षण सहायक ताकि प्रस्तुत किए गए आउटपुट के खिलाफ दावा किया जा सके। आइए हमारे डिस्काउंटकंपोनेंट का परीक्षण करके शुरू करें।
require "test_helper"
require "view_component/test_case"
class DiscountComponentTest < ViewComponent::TestCase
def test_render_component
render_inline(DiscountComponent.new(item: "my item"))
end
end
जब हम rails test test/components/discount_component_test.rb
कमांड का उपयोग करके इस परीक्षण को चलाते हैं , हमें निम्न त्रुटि मिलती है:
यह हमें साबित करता है कि परीक्षण सही घटक के लिए हो रहा है, लेकिन एक उपयुक्त प्रोप की कमी है, क्योंकि आइटम एक मूल्य संपत्ति के साथ एक कोर्स होना चाहिए, न कि एक स्ट्रिंग, जैसा कि हम पारित कर चुके हैं। यह हमें यह भी बताता है कि एक render?
. है इस घटक प्रस्तुत करने से पहले विधि की जाँच की जा रही है। आइए अब सही वेरिएबल्स में पास करें।
def test_render_component
course = Course.create(title: 'Organizing your Time', price: 55.00, location: 'London')
render_inline(DiscountComponent.new(item: course))
end
यह सफलतापूर्वक चलता है। आइए इस परीक्षण में अभिकथन जोड़ने के लिए आगे बढ़ें।
def test_render_component
course = Course.create(title: 'Organizing your Time', price: 155.00, location: 'London')
render_inline(DiscountComponent.new(item: course))
assert_selector 'p[class="green"]'
assert_text "10% discount"
end
यह परीक्षण भी पास हो जाता है। याद रखें कि इस घटक के लिए एक रेंडर स्थिति है। हालांकि, चिंता न करें, क्योंकि ViewComponent refute_component_rendered
का उपयोग करके यह जांचने का एक तरीका भी प्रदान करता है कि कोई घटक रेंडर नहीं किया गया है . हम 100 यूरो से कम कीमत वाले पाठ्यक्रम का उपयोग करके इसका परीक्षण कर सकते हैं।
def test_component_not_rendered
course = Course.create(title: 'Organizing your Time', price: 55.00, location: 'London')
render_inline(DiscountComponent.new(item: course))
refute_component_rendered
end
यह परीक्षा भी पास हो जाती है।
आइए हमारे कोर्सकंपोनेंट के लिए एक और परीक्षण लिखें ताकि यह परीक्षण किया जा सके कि यह इसके भीतर निहित सभी घटकों को प्रस्तुत करता है।
require "test_helper"
require "view_component/test_case"
class CourseComponentTest < ViewComponent::TestCase
def test_component_renders_all_children
course = Course.create(title: 'Organizing your Time', price: 155.00, location: 'London')
render_inline(CourseComponent.new(item: course, notice: 'A new test', item_counter: 1))
assert_selector("h2", text: "Organizing your Time")
assert_selector("h4", text: "€155.00")
assert_selector("h4", text: "London")
assert_text("enrollees")
assert_text("discount")
end
end
यह परीक्षा भी पास हो जाती है। यह परीक्षण करता है कि नामांकन और छूट घटक भी ठीक से प्रस्तुत कर रहे हैं।
याद रखें कि हमारे पास एक स्लॉट घटक है, और जैसा कि नीचे दी गई छवि में दिखाया गया है, यह एक हेडर और कई शीर्षक प्रदान करता है।
इसका परीक्षण करने के लिए, हम घटक को कोड का एक ब्लॉक पास करते हैं जिसमें हेडर और शीर्षक होते हैं, और फिर हम रेंडर किए गए घटक के खिलाफ जोर दे सकते हैं।
require "test_helper"
require "view_component/test_case"
class ListComponentTest < ViewComponent::TestCase
def test_renders_slots_with_content
render_inline(ListComponent.new) do |component|
component.header { "A Test List" }
component.titles [{title: 'Test title 1'}, {title: 'Test title 2'}]
end
assert_selector("h1", text: "A Test List")
assert_text("Test title 1")
assert_text("Test title 2")
end
end
यह परीक्षा भी पास हो जाती है :)।
Rspec Testing
परीक्षण के बारे में ऊपर बताई गई सभी बातों के अलावा, यदि पसंदीदा परीक्षण ढांचा RSpec है, तो ViewComponents के लिए RSpec को सक्षम करने के लिए कुछ अतिरिक्त कॉन्फ़िगरेशन किए जाने चाहिए।
# spec/rails_helper.rb
require "view_component/test_helpers"
require "capybara/rspec"
RSpec.configure do |config|
config.include ViewComponent::TestHelpers, type: :component
config.include Capybara::RSpecMatchers, type: :component
end
जैसा कि नीचे दिखाया गया है, हमारे डिस्काउंटकंपोनेंट परीक्षण को रुपयेपेक का उपयोग करके फिर से लिखा और पुन:परीक्षण किया जा सकता है:
require "rails_helper"
RSpec.describe DiscountComponent, type: :component do
it "renders the component correctly" do
course = Course.create(title: 'Organizing your Time', price: 155.00, location: 'London')
render_inline(DiscountComponent.new(item: course))
expect(rendered_component).to have_css "p[class='green']", text: "10% discount"
expect(rendered_component).to have_css "img[src*='/assets/star.png']"
end
end
यह परीक्षा सुरुचिपूर्ण ढंग से गुजरती है। अरे हाँ, हम अपना स्टार आइकन देख सकते हैं।
निष्कर्ष
अपने रेल ऐप के लिए कई दृश्य घटकों को लिखना न केवल आपके कोड को अधिक पठनीय और अवांछित जटिलताओं से त्रुटियों के लिए कम प्रवण बनाता है बल्कि न केवल HTTP अनुरोधों के दौरान अलगाव में आपके विचारों का परीक्षण करना संभव बनाता है। मौजूदा रेल ऐप में घटकों को देखना आसान है, और अधिकतर पुन:उपयोग किए जाने वाले विचारों से शुरू करना सबसे अच्छा है। अब तक सीखी गई हर चीज के साथ, यह एक आसान काम होना चाहिए। फिर भी, यदि आप ViewComponent के बारे में अधिक जानकारी चाहते हैं, तो इसके दस्तावेज़ीकरण या RubyDoc जानकारी के माध्यम से जाने में संकोच न करें।