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

रेल्स को सरल बनाना: क्लीनर कंट्रोलर्स के लिए `respond_to` में महारत हासिल करना

जब आप रेल्स में एक स्कैफोल्ड उत्पन्न करते हैं, तो आप सामान्य respond_to ब्लॉक्स देखेंगे:

app/controllers/tasks_controller.rb
 def destroy
  @task.destroy
  respond_to do |format|
    format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
    format.json { head :no_content }
  end
 end

लेकिन आपके कुछ एक्शन्स, जैसे index, में वे नहीं होते!

app/controllers/tasks_controller.rb
 # GET /tasks
 # GET /tasks.json
 def index
  @tasks = Task.all
 end

यह बुरा है। क्यों? यदि आप /tasks.txt हिट करते हैं, और txt आपके ऐप द्वारा समर्थित नहीं है, तो आपको गलत त्रुटि मिलेगी:

ActionView::MissingTemplate (Missing template tasks/index, application/index with {:locale=>[:en], :formats=>[:text], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}

यह बिल्कुल सही नहीं है। आपको क्लाइंट को बता देना चाहिए कि वे एक ऐसा फॉर्मेट रिक्वेस्ट कर रहे हैं जिसका आप समर्थन नहीं करते, न कि यह कि आपको सही फाइल नहीं मिल रही है।

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

आप अपने index एक्शन में एक respond_to ब्लॉक जोड़ सकते हैं:

app/controllers/tasks_controller.rb
 # GET /tasks
 # GET /tasks.json
 def index
  @tasks = Task.all
  respond_to do |format|
    format.html
    format.json
  end
 end

फिर, आपको वह अपवाद और त्रुटि कोड मिलेगा जिसकी आप उम्मीद करेंगे:

Started GET "/tasks.txt" for 127.0.0.1 at 2014-11-03 22:05:12 -0800
Processing by TasksController#index as TEXT
Completed 406 Not Acceptable in 21ms
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/tasks_controller.rb:8:in `index'

बहुत बेहतर। लेकिन अपने सभी कंट्रोलर्स को respond_to से भर देना पागलपन है। यह अन-रेल्स जैसा लगता है। यह DRY का उल्लंघन करता है। और यह आपको उस काम से विचलित करता है जो आपका कंट्रोलर वास्तव में कर रहा है।

आप अभी भी खराब फॉर्मेट को सही ढंग से संभालना चाहते हैं। तो आप क्या करते हैं?

एक respond_to शॉर्टकट

यदि आप अपने ऑब्जेक्ट्स को रेंडर करने के लिए कुछ खास नहीं कर रहे हैं, तो आप एक शॉर्टकट ले सकते हैं। यदि आप लिखते हैं:

app/controllers/tasks_controller.rb
def index
  @tasks = Task.all
  respond_to :html, :json
end

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

कंट्रोलर लेवल पर फॉर्मेट्स को संभालें

आमतौर पर, हालांकि, आपके कंट्रोलर में प्रत्येक एक्शन उसी फॉर्मेट्स के साथ काम करेगा। यदि index json का जवाब देता है, तो new, और create, और बाकी सब भी देंगे। तो यह अच्छा होगा यदि आपके पास एक respond_to हो जो पूरे कंट्रोलर को प्रभावित करे:

app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  before_action :set_task, only: [:show, :edit, :update, :destroy]
  respond_to :html, :json
  # GET /tasks
  # GET /tasks.json
  def index
    @tasks = Task.all
    respond_with(@tasks)
  end

और यह वास्तव में काम करता है:

Started GET "/tasks.txt" for 127.0.0.1 at 2014-11-03 22:17:37 -0800
Processing by TasksController#index as TEXT
Completed 406 Not Acceptable in 7ms
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/tasks_controller.rb:8:in `index'

ठीक वैसी ही त्रुटि जिसकी हम उम्मीद कर रहे थे! और आपको इसे करने के लिए प्रत्येक एक्शन के साथ छेड़छाड़ नहीं करनी पड़ी।

कभी-कभी आप मॉडल की स्थिति के आधार पर अलग-अलग चीजें करना चाहेंगे। उदाहरण के लिए, create के लिए, आप या तो रीडायरेक्ट करेंगे या फॉर्म को फिर से रेंडर करेंगे, इस पर निर्भर करता है कि मॉडल वैध है या नहीं।

रेल्स इसे संभाल सकता है। लेकिन आपको अभी भी इसे बताना होगा कि आप कौन सा ऑब्जेक्ट चाहते हैं जिसे यह जांचे, respond_with के साथ। इसलिए इसके बजाय:

app/controllers/tasks_controller.rb
 def create
  @task = Task.new(task_params)
  respond_to do |format|
    if @task.save
      format.html { redirect_to @task, notice: 'Task was successfully created.' }
      format.json { render :show, status: :created, location: @task }
    else
      format.html { render :new }
      format.json { render json: @task.errors, status: :unprocessable_entity }
    end
  end
 end

आप लिख सकते हैं:

app/controllers/tasks_controller.rb
 def create
  @task = Task.new(task_params)
  flash[:notice] = "Task was successfully created." if @task.save
  respond_with(@task)
 end

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

द रेस्पॉन्डर्स जेम

रेल्स 4.2 में, एक पकड़ है: respond_with अब शामिल नहीं है। लेकिन आप इसे वापस पा सकते हैं यदि आप responders जेम इंस्टॉल करते हैं। और responders जेम इसके साथ कुछ अन्य अच्छी फीचर्स लाता है।

आप अपने कंट्रोलर के शीर्ष पर responders :flash शामिल करके respond_with में फ्लैश मैसेज सेट कर सकते हैं:

app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  responders :flash

सुविधाजनक रूप से, आप इन फ्लैश मैसेज के लिए डिफ़ॉल्ट सेट कर सकते हैं अपने लोकेल फाइलों में।

इसके अलावा, यदि आपके Gemfile में responders जेम है और आप एक रेल्स स्कैफोल्ड उत्पन्न करते हैं, तो जनरेटर respond_to के बजाय respond_with का उपयोग करके कंट्रोलर्स बनाएगा:

app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  before_action :set_task, only: [:show, :edit, :update, :destroy]
  respond_to :html, :json
  def index
    @tasks = Task.all
    respond_with(@tasks)
  end
  def show
    respond_with(@task)
  end
  # ...

यह रेल्स के साथ आने वाले स्कैफोल्ड्स की तुलना में बहुत क्लीनर है।

और अंत में, यदि आप केवल विशिष्ट कंट्रोलर एक्शन के लिए एक फॉर्मेट के साथ जवाब देना चाहते हैं, तो आप respond_to को कई बार कॉल कर सकते हैं:

class TasksController < ApplicationController
  respond_to :html
  respond_to :js, only: :create
end

उस अंतिम टिप के लिए टिप्पणियों में जेरोन वेइंक को धन्यवाद!

respond_with या respond_to?

यदि आप अलग-अलग फॉर्मेट्स के लिए अलग-अलग जानकारी वापस करना चाहते हैं, तो आपके पास कुछ विकल्प हैं। कंट्रोलर-लेवल respond_to respond_with के साथ संयुक्त छोटे कंट्रोलर्स प्राप्त करने का एक शानदार तरीका है। लेकिन यह सबसे अधिक मदद करता है जब आपके सभी कंट्रोलर एक्शन उसी फॉर्मेट का जवाब देते हैं, और उस तरह से कार्य करते हैं जिस तरह रेल्स उनसे उम्मीद करता है।

कभी-कभी, हालांकि, आप कुछ एक्शन चाहते हैं जो अलग तरह से कार्य करें। वन-लाइनर respond_to उस स्थिति को संभालने के लिए बहुत अच्छा है।

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

इनमें से किसी के साथ, आपके द्वारा समर्थित नहीं फॉर्मेट्स के लिए अनुरोधों को सही त्रुटि मिलेगी। और आपका ऐप और इसके क्लाइंट बहुत कम भ्रमित होंगे।

  1. Amazon Day: अपनी सभी डिलीवरी एक ही दिन प्राप्त करें Amazon Day: अपनी सभी डिलीवरी एक ही दिन प्राप्त करें

    Amazon वर्षों से एक घरेलू नाम रहा है, लेकिन 2020 में Amazon की बिक्री ने सर्वकालिक उच्च स्तर को छू लिया। पहले से कहीं अधिक लोग Amazon के साथ खरीदारी कर रहे हैं, कुछ एक समर्पित Amazon Day बना रहे हैं, जहां वे उस सप्ताह के लिए अपने सभी पैकेज प्राप्त करते हैं। यह उन लोगों के लिए आदर्श है जिनके पास नियम

  1. MongoDB संग्रह से सभी फील्ड नाम कुशलतापूर्वक पुनर्प्राप्त करें MongoDB संग्रह से सभी फील्ड नाम कुशलतापूर्वक पुनर्प्राप्त करें

    परिचय मूल रूप से 18 जनवरी, 2019 को ObjectRocket.com/blog पर प्रकाशित। अपने स्कीमा को मान्य करने के लिए, फील्ड में टाइपो डीबग करने के लिए, या उन फील्ड को ढूंढने के लिए जिन्हें आप सेट नहीं करना चाहिए, आपको अपने MongoDB® संग्रह में सभी कुंजियों की समझ की आवश्यकता है। ObjectRocket सहित कई MongoDB-as-a-

  1. अपने MongoDB कलेक्शन में सभी की नाम आसानी से प्राप्त करें अपने MongoDB कलेक्शन में सभी की नाम आसानी से प्राप्त करें

    अपने स्कीमा को मान्य करने, फील्ड्स में टाइपो डीबग करने, या उन फील्ड्स को ढूंढने के लिए जो सेट नहीं होने चाहिए, आपको अपने MongoDB कलेक्शन में सभी कीज़ की समझ प्राप्त करने की आवश्यकता होगी। MongoDB-as-a-service कंपनियों में से कई, ObjectRocket सहित, UI में सीधे ऐसा करने का एक आसान तरीका प्रदान करती ह