2012-04-09 22 views
5

से तर्क के साथ एक नियंत्रक कार्रवाई को बुला रहा है क्या कोई तरीका है कि मैं मिडलवेयर से नियंत्रक एक्शन कॉल के लिए एक तर्क पारित कर सकता हूं?रैक मिडलवेयर

यह यहाँ है कि इस कार्रवाई

# in middleware 
# 
def call(env) 
    env['action_controller.instance'].class.action(:print_name).call(env) 
end 

निश्चित रूप से यह ArgumentError को जन्म देती है कहता है मेरी मिडलवेयर से कोड है नियंत्रक कोड

# in my_controller.rb 
# 
def print_name(name) 
    render :text => "Hello, #{name}!" 
end 

में कार्रवाई है।

मुझे पता नहीं है कि मैं action कॉल पर तर्क कैसे दे सकता हूं। यहां स्रोत है:

# in action_pack/lib/action_controller/metal.rb 
# 
def self.action(name, klass = ActionDispatch::Request) 
     middleware_stack.build(name.to_s) do |env| 
     new.dispatch(name, klass.new(env)) 
     end 
end 

जैसा कि आप देख सकते हैं, यह प्रदान की गई नियंत्रक कार्रवाई से एक रैक एंडपॉइंट देता है। मुझे कोई रास्ता नहीं दिखता है कि मैं यहां एक तर्क पारित कर सकता हूं।

मैंने class_eval के साथ गतिशील रूप से नियंत्रक को बदल दिया और फिर उस प्रॉक्सी विधि से नियंत्रक विधि को कॉल कर दिया।

# in middleware 
# 
def define_proxy_method(klass) 
     klass.class_eval do 
      def call_the_real_method 
       print_name(request.env['fake_attribute']) 
      end 
     end 
end 

def call(env) 
    define_proxy_method(env['action_controller.instance'].class) 
    env['fake_attrbute'] = "Yukihiro" 
    env['action_controller.instance'].class.action(:call_the_real_method).call(env) 
end 

यह गंदा लगता है और मैं बेहतर तरीके से जानना चाहता हूं। धन्यवाद।

+1

वहाँ मिला है जो कुछ भी आप कर रहे हैं के लिए एक बेहतर दृष्टिकोण होने के लिए करने का प्रयत्न। यदि आप आखिरकार पूरा करने की कोशिश कर रहे हैं, तो अधिक संदर्भ प्रदान कर सकते हैं, शायद एक बहुत कम हैकी समाधान है। –

+0

अपवाद को फेंकने के बाद मैं एक विशिष्ट नियंत्रक कार्रवाई पर रीडायरेक्ट करने का प्रयास कर रहा हूं। असल में यह एक [फिक्स] है (एयरग्रेक मणि के लिए https://github.com/airbrake/airbrake/commit/e13041bf9c69527b9bb34043617e52b6c7615657)। मिडलवेयर से कंट्रोलर विधि को कॉल करने का उदाहरण ढूंढना काफी मुश्किल था। हालांकि, टिप्पणी के लिए धन्यवाद। – shime

उत्तर

4

आप अपनी कार्रवाई पर तर्क डालना नहीं चाहते हैं। मिडलवेयर केवल अनुरोध पर्यावरण से बातचीत करनी चाहिए, सीधे नियंत्रक में कॉल करने का प्रयास न करें।

आप पैरामीटर हैश में समान मान पारित कर सकते हैं:

# middleware 
# 
def call(env) 
    request = Rack::Request.new(env) 
    request['name'] = get_name 
end 

और नियंत्रक में पैरामीटर हैश से पढ़ें:

# my_controller.rb 
# 
def print_name 
    render :text => "Hello, #{params['name']}!" 
end 
+0

हाँ, मैंने देखा कि यह करने का गलत तरीका है। इसे रेल 2.x के लिए इस तरह कार्यान्वित किया गया था, क्योंकि इसमें 'actionController' परिभाषित 'बचाव_action_in_public (अपवाद)' था, और यह विधि इसे अलियासिंग कर रही थी। मैं विधि कॉल को बदलने के बिना, रेल 3.x के लिए एक ही व्यवहार को लागू करने की कोशिश कर रहा था। हालांकि आपके उत्तर के लिए धन्यवाद -> स्वीकार, अपवित्र और बक्षीस :) – shime

+0

धन्यवाद। जीमेल या ग्चैट पर winfield.peterson पर मुझे ई-मेल करने के लिए आपका स्वागत है। आप अपने अपवाद हैंडलिंग/रिपोर्टिंग को एक सहायक वर्ग में निकालने में सक्षम हो सकते हैं और इसे मिडलवेयर और नियंत्रकों दोनों में उपयोग कर सकते हैं। यदि इसमें नियंत्रक-विशिष्ट रीडायरेक्ट तर्क या अन्य सामान हैं जो आप इसे ब्लॉक में डाल सकते हैं? एक पूर्ण समाधान पर लूप बंद करने के लिए खुश है। – Winfield

संबंधित मुद्दे