Ruby on Rails
ActionController
खोज…
परिचय
एमवीसी में एक्शन कंट्रोलर सी है। राउटर ने यह निर्धारित करने के बाद कि किस नियंत्रक को अनुरोध के लिए उपयोग करना है, नियंत्रक अनुरोध की समझ बनाने और आउटपुट का उत्पादन करने के लिए जिम्मेदार है।
नियंत्रक अनुरोध प्राप्त करेगा, एक मॉडल से डेटा प्राप्त करेगा या सहेजेगा और आउटपुट बनाने के लिए एक दृश्य का उपयोग करेगा। एक नियंत्रक को मॉडल और विचारों के बीच एक बिचौलिया के रूप में सोचा जा सकता है। यह मॉडल डेटा को दृश्य के लिए उपलब्ध कराता है ताकि यह उपयोगकर्ता को प्रदर्शित कर सके, और यह उपयोगकर्ता डेटा को मॉडल में सहेजता है या अपडेट करता है।
HTML के बजाय आउटपुट JSON
class UsersController < ApplicationController def index hashmap_or_array = [{ name: "foo", email: "[email protected]" }] respond_to do |format| format.html { render html: "Hello World" } format.json { render json: hashmap_or_array } end end end
इसके अलावा आपको मार्ग की आवश्यकता होगी:
resources :users, only: [:index]
यह /users
से अनुरोध करने के दो अलग-अलग तरीकों से प्रतिक्रिया देगा:
- यदि आप
/users
या/users.html
, तो यह सामग्रीHello World
साथ एक html पृष्ठ दिखाएगा - यदि आप
/users.json
पर/users.json
, तो यह JSON ऑब्जेक्ट प्रदर्शित करेगा:
[ { "name": "foo", "email": "[email protected]" } ]
आप format.html { render inline: "Hello World" }
को छोड़ सकते हैं format.html { render inline: "Hello World" }
यदि आप यह सुनिश्चित करना चाहते हैं कि आपका मार्ग केवल JSON अनुरोधों का जवाब देगा।
नियंत्रकों (मूल)
class UsersController < ApplicationController def index respond_to do |format| format.html { render html: "Hello World" } end end end
यह एक मूल नियंत्रक है, जिसमें निम्न मार्ग (मार्गों में शामिल हैं ।rb):
resources :users, only: [:index]
जब आप URL /users
एक्सेस करते हैं तो एक वेबपेज में Hello World
संदेश प्रदर्शित करेगा
पैरामीटर
नियंत्रकों की पहुंच HTTP मापदंडों तक होती है (आप उन्हें URL के रूप में जानते हैं ?name=foo
URLs में, लेकिन रूबी ऑन रेल्स विभिन्न स्वरूपों को भी संभालते हैं!) और उनके आधार पर विभिन्न प्रतिक्रियाओं का उत्पादन करते हैं। GET और POST मापदंडों के बीच अंतर करने का कोई तरीका नहीं है, लेकिन आपको किसी भी मामले में ऐसा नहीं करना चाहिए।
class UsersController < ApplicationController
def index
respond_to do |format|
format.html do
if params[:name] == "john"
render html: "Hello John"
else
render html: "Hello someone"
end
end
end
end
end
हमेशा की तरह हमारा मार्ग:
resources :users, only: [:index]
URL /users?name=john
तक पहुंचें /users?name=john
और आउटपुट Hello John
, एक्सेस /users?name=whatever
और आउटपुट Hello someone
फ़िल्टरिंग पैरामीटर (मूल)
class UsersController < ApplicationController def index respond_to do |format| format.html do render html: "Hello #{ user_params[:name] } user_params[:sentence]" end end end private def user_params if params[:name] == "john" params.permit(:name, :sentence) else params.permit(:name) end end end
आप कुछ पैरामेट्स की अनुमति दे सकते हैं (या अस्वीकार कर सकते हैं), ताकि आप जो चाहते हैं, केवल वही पास हो और आपको खराब आश्चर्य न हो जैसे उपयोगकर्ता सेटिंग विकल्प को बदलना नहीं है।
विजिटिंग /users?name=john&sentence=developer
Hello john developer
/users?name=john&sentence=developer
को प्रदर्शित करेगा, हालांकि विजिटिंग /users?name=smith&sentence=spy
केवल Hello smith
को प्रदर्शित करेगा, क्योंकि :sentence
की अनुमति केवल तब होती है जब आप john
रूप में एक्सेस करते हैं
पुन: निर्देशित
मार्ग मानकर:
resources :users, only: [:index]
आप किसी भिन्न URL का उपयोग करके पुनर्निर्देशित कर सकते हैं:
class UsersController def index redirect_to "http://stackoverflow.com/" end end
आप उपयोग किए गए उपयोगकर्ता के पिछले पृष्ठ पर वापस जा सकते हैं:
redirect_to :back
ध्यान दें कि रेल 5 में पुनर्निर्देशन के लिए वाक्यविन्यास अलग है:
redirect_back fallback_location: "http://stackoverflow.com/"
जो पिछले पृष्ठ पर पुनर्निर्देशित करने की कोशिश करेगा और संभव नहीं होने पर (ब्राउज़र HTTP_REFERRER शीर्ष लेख को अवरुद्ध कर रहा है), यह पुनर्निर्देशित करेगा :fallback_location
दृश्यों का उपयोग करना
मार्ग मानकर:
resources :users, only: [:index]
और नियंत्रक:
class UsersController < ApplicationController def index respond_to do |format| format.html { render } end end end
दृश्य app/users/index.html.erb
प्रदान किया जाएगा। यदि दृश्य है:
Hello <strong>World</strong>
आउटपुट पाठ के साथ एक वेबपेज होगा: "हैलो वर्ल्ड "
यदि आप एक अलग दृश्य प्रस्तुत करना चाहते हैं, तो आप उपयोग कर सकते हैं:
render "pages/home"
और इसके बजाय फ़ाइल app/views/pages/home.html.erb
का उपयोग किया जाएगा।
आप नियंत्रक उदाहरण चर का उपयोग करके विचारों को चर पास कर सकते हैं:
class UsersController < ApplicationController def index @name = "john" respond_to do |format| format.html { render } end end end
और फ़ाइल app/views/users/index.html.erb
आप @name
उपयोग कर सकते हैं:
Hello <strong><%= @name %></strong>
और आउटपुट होगा: "हेलो जॉन "
रेंडर सिंटैक्स के चारों ओर एक महत्वपूर्ण नोट, आप render
सिंटैक्स को पूरी तरह से छोड़ सकते हैं, रेल मानती है कि यदि आप इसे छोड़ देते हैं। इसलिए:
class UsersController < ApplicationController def index respond_to do |format| format.html { render } end end end
इसके बजाय लिखा जा सकता है:
class UsersController < ApplicationController def index respond_to do |format| format.html end end end
रेल काफी स्मार्ट है यह पता लगाने के लिए कि उसे फ़ाइल app/views/users/index.html.erb
को प्रस्तुत करना होगा।
404 जब रिकॉर्ड नहीं मिला
अपवाद या श्वेत पृष्ठ दिखाने के बजाय रिकॉर्ड से बचाव में त्रुटि नहीं मिली:
class ApplicationController < ActionController::Base
# ... your other stuff here
rescue_from ActiveRecord::RecordNotFound do |exception|
redirect_to root_path, 404, alert: 'Record not found'
end
end
बेसिक रेस्ट कंट्रोलर
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
@posts = Post.all
end
def show
end
def new
@post = Post.new
end
def edit
end
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to @post.company, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_post
@post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :body, :author)
end
end
अपवादों के लिए त्रुटि पृष्ठ प्रदर्शित करें
यदि आप सरल "सॉरी, कुछ गलत हो गया" के बजाय अपने उपयोगकर्ताओं को सार्थक त्रुटियों को प्रदर्शित करना चाहते हैं, तो रेल का उद्देश्य के लिए एक अच्छी उपयोगिता है।
फ़ाइल app/controllers/application_controller.rb
खोलें app/controllers/application_controller.rb
और आपको इस तरह से कुछ ढूंढना चाहिए:
class ApplicationController < ActionController::Base protect_from_forgery with: :exception end
विशिष्ट त्रुटियों से उबरने के लिए हम अब एक rescue_from
जोड़ सकते हैं:
class ApplicationController < ActionController::Base protect_from_forgery with: :exception rescue_from ActiveRecord::RecordNotFound, with: :record_not_found private def record_not_found render html: "Record <strong>not found</strong>", status: 404 end end
यह सलाह दी जाती है कि Exception
या StandardError
से बचाव न करें अन्यथा रेल त्रुटियों के मामले में सहायक पृष्ठ प्रदर्शित नहीं कर पाएंगे।
फिल्टर
फिल्टर एक विधि कार्रवाई के "पहले", "बाद" या "आसपास" चलाए जाने वाले तरीके हैं। वे विरासत में मिले हैं, इसलिए यदि आप अपने ApplicationController
में कोई भी सेट करते हैं तो वे आपके अनुरोध को प्राप्त करने वाले हर अनुरोध के लिए चलाए जाएंगे।
फ़िल्टर करने से पहले
नियंत्रक कार्रवाई से पहले फ़िल्टर निष्पादित किए जाते हैं और अनुरोध (और / या पुनर्निर्देशित) को रोक सकते हैं। यदि उपयोगकर्ता लॉग इन है तो एक सामान्य उपयोग यह सत्यापित करना है:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
def authenticate_user!
redirect_to some_path unless user_signed_in?
end
end
नियंत्रक की कार्रवाई के लिए अनुरोध मिलने से पहले फ़िल्टर अनुरोधों पर चलाए जाते हैं। यह स्वयं एक प्रतिक्रिया लौटा सकता है और कार्रवाई को पूरी तरह से बायपास कर सकता है।
फ़िल्टर से पहले के अन्य सामान्य उपयोग उनके अनुरोध को संभालने के लिए निर्दिष्ट कार्रवाई तक पहुंच प्रदान करने से पहले उपयोगकर्ता के प्रमाणीकरण को मान्य कर रहे हैं। मैंने उन्हें डेटाबेस से एक संसाधन को लोड करने, एक संसाधन पर अनुमतियों की जांच करने, या अन्य परिस्थितियों में पुनर्निर्देशन का प्रबंधन करने के लिए उपयोग करते हुए भी देखा है।
फ़िल्टर के बाद
फ़िल्टर के बाद "पहले" के समान हैं, लेकिन जैसा कि वे कार्रवाई चलाने के बाद निष्पादित हो जाते हैं, उनके पास प्रतिक्रिया ऑब्जेक्ट का उपयोग होता है जिसे भेजा जाना है। तो संक्षेप में कार्रवाई पूरा होने के बाद फिल्टर चलाए जाते हैं। यह प्रतिक्रिया को संशोधित कर सकता है। ज्यादातर समय अगर किसी चीज को आफ्टर फिल्टर में किया जाता है, तो उसे एक्शन में ही किया जा सकता है, लेकिन अगर किसी भी क्रिया को चलाने के बाद उसे चलाने के लिए कुछ तर्क दिए जाते हैं, तो एक फिल्टर करने के लिए एक अच्छी जगह है यह।
आमतौर पर, मैंने लॉगिंग के लिए उपयोग किए जाने वाले फ़िल्टर के बाद और उसके आसपास देखा है।
फ़िल्टर के आसपास
कार्रवाई चलाने से पहले और बाद में फ़िल्टर के पास तर्क हो सकते हैं। यह केवल उस जगह तक कार्रवाई करता है जो आवश्यक हो। ध्यान दें कि उसे कार्रवाई करने के लिए उपज की आवश्यकता नहीं है और एक पहले के फिल्टर की तरह ऐसा किए बिना चल सकता है।
रैक के बिचौलिये कैसे काम करते हैं, इसके हिसाब से फ़िल्टरिंग से संबंधित क्रियाओं को चलाने के लिए जिम्मेदार होते हैं।
कॉलबैक में चारों ओर क्रियाओं का निष्पादन होता है। आप दो अलग-अलग शैलियों में कॉलबैक के आसपास लिख सकते हैं। पहले में, कॉलबैक कोड का एक एकल हिस्सा है। कार्रवाई निष्पादित होने से पहले उस कोड को कहा जाता है। यदि कॉलबैक कोड उपज को आमंत्रित करता है, तो कार्रवाई निष्पादित होती है। जब कार्रवाई पूरी हो जाती है, तो कॉलबैक कोड निष्पादित करना जारी रखता है। इस प्रकार, उपज से पहले का कोड एक्शन कॉलबैक की तरह है और उपज के बाद का कोड एक्शन कॉलबैक है। यदि कॉलबैक कोड कभी उपज को आमंत्रित नहीं करता है। कार्रवाई नहीं चल रही है-यह एक कॉलबैक रिटर्न झूठी होने से पहले की कार्रवाई के समान है।
यहाँ फ़िल्टर के आसपास का एक उदाहरण दिया गया है:
around_filter :catch_exceptions
private
def catch_exceptions
begin
yield
rescue Exception => e
logger.debug "Caught exception! #{e.message}"
end
end
यह किसी भी कार्रवाई के अपवाद को पकड़ लेगा और आपके लॉग में संदेश डाल देगा। आप अपवाद हैंडलिंग, सेटअप और फाड़ के लिए फ़िल्टर और अन्य मामलों के असंख्य उपयोग कर सकते हैं।
केवल और सिवाय
सभी फ़िल्टर विशिष्ट कार्यों पर लागू किए जा सकते हैं, :only
:except
और :except
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update]
# ... controller actions
# Define your filters as controller private methods
private
def set_product
@product = Product.find(params[:id])
end
end
स्किपिंग फ़िल्टर
सभी फ़िल्टर (कुछ भी विरासत में मिले) को कुछ विशिष्ट कार्यों के लिए छोड़ दिया जा सकता है:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
def authenticate_user!
redirect_to some_path unless user_signed_in?
end
end
class HomeController < ApplicationController
skip_before_action :authenticate_user!, only: [:index]
def index
end
end
जैसा कि उन्हें विरासत में मिला है, फ़िल्टर को एक namespace
"मूल" नियंत्रक में भी परिभाषित किया जा सकता है। उदाहरण के लिए कहें कि आपके पास एक admin
नाम स्थान है, और आप निश्चित रूप से केवल उपयोगकर्ताओं को ही इसे एक्सेस करने में सक्षम होना चाहते हैं। आप ऐसा कुछ कर सकते हैं:
# config/routes.rb
namespace :admin do
resources :products
end
# app/controllers/admin_controller.rb
class AdminController < ApplicationController
before_action :authenticate_admin_user!
private
def authenticate_admin_user!
redirect_to root_path unless current_user.admin?
end
end
# app/controllers/admin/products_controller.rb
class Admin::ProductsController < AdminController
# This controller will inherit :authenticate_admin_user! filter
end
खबरदार रेल में 4.x कि आप इस्तेमाल कर सकते हैं before_filter
के साथ before_action
, लेकिन before_filter
वर्तमान में रेल 5.0.0 में हटा दिया गया है और 5.1 में निकाल दिया जाएगा।
एक नियंत्रक उत्पन्न करना
नियंत्रकों के लिए, बहुत सारे जनरेटर प्रदान करते हैं, बेशक।
आप अपने ऐप फ़ोल्डर में इस कमांड को चलाकर एक नया कंट्रोलर उत्पन्न कर सकते हैं
rails generate controller NAME [action action] [options]
नोट: आप rails generate
करने के लिए rails generate
rails g
अलियास का भी उपयोग कर सकते हैं
उदाहरण के लिए, #index
और #show
क्रियाओं के साथ एक Product
मॉडल के लिए एक नियंत्रक उत्पन्न करने के लिए, जो आप चलाएंगे
rails generate controller products index show
यह आपके द्वारा निर्दिष्ट दोनों क्रियाओं के साथ app/controllers/products_controller.rb
में कंट्रोलर बनाएगा
class ProductsController < ApplicationController
def index
end
def show
end
end
यह app/views/
अंदर एक products
फ़ोल्डर भी बनाएगा, जिसमें आपके नियंत्रक के कार्यों के लिए दो टेम्पलेट होंगे (जैसे index.html.erb
और show.html.erb
, ध्यान दें कि एक्सटेंशन आपके टेम्पलेट इंजन के अनुसार भिन्न हो सकता है, इसलिए यदि आप slim
का उपयोग कर रहे हैं, उदाहरण के लिए, जनरेटर index.html.slim
और show.html.slim
बनाएगा )
इसके अलावा, यदि आपने कोई कार्य निर्दिष्ट किया है तो वे आपके routes
फ़ाइल में भी जोड़े जाएंगे
# config/routes.rb
get 'products/show'
get 'products/index'
रेल आपके लिए app/helpers/products_helper.rb
, और साथ ही app/assets/javascripts/products.js
और app/assets/stylesheets/products.css
में एसेट फाइल बनाती है। दृश्यों के लिए, जनरेटर आपके Gemfile
में निर्दिष्ट किए गए अनुसार इस व्यवहार को Gemfile
: यानी, यदि आप अपने आवेदन में Coffeescript
और Sass
का उपयोग कर रहे हैं, तो कंट्रोलर जनरेटर जनरेटर products.coffee
और products.sass
Coffeescript
।
अंत में, लेकिन कम से कम, रेल आपके नियंत्रक, आपके सहायक और आपके विचारों के लिए परीक्षण फ़ाइलें भी नहीं बनाता है।
यदि आप नहीं चाहते हैं कि इनमें से कोई भी आपके लिए बनाया जाए, तो आप रेल को उन्हें छोड़ने के लिए कह सकते हैं, बस किसी भी विकल्प के साथ प्रस्तुत करें
--no-
या --skip
, इस तरह:
rails generate controller products index show --no-assets --no-helper
और जनरेटर assets
और helper
दोनों को छोड़ देगा
यदि आपको किसी विशिष्ट namespace
लिए एक नियंत्रक बनाने की आवश्यकता है, तो उसे NAME
सामने जोड़ें:
rails generate controller admin/products
इससे app/controllers/admin/products_controller.rb
अंदर आपका कंट्रोलर बन जाएगा
रेल भी आपके लिए एक पूर्ण RESTful नियंत्रक उत्पन्न कर सकती है:
rails generate scaffold_controller MODEL_NAME # available from Rails 4
rails generate scaffold_controller Product
ActiveRecord को बचाया :: RecordNotFound को redirect_to के साथ
आप एक त्रुटि पृष्ठ दिखाने के बजाय एक रीडायरेक्ट के साथ RecordNotFound अपवाद को छुड़ा सकते हैं:
class ApplicationController < ActionController::Base
# your other stuff
rescue_from ActiveRecord::RecordNotFound do |exception|
redirect_to root_path, 404, alert: I18n.t("errors.record_not_found")
end
end