जब आप रेल में मचान उत्पन्न करते हैं, तो आप सामान्य respond_to
. देखेंगे ब्लॉक:
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
, उनके पास नहीं है!
# GET /tasks
# GET /tasks.json
def index
@tasks = Task.all
end
यह तो बुरा हुआ। क्यों? अगर आप /tasks.txt
hit दबाते हैं , और txt
आपके ऐप द्वारा समर्थित नहीं है, आपको गलत त्रुटि मिलेगी:
ActionView::MissingTemplate (Missing template tasks/index, application/index with {:locale=>[:en], :formats=>[:text], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}
यह बिलकुल सही नहीं है। आपको क्लाइंट को बताना चाहिए कि वे एक ऐसे प्रारूप का अनुरोध कर रहे हैं जिसका आप समर्थन नहीं करते हैं, ऐसा नहीं है कि आपको सही फ़ाइल नहीं मिल रही है।
अगर यह एक UnknownFormat
था त्रुटि, आप एक बेहतर प्रतिक्रिया कोड वापस कर सकते हैं। इसके बजाय, ये त्रुटियां अन्य, असंबंधित त्रुटियों के साथ मिल जाएंगी, और उन्हें संभालना वास्तव में कठिन होगा।
आप एक respond_to
जोड़ सकते हैं अपने index
. पर ब्लॉक करें क्रिया:
# 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
शॉर्टकट
यदि आप अपनी वस्तुओं को प्रस्तुत करने के लिए कुछ विशेष नहीं कर रहे हैं, तो आप एक शॉर्टकट ले सकते हैं। अगर आप लिखते हैं:
def index
@tasks = Task.all
respond_to :html, :json
end
यह उसी तरह काम करता है जैसे पूरा respond_to
. लिखना index
. में ब्लॉक करें . यह रेल को उन सभी प्रारूपों के बारे में बताने का एक छोटा तरीका है, जिनके बारे में आपकी कार्रवाई को पता है। और अगर अलग-अलग कार्रवाइयां अलग-अलग फ़ॉर्मैट का समर्थन करती हैं, तो बिना अधिक कोड के उन अंतरों को संभालने का यह एक अच्छा तरीका है।
नियंत्रक स्तर पर प्रारूपों को संभालें
आम तौर पर, हालांकि, आपके नियंत्रक में प्रत्येक क्रिया उसी . के साथ काम करेगी प्रारूप। अगर index
json
का जवाब देता है , तो new
होगा , और create
, और सब कुछ। तो अच्छा होगा यदि आपके पास respond_to
हो जो संपूर्ण नियंत्रक को प्रभावित करेगा:
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
. के साथ . तो इसके बजाय:
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
आप लिख सकते हैं:
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
मणि अपने साथ कुछ और अच्छी सुविधाएँ लाता है।
आप फ़्लैश संदेशों को respond_with
में सेट कर सकते हैं responders :flash
आपके नियंत्रक के शीर्ष पर:
class TasksController < ApplicationController
responders :flash
आसानी से, आप अपनी स्थानीय फ़ाइलों में इन फ़्लैश संदेशों के लिए डिफ़ॉल्ट सेट कर सकते हैं।
साथ ही, यदि आपके पास responders
है आपके Gemfile
. में मणि और आप एक रेल मचान उत्पन्न करते हैं, जनरेटर respond_with
. का उपयोग करके नियंत्रक बनाएगा respond_to
. के बजाय :
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
का उपयोग करें एक ब्लॉक के साथ, और आप अपनी इच्छानुसार प्रत्येक प्रारूप को संभाल सकते हैं।
इनमें से किसी के साथ, आपके द्वारा समर्थित प्रारूपों के अनुरोधों को सही त्रुटि मिलेगी। और आपका ऐप और उसके क्लाइंट दोनों बहुत कम भ्रमित होंगे।