5

मुझे पता है कि दृश्य टेम्पलेट्स (एचटीएमएल, रैबल) का उपयोग करते समय, मुझे अपने नियंत्रक कार्रवाई में एक स्पष्ट रेंडर कॉल की आवश्यकता नहीं है क्योंकि डिफ़ॉल्ट रूप से, रेल टेम्पलेट को नियंत्रक क्रिया नाम से संबंधित नाम के साथ प्रस्तुत करता है। मुझे इस अवधारणा को पसंद है (मेरे नियंत्रक कोड में प्रतिपादन की परवाह नहीं है) और इसलिए आश्चर्य है कि यह ActiveModel :: Serializers का उपयोग करते समय भी संभव है?क्या ActiveModel :: Serializer को एक स्पष्ट रेंडर कॉल की आवश्यकता है?

उदाहरण के लिए, यह एक उत्पन्न नियंत्रक से कोड है (4.1.0 रेल):

class ProductsController < ApplicationController 
    before_action :set_product, only: [:show, :edit, :update, :destroy] 

    #other actions 
    # GET /products/1 
    # GET /products/1.json 
    def show 
    end 
end 

और इस serializer है:

class ProductSerializer < ActiveModel::Serializer 
    attributes :id, :name, :description, :url, :quantity, :price 
end 

/products/1.json साधते, मैं करूंगा उम्मीद दो बातें होती हैं करने के लिए:

  1. फील्ड्स serializer में सूचीबद्ध नहीं ommited किया जाना है,
  2. पूरे JSON ऑब्जेक्ट को 'उत्पाद' शीर्ष स्तर फ़ील्ड में शामिल किया जाना है।

हालांकि, ऐसा नहीं होता है, पूरे धारावाहिक को अनदेखा किया जाता है। लेकिन फिर अगर मैं निम्नलिखित को दिखाएँ विधि को संशोधित:

# GET /products/1 
# GET /products/1.json 
def show 
    @product = Product.find(params[:id]) 
    respond_to do |format| 
    format.html 
    format.json { render json: @product } 
    end 
end 

और अब यह सब ठीक है, लेकिन मैं before_action फिल्टर के लाभ को खो दिया है (और यह है कि मैं कुछ बेमानी कोड है मुझे लगता है)।

यह वास्तव में कैसे किया जाना चाहिए?

+0

