2011-03-23 21 views
10

Estoy tratando de tener una respuesta JSON en el que algún valor es HTML representado por un parcialJSON no puede encontrar otra html parcial

#projects_Controller.rb 

def index 
    respond_to do |f| 
    f.json 
    end 
end 

# index.json.erb 

    { 
    "html":"<%= raw escape_javascript(render :partial => 'projects/disclaimer') %>" 
    } 

pero me da el siguiente error:

ActionView::Template::Error (Missing partial projects/disclaimer with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=> 
    [:json], :locale=>[:en, :en]} in view paths "c:/rails/app/views", "c:/rails/vendor/plugins/more/app/views", "C:/Ruby192/lib/ruby/gems/1.9.1/gems/devise-1.1.8/app/views") 

Parece que JSON solicita renderizaciones parciales con .json.erb en su nombre, pero no con .html.erb, que es lo que tengo. ¿Hay alguna manera de especificar "html"?

añadido: Si la solicitud es 'js', y en index.js.erb que hacen que el casi mismo código: # index.js.erb

disclaimer = { 
    "html":"<%= raw escape_javascript(render :partial => 'projects/disclaimer') %>" 
    } 

lo hace encontrar los proyectos/descargo de responsabilidad .html.erb y lo renderiza correctamente. Me pregunto por qué hay tal inconsistencia en que si uno solicita js, cualquier representación parcial en su plantilla buscará partial_name.html.erb, pero si se solicita json, la representación parcial solicitaría partial_name.json.erb?

Gracias

Respuesta

13

¡Gracias: Todo lo que necesitas es esta línea en el archivo .json.erb <% self.formats = [ "html"]%>

Así que la index.json.erb completa

 <% self.formats = ["html"] %> 
     disclaimer = { 
     "html":"<%= raw escape_javascript(render :partial => 'projects/disclaimer', 
        :content_type => 'text/html'), 
        :locals => {:localVariable => @localVariable} 
       %>" 
     } 
+5

Este enfoque también funciona desde dentro de un controlador que está renderizando JSON; Configuro 'self.formats = [: html]', luego 'render_to_string (: partial => 'an_html_partial',: locals => {: whatever => whatever})', y luego puedo renderizar json fine. – alxndr

+0

En caso de que también tenga otros parciales json, es posible que desee hacer 'self.formats + = [: html]' en su lugar. –

0

no estoy seguro de si te tengo bien, pero tal vez se puede jugar con el tipo de contenido como esto:

disclaimer = { 
    "html":"<%= raw escape_javascript(render :partial => 'projects/disclaimer', :content_type => 'text/html'), :locals => {:localVariable => @localVariable} %>" 
} 

Los lugareños: es sólo por si desea pasar una var al parcial.

+0

No, no, creo que tienes razón en el dinero: se le pide a los carriles para servir JSON, así que cualquier cosa que sirve, incluyendo cualquier renders tendrá que ser JSON no html.erb. así que cuando pido un partial.html.erb dentro de la respuesta, arroja un error que dice que partial.JSON.erb no se encuentra. Lo extraño es, si pido .js (JSONP?) En el encabezado, lo que significa que los rieles deben servir a todos los parciales en el final de .js.erb, pero esta vez, no le importaría servir .html.erb y no dirá no se encuentra Esa es una incoherencia en mi opinión .... Pero después de agregar el: content_type => 'text/html', aún arroja el mismo error –

5

Mi respuesta es similar a la anterior de Nik. Tengo el siguiente ayudante para las plantillas json.erb:

# helpers useful for json.erb templates 
module JsonHelper 

    # Same as render but force actionview to look for html templates instead of json. 
    def render_html(options={}, locals={}, &block) 
    old_formats = formats 
    self.formats = [:html] # hack so partials resolve with html not json format 
    render options, locals, &block 

    ensure 
    self.formats = old_formats 
    end 

    # json escape a string. For example <%=json "some { string }" %> 
    def json(value) 
    raw value.to_json 
    end 
end 

Así que ahora puedo escribir como plantillas

{ 
    "html": <%=json render_html(:partial => 'some_partial') %>, 
    "status": success 
} 

Esta sería mejor si ActionView permitió la representación con un content_type al igual que en el ejemplo de 23tux (que doesn no funciona para mí). También sería mejor si solo * .html.erb se sometiera a html escaping en lugar de todos los archivos * .erb.

1

Para futuros lectores, puede pasar parámetros como este.

= render partial: 'user', locals: {xyz: @xyz}, :formats => [:html]