Disposition des rails par action?

165

J'utilise une disposition différente pour certaines actions (principalement pour la nouvelle action dans la plupart des contrôleurs).

Je me demande quelle serait la meilleure façon de spécifier la mise en page? (J'utilise 3 mises en page différentes ou plus dans le même contrôleur)

Je n'aime pas utiliser

render: layout => 'nom'

J'aimais faire

layout 'name',: only => [: new]

Mais je ne peux pas utiliser cela pour spécifier 2 ou plusieurs mises en page différentes.

Par exemple:

Lorsque j'appelle la mise en page 2 fois dans le même contrôleur, avec des noms de mise en page différents et des options uniquement différentes, la première est ignorée - ces actions ne s'affichent pas dans la mise en page que j'ai spécifiée.

Remarque: j'utilise Rails 2.

mrbrdo
la source
1
La documentation des guides Rails: guides.rubyonrails.org
Kevin
1
Bon point. La documentation pour Rails 2: guides.rubyonrails.org/v2.3.11/…
Kevin
2
(Aussi, j'ai posté le guide pour aider les futurs lecteurs. Je n'ai aucun doute que votre problème a été résolu il y a longtemps ;-)
Kevin

Réponses:

297

Vous pouvez utiliser une méthode pour définir la mise en page.

class MyController < ApplicationController
  layout :resolve_layout

  # ...

  private

  def resolve_layout
    case action_name
    when "new", "create"
      "some_layout"
    when "index"
      "other_layout"
    else
      "application"
    end
  end
end
August Lilleaas
la source
22
Cool merci. Et au cas où quelqu'un voudrait faire des choses plus simples avec une seule ligne, ce qui suit est possible. Il est facile à lire et à placer en haut du contrôleur. ---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
holli
1
Cela aurait-il un effet important sur les performances de l'application si diverses mises en page utilisent respectivement plusieurs fichiers css et js différents?
Noz
15
-1: Trop complexe. Le commentaire ci-dessous ( stackoverflow.com/a/21203783/285154 ) est la meilleure option.
dimitarvp
Merci! C'est toujours un problème dans Rails 4.2, peut-être seulement si vous utilisez des contrôleurs héréditaires à plusieurs niveaux. J'ai utilisé la méthode avant, mais je ne pensais pas à tester cela quand j'ai eu le problème maintenant, merci encore.
244
@dimitko non ce n'est pas le cas, j'ai déjà référencé cette solution dans la question elle-même. Cela ne fonctionne pas si vous souhaitez utiliser 3 mises en page différentes ou plus (comme c'est exactement mon cas).
mrbrdo
201

Si vous ne sélectionnez qu'entre deux mises en page, vous pouvez utiliser :only:

class ProductsController < ApplicationController
   layout "admin", only: [:new, :edit]
end

ou

class ProductsController < ApplicationController
   layout "application", only: [:index]
end
axeltaglia
la source
2
Eh bien, le problème avec ceci est que vous ne pouvez pas accéder à des objets tels que current_user pour déterminer conditionnellement la mise en page
Andrew K
@AndrewK Choisir dynamiquement une mise en page ne semble pas faire partie de la question posée.
Nick
11
Si l'un d'entre vous lisait la question, vous saurez que ce n'est pas la bonne réponse, car j'ai déjà décrit cette solution dans la question elle-même et aussi pourquoi cela ne fonctionne pas dans mon cas (3 mises en page ou plus).
mrbrdo
2
Comme l'a dit mrbrdo, ce n'est pas la réponse. Sa question l'indique spécifiquement (I am using 3 or more different layouts in the same controller). Cette réponse permet une mise en page et aucune mise en page, pas des mises en page différentes.
Michael
49

Vous pouvez spécifier la disposition d'une action individuelle à l'aide de respond_to :

  def foo
    @model = Bar.first
    respond_to do |format|
      format.html {render :layout => 'application'}
    end
  end
Gavin Terrill
la source
Pour moi, c'est la réponse la plus flexible. Le séchage des choses en appliquant le layout "[...]" to the controller class only allows one statement effectively. If you have more than two layouts to deal with (say, admin, generic_app, tailored_app), you will experience rendu et / ou la redirection était appelé plusieurs fois dans les erreurs de cette action; et vous n'avez pas d'autre choix que d'utiliser cette suggestion.
Jerome
1
Cette réponse est la meilleure, elle est simple et soignée par opposition à l'utilisation de méthodes avec interrupteur ou instructions if à l'intérieur.
kev
il peut également spécifier le fichier erb et la disposition à la fois: format.html { render 'custom_index', layout: 'application' } de la même manière.
thatway_3
12

Vous pouvez également spécifier la disposition de l'action à l'aide du rendu:

def foo
  render layout: "application"
end
yottanami
la source
7

Différentes manières de spécifier la disposition sous le contrôleur:

  1. Dans le code suivant, la mise en page application_1 est appelée sous index et l'action show du contrôleur Utilisateurs et la mise en page de l'application (mise en page par défaut) est appelée pour d'autres actions.

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. Dans le code suivant, la disposition application_1 est appelée pour toutes les actions du contrôleur Utilisateurs.

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. Dans le code suivant, la disposition application_1 est appelée pour l'action de test des contrôleurs Utilisateurs uniquement et pour toutes les autres actions, la disposition d'application (par défaut) est appelée.

        class UsersController < ApplicationController
          def test
            render layout: "application_1"
          end
        end
puneet18
la source
5

Précision :

Une manière DRY pas vraiment mais qui fonctionne est ce que vous voyez ci-dessus, mais avec une précision: la mise en page doit être après vos variables pour fonctionner ("@some"). Comme:

def your_action
   @some = foo
   render layout: "your_layout"
end

Et pas :

def your_action
   render layout: "your_layout"
   @some = foo
   @foo = some
end

Si vous faites une before_action ... cela ne fonctionnera pas non plus.

J'espère que ça aide.

Gregdebrick
la source