web-dev-qa-db-fra.com

Rails: confusion sur la syntaxe pour passer des locaux aux partiels

Comprendre Rails "magique" en ce qui concerne le rendu des partiels (et leur passer des locaux).

Pourquoi ça marche:

<%= render "rabbits/form" %>

Et ce travail:

<%= render "rabbits/form", :parent => @warren, :flash => flash %>

mais cela fonctionne pas:

<%= render "rabbits/form", :locals => { :parent => @warren, :flash => flash } %>

Mais cela:

<%= render :partial =>"rabbits/form", :locals => { :parent => @warren, :flash => flash } %>

De plus, comment puis-je rechercher ces nuances pour ne pas avoir à déranger les gens sur S.O.?

98
Meltemi

La réponse courte est que la méthode de rendu examine le premier argument que vous passez. Si vous passez un hachage (qui inclut :partial => 'foo', :locals => {blah blah blah}), Il passera tous vos arguments en tant que hachage et les analysera en conséquence.

Si vous passez une chaîne comme premier argument, cela suppose que le premier argument est votre nom partiel et passera le reste en tant que vos sections locales. Cependant, lors de cet appel ultérieur, il affecte en fait :locals => your_locals_argument, Qui dans ce cas est l'intégralité de :locals => {locals hash}, Au lieu de simplement {locals hash}; c'est-à-dire que vous vous retrouvez avec :locals => {:locals => {locals hash}}, plutôt que :locals => {locals hash}.

Donc, mon conseil est juste de toujours passer explicitement les valeurs de la même manière tout le temps, et vous n'aurez pas de problèmes. Pour en savoir plus, je suis allé directement au code lui-même (actionpack/lib/base.rb, render() méthode dans Rails 2 ; Rails 3 est différent). C'est un bon exercice.

De plus, ne vous inquiétez pas de "déranger" les gens sur SO. C'est pourquoi ce site existe. J'ai même appris quelque chose de cela.

151
Doug R

si vous devez spécifier: locaux, vous devez spécifier: partiel ou: modèle

<%= render :partial => "rabbits/form", :locals => {...} %>

devrait marcher

5
sethvargo

Pour être honnête, je ne connais que ces cas d'utilisation, car j'ai suivi Rails au cours des deux dernières années et j'ai lu les annonces qu'une nouvelle façon de le faire a été ajoutée. J'y fais souvent moi-même une erreur, mais en général c'est facile à corriger.

C'est l'une de ces parties de l'API Rails qui n'a pas été bien pensée, si vous me demandez. Elle a simplement accumulé de plus en plus de sucre syntaxique au fil des ans, sans déprécier aucune La méthode de rendu est diabétique.

Pour le rendre encore pire, le rendu se comporte différemment dans le contrôleur et la vue. Je regarde également le contenu du premier argument pour voir s'il s'agit d'un fichier, d'un modèle, d'une action ou partiel. Si cela commence par une barre oblique, c'est un fichier, ou quelque chose comme ça.

Je suis en faveur de l'utilisation de la notation la plus courte dans la mesure du possible. Parce que les courtes notations communiquent assez bien l'intention. En le lisant, il fait généralement ce que vous pensez qu'il fait. L'écrire n'est pas si simple.

2
iain

Voici la source de la méthode de rendu de http://api.rubyonrails.org/classes/ActionView/Rendering.html#method-i-render :

def render(options = {}, locals = {}, &block)
  case options
  # Here is your last case
  when Hash
    if block_given?
      _render_partial(options.merge(:partial => options.delete(:layout)), &block)
    elsif options.key?(:partial)
      _render_partial(options)
    else
      template = _determine_template(options)
      lookup_context.freeze_formats(template.formats, true)
      _render_template(template, options[:layout], options)
    end
  when :update
    update_page(&block)
  else
    # here the first three cases
    _render_partial(:partial => options, :locals => locals)
  end
end

J'espère que cette aide!

1
Andrea Salicetti