रेल 3: अजाक्स कॉल में "पुनर्निर्देशन" कैसे करें?


85

attempt_loginलॉगिन फॉर्म जमा करने के बाद अजाक्स का उपयोग करते हुए निम्नलिखित विधि को कहा जाता है।

class AccessController < ApplicationController
  [...]
  def attempt_login
    authorized_user = User.authenticate(params[:username], params[:password])

    if authorized_user
      session[:user_id] = authorized_user.id
      session[:username] = authorized_user.username
      flash[:notice] = "Hello #{authorized_user.name}."
      redirect_to(:controller => 'jobs', :action => 'index')
    else
      [...]
    end
  end
end

समस्या यह है कि redirect_toकाम नहीं करता है।

आप इसे कैसे हल करेंगे?

जवाबों:


102

अंत में, मैंने अभी प्रतिस्थापित किया

redirect_to(:controller => 'jobs', :action => 'index')

इसके साथ:

render :js => "window.location = '/jobs/index'"

और यह ठीक काम करता है!


43
एक बेहतर तरीका होगाrender :js => "window.location = '#{jobs_path}'"
ज़ाक्लाफ़स्सी

3
यह काम करता है, लेकिन यह एक वास्तविक json सफलता संदेश के साथ रीडायरेक्ट स्थान को वापस पास करने के लिए बहुत बेहतर नहीं होगा और फ्रंट छोर पर रीडायरेक्ट करना है?
justinxreese

1
jobs_pathमूल रूप से URL के रूप में कठोर नहीं है ? यदि URL बदलता है, तो मार्ग का नाम तब तक होगा, जब तक कि आप अतिरिक्त सावधानी नहीं बरतते। एक अन्य विकल्प render js: "window.location = '#{polymorphic_path(@job.class)}'"जॉब मॉडल के आधार पर गणना किए गए संसाधन मार्ग का उपयोग और होगा । यह केवल तभी काम करता है जब आपके मार्ग संसाधनपूर्ण हों और मानक नामकरण परंपराओं का उपयोग करें जो आपके मॉडलों के साथ मेल खाती हैं। (या यदि आप अपने मॉडलों पर model_name निर्दिष्ट करते हैं ताकि वे सही मार्ग नाम उत्पन्न करें।)
smudge

2
बहुत बढ़िया। किसी को भी कोई भी विचार है कि सरल रीडायरेक्ट_टो क्यों काम नहीं करता है?
तसोस अनीसादिस

1
@Tasos Anesiadis, redirect_to तब काम नहीं करता है जब फ़ॉर्म एक 'रिमोट' रेल्स रूप होता है क्योंकि ब्राउज़र को जावास्क्रिप्ट से नियंत्रक की प्रतिक्रिया की व्याख्या करने के लिए कहा गया है। आप Chrome DevTools के रिस्पॉन्स टैब (नेटवर्क पैनल के माध्यम से) में redirect_to पेज देख सकते हैं, लेकिन इसके बजाय ब्राउज़र से एक अलग पेज खोजने के लिए नियंत्रक से एक निर्देश है। यहां दिए गए विंडो.लोकेशन सॉल्यूशंस, या फॉर्म को एक नियमित 'स्थानीय' फॉर्म में बदलने की आवश्यकता होती है, जब तक कि आप फॉर्म डेटा को भ्रूण () और JSON के माध्यम से मैन्युअल रूप से सबमिट और प्रोसेस नहीं करना चाहते हैं।
एमएससी

67

अगले अनुरोध के लिए फ्लैश रखने का बहुत आसान तरीका है। अपने कंट्रोलर में कुछ ऐसा करें

flash[:notice] = 'Your work was awesome! A unicorn is born!'
flash.keep(:notice)
render js: "window.location = '#{root_path}'"

यह flash.keepसुनिश्चित करेगा कि फ्लैश अगले अनुरोध के लिए रखा गया है। इसलिए जब root_pathइसका प्रतिपादन किया जाता है, तो यह दिए गए फ्लैश संदेश को दिखाएगा। रेलें कमाल की हैं :)


27

मुझे लगता है कि यह थोड़ा अच्छा है:

render js: "window.location.pathname='#{jobs_path}'"


12
थोड़ा सा अच्छा:render js: "window.location.pathname = #{jobs_path.to_json}"
tokland

26

मेरे एक ऐप में, मैं JSON का उपयोग रीडायरेक्ट और फ्लैश मैसेज डेटा पर ले जाने के लिए करता हूं। यह कुछ इस तरह दिखेगा:

class AccessController < ApplicationController
  ...
  def attempt_login
    ...
    if authorized_user
      if request.xhr?
        render :json => {
          :location => url_for(:controller => 'jobs', :action => 'index'),
          :flash => {:notice => "Hello #{authorized_user.name}."}
        }
      else
        redirect_to(:controller => 'jobs', :action => 'index')
      end
    else
      # Render login screen with 422 error code
      render :login, :status => :unprocessable_entity
    end
  end
end

और सरल jQuery का उदाहरण होगा:

$.ajax({
  ...
  type: 'json',
  success: functon(data) {
    data = $.parseJSON(data);
    if (data.location) {
      window.location.href = data.location;
    }
    if (data.flash && data.flash.notice) {
      // Maybe display flash message, etc.
    }
  },
  error: function() {
    // If login fails, sending 422 error code sends you here.
  }
})

1
यहाँ अच्छी जानकारी के बहुत सारे। रेंडर का अच्छा और उचित उपयोग: स्थान, का: स्थिति विकल्प, और xhr? जाँच। चूंकि अधिक वेब एप्लिकेशन मोबाइल एप्लिकेशन और इस तरह से सेवा करने के लिए एपीआई को अपनाते हैं, मुझे उम्मीद है कि इस पोस्ट में चीजें अधिक मानकीकृत हो जाएंगी। निश्चित रूप से मेरा उत्थान है। शानदार उत्तर
TheJKFever

18

सभी उत्तरों का सबसे अच्छा संयोजन:

...
if request.xhr?
  flash[:notice] = "Hello #{authorized_user.name}."
  flash.keep(:notice) # Keep flash notice around for the redirect.
  render :js => "window.location = #{jobs_path.to_json}"
else
...

आपके उत्तर के लिए धन्यवाद, मैंने इसका उपयोग किया। हालाँकि, अब परीक्षण के लिए, जब मैं JS के रूप में इस क्रिया का अनुरोध करने का प्रयास करता हूँ, तो यह एक CORS चेतावनी देता है: ActionController :: InvalidCrossOriginRequest। क्या आपके पास कोई विचार है कि इसे परीक्षणों में कैसे एकीकृत किया जाए?
वी। देहाय

1
def redirect_to(options = {}, response_status = {})
  super(options, response_status)
  if request.xhr?
    # empty to prevent render duplication exception
    self.status = nil
    self.response_body = nil
    path = location
    self.location = nil

    render :js => "window.location = #{path.to_json}"
  end
end

0

मैं अपने नियंत्रक कार्यों को संशोधित नहीं करना चाहता था इसलिए मैं इस हैक के साथ आया:

class ApplicationController < ActionController::Base
  def redirect_to options = {}, response_status = {}
    super

    if request.xhr?
      self.status        = 200
      self.response_body = "<html><body><script>window.location.replace('#{location}')</script></body></html>"
    end
  end
end
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.