web-dev-qa-db-fra.com

Comment rendre une partie d'un format différent dans Rails?

J'essaie de générer une réponse JSON qui inclut du HTML. Ainsi, j'ai /app/views/foo/bar.json.erb:

{
  someKey: 'some value',
  someHTML: "<%= h render(:partial => '/foo/baz') -%>"
}

Je veux qu'il rende /app/views/foo/_baz.html.erb, mais il ne rendra que /app/views/foo/_baz.json.erb. Qui passe :format => 'html' n'aide pas.

112
James A. Rosen

En me basant sur réponse de roninek , j'ai trouvé la meilleure solution comme suit:

dans /app/helpers/application.rb:

def with_format(format, &block)
  old_format = @template_format
  @template_format = format
  result = block.call
  @template_format = old_format
  return result
end

Dans /app/views/foo/bar.json:

<% with_format('html') do %>
  <%= h render(:partial => '/foo/baz') %>
<% end %>

Une autre solution serait de redéfinir render pour accepter un :format paramètre.

Je ne pouvais pas avoir render :file travailler avec la population locale et sans chemin de ronde.

29
James A. Rosen

Commençant par Rails 3.2.3, lors de l’appel de render: partial (fonctionne uniquement en dehors du respond_to bloc).

:formats => [:html]

au lieu de

:format => 'html'
99
Tim Haines

Quel est le problème avec

render :partial => '/foo/baz.html.erb'

? J'ai juste essayé de rendre un ERB HTML partiel de l'intérieur d'un gabarit de générateur Atom) et tout fonctionnait bien. Aucun problème avec les variables globales requises (ouais, je sais qu'ils ont "@" en face de eux, mais c’est ce qu’ils sont).

Votre with_format &block approche est cool cependant et présente l’avantage de ne spécifier que le format, alors que l’approche simple spécifie également le moteur de template (ERB/​​builder/etc).

64
Sam Stokes

Pour Rails 3, le bloc with_format fonctionne, mais c'est un peu différent:

  def with_format(format, &block)
    old_formats = formats
    self.formats = [format]
    block.call
    self.formats = old_formats
    nil
  end
32
zgchurch

Rails 4 vous permettra de passer un paramètre de format. Donc tu peux faire

render(:partial => 'form', :formats => [:html])} 

Notez que vous pouvez faire quelque chose de similaire dans Rails 3 mais il ne passera pas ce format à aucun sous-partials (si le formulaire appelle d'autres partials).

Vous pouvez avoir la capacité Rails 4 dans Rails 3 en créant config/initializers/renderer.rb:

class ActionView::PartialRenderer
  private
  def setup_with_formats(context, options, block)
    formats = Array(options[:formats])
    @lookup_context.formats = formats | @lookup_context.formats
    setup_without_formats(context, options, block)
  end

  alias_method_chain :setup, :formats
end

Voir http://railsguides.net/2012/08/29/Rails3-does-not-render-partial-for-specific-format/

31
DrewB

Dans Rails 3, la vue contient un tableau de formats, ce qui signifie que vous pouvez le configurer pour rechercher [: mobile,: html]. Ce paramètre sera utilisé par défaut pour rechercher des modèles pour mobile, mais tomber de nouveau à: modèles html.

La meilleure façon, mais toujours imparfaite, que je pouvais trouver pour régler cela était de placer cette ligne en haut de chaque modèle mobile complet (mais pas les partiels).

<% self.formats = [:mobile, :html] %>

Le défaut est que vous devez ajouter cette ligne à plusieurs modèles. Si quelqu'un connaît un moyen de définir cela une fois, à partir de application_controller.rb, j'aimerais le savoir. Malheureusement, il ne fonctionne pas d'ajouter cette ligne à votre mise en page mobile, car les modèles sont rendus avant la mise en page.

25
Tony Stubblebine

Expliquant simplement ce que zgchurch a écrit:

  • prise en compte des exceptions
  • renvoyer le résultat du bloc appelé

Pensé que cela pourrait être utile.

def with_format(format, &block)
  old_formats = formats
  begin
    self.formats = [format]
    return block.call
  ensure
    self.formats = old_formats
  end
end
16
viphe

Vous avez deux options:

1) utiliser render :file

render :file => "foo/_baz.json.erb"

2) changer le format de template en HTML en définissant la variable @template_format

<% @template_format = "html" %>
<%= h render(:partial => '/foo/baz') %>
9
roninek

J'avais un fichier nommé 'api/item.rabl' et je voulais le rendre à partir d'une vue HTML, donc je devais utiliser:

render file: 'api/item', formats: [:json]

(file parce que le nom du fichier ne comporte pas de trait de soulignement, formats et non format (et passe et tableau))

5
Dorian

Il semble que passer par une option formats la rendra correctement dans les versions plus récentes Rails version, au moins 3.2:

{
  someKey: 'some value',
  someHTML: "<%= h render('baz', formats: :html) -%>"
}
2
Mario Uher

Je suis tombé sur ce fil lorsque j'essayais de rendre un partiel XML dans un autre fichier de vue xml.builder. Voici une bonne façon de le faire

xml.items :type => "array" do
    @items.each do |item|
        xml << render(:partial => 'shared/partial.xml.builder', :locals => { :item => item })
    end
end

Et oui ... Le nom complet du fichier fonctionne ici aussi ...

1
Garfield