@zmilojko क्या आपने ['respond_with'] (http://api.rubyonrails.org/classes/ActionController/MimeResponds.html#method-i-respond_with) का उपयोग करने का प्रयास किया है? मुझे लगता है कि 'respond_with (@product)' आपको बिल्कुल वही नहीं मिलेगा जो आप चाहते हैं। ['ActiveModel :: Serializer' README से उदाहरण] (https://github.com/rails-api/active_model_serializers#render-json)। –

+0

@PaulFioravanti लेकिन यह वह नहीं है जो मैं बाद में हूं। मैं खाली रहने के लिए 'शो' विधि चाहूंगा क्योंकि रेल 4 जनरेटर इसे बनाता है, लेकिन अभी भी प्रश्न में परिभाषित सीरियलज़र का उपयोग करने में सक्षम होने के लिए (और जेबिल्डर नहीं, क्योंकि ऐसा लगता है कि रेल पसंद करेंगे)। – zmilojko

+0

@zmilojko क्या यह एक सीधी रेल 4.1 ऐप है? या एक रेल-एपीआई ऐप? आप अपने ऐप की प्रारंभिक स्थिति कैसे बना रहे हैं? – noel

उत्तर

0

'अनावश्यक कोड' हम एक दूसरे में देखते हैं, केवल इस पंक्ति है:

@product = Product.find(params[:id])

और मुझे विश्वास है कि यह आपके before_action रूप में एक ही तर्क है। आपको इस लाइन की आवश्यकता नहीं है, बस इसे हटा दें। अब डुप्लिकेशंस हटा दिया गया है।

शेष भाग में। एक कार्रवाई को जानने की जरूरत है कि क्या प्रस्तुत करना है। डिफ़ॉल्ट रूप से यदि कार्रवाई खाली या अनुपस्थित है, तो संबंधित 'action_name'.html.erb (और respond_to द्वारा निर्दिष्ट अन्य प्रारूप) को देखा और प्रस्तुत किया जाएगा।

यही कारण है कि रेल 4 जनरेटर ने काम किया है: यह show.html.erb और show.json.jbuilder बनाता है जो प्रदान किया जाता है।

ActiveModel::Serializer के साथ, आपके पास कोई टेम्पलेट नहीं है। यदि आप कार्रवाई को खाली छोड़ देते हैं, तो इसमें कोई संकेत नहीं है कि प्रस्तुत करना क्या है। इस प्रकार आप, json के रूप में @product रेंडर करने के लिए यह बताने की आवश्यकता या तो द्वारा:

render json: @product

या

respond_with @product

+0

लेकिन मेरा लक्ष्य डुप्लिकेट लाइन को हटाना नहीं था, लेकिन बाकी बाकी। मैं खाली रहने के लिए 'शो' विधि चाहता हूं और अभी भी सीरिएलाइज़र का आह्वान करता हूं। ऐसा लगता है कि काम नहीं कर रहा है, पूरे ActiveModel प्रतिपादन: Serializer बेकार। – zmilojko

0

बिना एक स्पष्ट render या respond_with या respond_to रेल उससे मिलते-जुलते टेम्पलेट के लिए दिखेगा । यदि वह टेम्पलेट मौजूद नहीं है तो रेल एक त्रुटि फेंकता है।

हालांकि, आप इसे बाईपास करने के लिए अपना स्वयं का संकल्प बना सकते हैं।

class SerializeResolver < ActionView::Resolver 
    protected 
    def find_templates(name, prefix, partial, details) 
    if details[:formats].to_a.include?(:json) && prefix !~ /layout/ 
     instance = prefix.to_s.singularize 
     source = "<%= @#{instance}.active_model_serializer.new(@#{instance}).to_json.html_safe %>" 
     identifier = "SerializeResolver - #{prefix} - #{name}" 
     handler = ActionView::Template.registered_template_handler(:erb) 
     details = { 
     format: Mime[:json], 
     updated_at: Date.today, 
     virtual_path: "/#{normalize_path(name, prefix)}" 
     } 
     [ActionView::Template.new(source, identifier, handler, details)] 
    else 
     [] 
    end 
    end 

    def normalize_path(name, prefix) 
    prefix.present? ? "#{prefix}/#{name}" : name 
    end 
end 

और फिर, में या तो अपने आवेदन नियंत्रक (या एक व्यक्ति के नियंत्रक में) जगह:

append_view_path ::SerializeResolver.new 

कि के साथ आप में सक्षम होना चाहिए उदाहरण के लिए, आप app\models\serialize_resolver.rb बनाया है और यह में डाल लगता है जो करना चाहते हैं उसे करने के लिए। यदि यह एक जेसन अनुरोध है, तो यह सही सामग्री के साथ एक erb टेम्पलेट बना देगा और इसे वापस कर देगा।

सीमाएं:

  • इसका कारण यह है कि यह ERB है, जो की जरूरत नहीं है पर निर्भर करता है थोड़ा भद्दा है। यदि मेरे पास समय है तो मैं एक साधारण टेम्पलेट हैंडलर बनाउंगा। फिर हम बिना किसी क्रिया के आह्वान कर सकते हैं।
  • यह डिफ़ॉल्ट json प्रतिक्रिया को मिटा देता है।
  • यह नियंत्रक नाम पर निर्भर करता है उदाहरण चर खोजने के लिए (/posts@post में बदल जाती है।)
  • मैं केवल इस एक छोटे से परीक्षण किया है। तर्क शायद चालाक हो सकता है।

नोट्स: एक टेम्पलेट मौजूद है

  • हैं, तो यह पहली बार उपयोग किया जाएगा। यह आपको इस व्यवहार को ओवरराइड करने की अनुमति देता है।
  • आप बस एक नया रेंडरर नहीं बना सकते हैं और इसे पंजीकृत नहीं कर सकते हैं, क्योंकि डिफ़ॉल्ट प्रक्रिया इसे हिट नहीं करती है। यदि टेम्पलेट नहीं मिला है, तो आपको एक त्रुटि मिलती है। अगर फ़ाइल पाई जाती है, तो यह सीधे टेम्पलेट हैंडलर का आह्वान करने के लिए जाती है।
+0

मैंने इस उत्तर को बनाने के लिए जोस वैलीम की पुस्तक 'क्राफ्टिंग रेल' से कुछ कोड दोहराया। – noel

+0

हम्म, मैं अपने कोड को सरल बनाने के लिए एक समाधान की तलाश में था, यह काफी विपरीत है। मुझे लगता है कि jbuilder दृष्टिकोण जीतता है, और ActiveModel: Serializer बस इतना उपयोगी नहीं है ... – zmilojko

+0

आप यह कह सकते हैं। लेकिन यह केवल एक बार किया जाना है। – noel

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

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