कैसे रेल में ओवररोज करने के लिए ओवरराइड करें?


94

अपडेट करें:

इस मुद्दे को ठीक से नहीं खोजा गया था। असली मुद्दा भीतर है render :json

मूल प्रश्न में पहला कोड पेस्ट अपेक्षित परिणाम देगा। हालांकि, अभी भी एक चेतावनी है। इस उदाहरण को देखें:

render :json => current_user

के रूप में ही नहीं है

render :json => current_user.to_json

यही है, render :jsonस्वचालित रूप to_jsonसे उपयोगकर्ता ऑब्जेक्ट से जुड़ी विधि को कॉल नहीं करेगा । वास्तव में , यदि मॉडल to_jsonपर ओवरराइड किया जा रहा है , तो नीचे वर्णित वर्णन उत्पन्न करेगा ।Userrender :json => @userArgumentError

सारांश

# works if User#to_json is not overridden
render :json => current_user

# If User#to_json is overridden, User requires explicit call
render :json => current_user.to_json

यह सब मुझे मूर्खतापूर्ण लगता है। यह मुझे ऐसा प्रतीत हो रहा है जो renderवास्तव में कॉल नहीं कर रहा है Model#to_jsonजब प्रकार :jsonनिर्दिष्ट किया गया है। क्या कोई समझा सकता है कि वास्तव में यहाँ क्या हो रहा है?

कोई भी जिन्न जो मेरी मदद कर सकता है, वह मेरे अन्य प्रश्न का उत्तर दे सकता है: Rails में @ foo.to_json (विकल्प) और @ bar.to_json (विकल्प) को मिलाकर JSON प्रतिक्रिया कैसे बनाएं


मूल प्रश्न:

मैंने SO पर कुछ अन्य उदाहरण देखे हैं, लेकिन मैं वह नहीं कर रहा हूं जो मैं देख रहा हूं।

मैं कोशिश कर रहा हूँ:

class User < ActiveRecord::Base

  # this actually works! (see update summary above)
  def to_json
    super(:only => :username, :methods => [:foo, :bar])
  end

end

मैं हो रही है ArgumentError: wrong number of arguments (1 for 0)में

/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json

कोई विचार?


आपका उदाहरण मेरे एक मॉडल में काम करता है। से कुछ भी करें username, fooया barतरीकों तर्क उम्मीद करते हैं?
जोनाथन जूलियन 19

नहीं, usernameयह एक विधि नहीं है fooऔर barइसे विधियों की आवश्यकता नहीं है। मैंने अपना प्रश्न यह दिखाने के लिए अद्यतन किया कि त्रुटि कहाँ हो रही है।
माकक

मैं 1.8.7 चला रहा हूं। आपको उस फ़ाइल को खोलना होगा और देखना होगा कि यह एक विधि से एक arg पास क्यों है जो शून्य args की अपेक्षा करता है।
जोनाथन जूलियन

जवाबों:


214

आपको मिल रहा है ArgumentError: wrong number of arguments (1 for 0)क्योंकि to_jsonएक पैरामीटर, optionsहैश के साथ ओवरराइड करने की आवश्यकता है ।

def to_json(options)
  ...
end

की लंबी व्याख्या to_json, as_jsonऔर प्रतिपादन:

ActiveSupport 2.3.3 में, as_jsonआपके द्वारा सामना किए गए जैसे मुद्दों को संबोधित करने के लिए जोड़ा गया था। निर्माण json के से अलग होना चाहिए प्रतिपादन json की।

अब, कभी भी to_jsonकिसी ऑब्जेक्ट पर कॉल किया जाता है, as_jsonडेटा संरचना बनाने के लिए आह्वान किया जाता है, और फिर उस हैश को JSON स्ट्रिंग के रूप में एन्कोड किया जाता है ActiveSupport::json.encode। यह सभी प्रकारों के लिए होता है: ऑब्जेक्ट, न्यूमेरिक, दिनांक, स्ट्रिंग, आदि (ActiveSupport कोड देखें)।

ActiveRecord ऑब्जेक्ट्स उसी तरह व्यवहार करते हैं। एक डिफ़ॉल्ट as_jsonकार्यान्वयन है जो एक हैश बनाता है जिसमें सभी मॉडल की विशेषताएं शामिल होती हैं। आपको as_jsonअपने JSON संरचना को बनाने के लिए अपने मॉडल में ओवरराइड करना चाहिएas_jsonपुराने की तरह to_json, एक विकल्प हैश लेता है जहाँ आप विशेषताओं और विधियों को घोषित रूप से शामिल करने के लिए निर्दिष्ट कर सकते हैं।

def as_json(options)
  # this example ignores the user's options
  super(:only => [:email, :handle])
end

अपने नियंत्रक में, render :json => oएक स्ट्रिंग या एक वस्तु को स्वीकार कर सकते हैं। यदि यह एक स्ट्रिंग है, तो इसे प्रतिक्रिया निकाय के रूप में पारित किया जाता है, यदि यह एक वस्तु है, तो उसे to_jsonकहा जाता है, जो as_jsonऊपर बताए अनुसार चलाता है।

