2011-01-13 36 views
5

Rails uygulamasında XML Oluşturucu şablonu (rxml) şablonu ve render_to_string kullanarak bir XML belgesi oluşturan bir eylemim var. XML belgesi bir arka uç sunucusuna iletilir.render_to_string kullandıktan sonra normal görünüm nasıl oluşturulur?

XML belgesini oluşturduktan sonra tarayıcıya normal bir HTML yanıtı göndermek istiyorum, ancak her nasılsa Rails ilk aramayı render_to_string olarak hatırlıyor. Örneğin

: Bir show.rxml arar çünkü

  • Raylar varsayılan görünümü show.html.erb bulamıyorum.
  • Eylem işleyicimin alt kısmına bir render 'mycontroller/show.html.erb' koymanız, Rails'in şablonu bulmasını sağlar, ancak yanıt başlığının içerik türü text/xml olduğundan tarayıcı çalışmaz.

Gerçek tarayıcı yanıtı "lekelenmeden" render_to_string'u kullanmanın bir yolu var mı?

DÜZENLEME: Rails 2 erase_render_results'da hile yapacağı görülüyor, ancak Rails 3'te artık mevcut değil.

+0

Aslında 'erase_render_results' false için bir bayrak ayarlar ve response_body öğesini siler - render_to_string kaynağında içerik türü açıkça sıfır olarak ayarlanır. Bu, karşılaştığınız sorunun neden kaynaklandığı gibi görünüyor. –

cevap

2

Pragmatik yanıt, bir görüntüleme dosyası ve görüntülenmek üzere iki çağrının kullanılmasıdır. Rails Yolu değil: Görünümler genellikle istemciye gönderilen bir şeydir ve ActionPack bu şekilde çalışmak üzere tasarlanmıştır.

Yaptığınız şeyi başarmanın kolay bir yolu var demişti. Aksine ActionView kullanmak yerine, bir dize olarak XML'inizi oluşturmak için doğrudan Builder :: XmlMarkup kullanabilirsiniz:

def action_in_controller 
    buffer = "" 
    xml = Builder::XmlMarkup.new(buffer) 

    # build your XML - essentially copy your view.xml.builder file here 
    xml.element("value") 
    xml.element("value") 

    # send the contents of buffer to your 3rd server 

    # allow your controller to render your view normally 
end 

nasıl çalıştığını görmek için the Builder documentation göz at.

Oluşturucunun kullanabileceği diğer bir özelliği de, XML içeriğinin << kullanarak arabelleğe eklenmesidir, böylece herhangi bir IO akışı kullanılabilir. İçeriği diğer sunucuya nasıl gönderdiğine bağlı olarak, hepsini oldukça güzel bir şekilde sarabilirsiniz.

Elbette, bu çok dağınık ve uzun sürebilir, bu nedenle bu biraz işlevselliği başka bir sınıfta veya modelinizde bir yöntem olarak kapsüllemek isteyebilirsiniz.

+1

Sorun, XML verilerinin normal bir görünüm olarak da mevcut olması gerektiğidir, bu yüzden tavsiyenizi izleyerek kodu çoğaltmak anlamına gelir (benim durumumda) Bununla birlikte, yaptığım şey budur, teşekkür ederim. –

2

Bu, raylar 3'te bir hata olabilir (en azından 2.3.x render_to_string davranışına kıyasla). source for 2.3.8'da, content_type'ı sıfırlamak ve yanıt gövdesini sıfırlamak (diğer şeylerin yanı sıra) için ekstra adımlar atıyorlar. AbstractController::Rendering

def render_to_string(*args, &block) 
    options = _normalize_args(*args, &block) 
    _normalize_options(options) 
    render_to_body(options) 
end 

Sen değişkenlerin açık bir sıfırlama yoktur görebilirsiniz için

def render_to_string 
    ... 
ensure 
    response.content_type = nil 
    erase_render_results 
    reset_variables_added_to_assigns 
end 

ama 3.0.3 kaynakta

, render_to_body sadece view_context.render döndürür. Vb içerik tipi, response_body, başka yerde ele alınmasını mevcuttur ve bu bir kırmızı ringa, ama benim ilk içgüdüsü aslında render önce senin render_to_string sonra

response.headers['Content-Type'] = 'text/html'

ayarlamak olacaktır.

2

actionwebservice gem taşınırken aynı hatayla karşılaştım. Kodlarında, erase_render_results işlevini çağırarak çift render istisnasını atlatırlar.

Bu işlev artık raylarda3 kullanılamaz. Neyse ki düzeltme oldukça kolay (ama bulmak için biraz zaman aldı). Aşağıdaki fonksiyonu actionwebservice İçinde

ikinci işlemek izin vermek için bir denetleyici içinde çağrıldı:

def reset_invocation_response 
    self.instance_variable_set(:@_response_body, nil) 
    response.instance_variable_set :@header, Rack::Utils::HeaderHash.new("cookie" => [], 'Content-Type' => 'text/html') 
end 

Umut bu yardımcı olur:

def reset_invocation_response 
    erase_render_results 
    response.instance_variable_set :@header, Rack::Utils::HeaderHash.new(::ActionController::Response::DEFAULT_HEADERS.merge("cookie" => [])) 
end 

raylar 3. bu işi yapmak için, sadece yazmak zorunda .

+0

+ 1 son derece yararlı, 5 internets olsun! –

İlgili konular