इसलिए, जब तक आपके मॉडल को as_jsonओवरराइड (या नहीं) के साथ ठीक से दर्शाया जाता है , तब तक एक मॉडल को प्रदर्शित करने के लिए आपका नियंत्रक कोड इस तरह दिखना चाहिए:

format.json { render :json => @user }

कहानी का नैतिक है: सीधे कॉल to_jsonसे बचें , आपके renderलिए ऐसा करने की अनुमति दें । यदि आपको JSON आउटपुट को ट्वीक करने की आवश्यकता है, तो कॉल करें as_json

format.json { render :json => 
    @user.as_json(:only => [:username], :methods => [:avatar]) }

@ जोनाथन जूलियन, यह एक बहुत ही उपयोगी व्याख्या है as_json। जैसा कि आप ActiveRecord में देख सकते हैं :: Serialization docs ( api.rubyonrails.org/classes/ActiveRecord/… ), इसके लिए बहुत कम (कोई) दस्तावेज नहीं है। मैं इसे
आजमाऊंगा

1
@ जोनाथन जूलियन, अगर मैं इस 10 बार मतदान कर सकता हूं, तो मैं करूंगा। जहां बिल्ली as_jsonडॉक्स हैं! धन्यवाद फिर से :)
maček

71

यदि आपके पास रेल 3 में इसके साथ समस्याएँ हैं, तो serializable_hashइसके बजाय ओवरराइड करें as_json। इससे आपकी XML फॉर्मेटिंग भी मुफ्त में हो जाएगी :)

पता लगाने के लिए इसने मुझे हमेशा के लिए मुझे लिया। आशा है कि किसी की मदद करता है।


1
क्या किसी को विधि के बारे में किसी भी अच्छे लेखन का पता है serializable_hash? जब मैं इसका उपयोग करता हूं, तो यह अपने नाम के साथ वस्तु को लपेटने से मेरे बाद के xml आउटपुट को बदल देता है (उदाहरण के लिए "एक उद्धरण वस्तु के लिए उद्धरण") इसके बजाय इसे हमेशा "<हैश>" के साथ लपेटें।
टायलर कोलियर

@ टायलरकोइलियर में वही विकल्प होना चाहिए जैसेto_xml
सैम सॉफ्स

इस समाधान के लिए धन्यवाद! मैं ruby2 / rails4 का उपयोग कर रहा हूं और as_json नेस्टेड ऑब्जेक्ट्स के साथ काम नहीं कर रहा था, ओवरराइड विधि को 'शामिल' में नहीं बुलाया गया था, यह serializable_hash के साथ काम करता है!
9

इस कारण की व्याख्या के लिए robots.thoughtbot.com/better-serialization-less-as-json देखें कि इसके बजाय serializable_hash को ओवरराइड क्यों किया जाना चाहिए।
टॉपर हंट

36

उन लोगों के लिए जो उपयोगकर्ताओं के विकल्पों को अनदेखा नहीं करना चाहते हैं, लेकिन वे भी जोड़ते हैं:

def as_json(options)
  # this example DOES NOT ignore the user's options
  super({:only => [:email, :handle]}.merge(options))
end

आशा है कि यह किसी को भी मदद करता है :)


1
इस तरह से मैं इसे कर रहा हूं, इसके अलावा मैं optionsहैश को डिफॉल्ट करता हूं, = {}इसलिए कॉल करते समय इसकी आवश्यकता नहीं होती है
मार्च

4

ओवरराइड नहीं करना to_json, लेकिन as_json। और as_json कॉल से आप क्या चाहते हैं:

इसे इस्तेमाल करे:

def as_json 
 { :username => username, :foo => foo, :bar => bar }
end

as_jsonसिर्फ ActiveResource के लिए नहीं है ?
जोनाथन जूलियन

जाहिर तौर पर ActiveRecord :: Serialization में as_json api.rubyonrails.org/classes/ActiveRecord/Serialization.html
glebm

@glebm, मैंने यह कोशिश की और मुझे वही परिणाम मिल रहा है। मैंने आपको दिखाने के लिए अपना प्रश्न अपडेट किया।
माकक

@glebm, मुझे अभी भी वही त्रुटि मिल रही है। यहां तक ​​कि जब मैं करता render :json => current_userहूं मुझे अपेक्षित डिफ़ॉल्ट परिणाम मिलता है ( UserJSON प्रारूप में मॉडल के सभी गुण )। जब मैं as_jsonअपने Userमॉडल में विधि जोड़ता हूं और एक ही चीज की कोशिश करता हूं, तो मुझे त्रुटि मिलती है :(
maček

@glebm, धन्यवाद। मुझे पता है कि मैं कुछ गलत कर रहा था। यह अद्यतन किए गए प्रश्न की जाँच के लायक हो सकता है।
20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.