Schienenlayouts pro Aktion?

165

Ich verwende für einige Aktionen ein anderes Layout (hauptsächlich für die neue Aktion in den meisten Controllern).

Ich frage mich, wie ich das Layout am besten festlegen kann. (Ich verwende 3 oder mehr verschiedene Layouts in demselben Controller.)

Ich benutze es nicht gerne

render: layout => 'name'

Ich habe es gern gemacht

Layout 'Name' ,: nur => [: neu]

Aber ich kann das nicht verwenden, um zwei oder mehr verschiedene Layouts anzugeben.

Beispielsweise:

Wenn ich das Layout zweimal im selben Controller mit unterschiedlichen Layoutnamen und unterschiedlichen Optionen aufrufe, wird der erste ignoriert - diese Aktionen werden in dem von mir angegebenen Layout nicht angezeigt.

Hinweis: Ich verwende Rails 2.

mrbrdo
quelle
1
Die Rails Guides Dokumentation : guides.rubyonrails.org/…
Kevin
1
Guter Punkt. Die Dokumentation für Rails 2 : guides.rubyonrails.org/v2.3.11/…
Kevin
2
(Außerdem habe ich den Leitfaden veröffentlicht, um zukünftigen Lesern zu helfen. Ich habe keinen Zweifel, dass Sie Ihr Problem vor langer Zeit gelöst haben ;-)
Kevin

Antworten:

297

Sie können eine Methode verwenden, um das Layout festzulegen.

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
quelle
22
Cool, danke. Und falls jemand einfachere Dinge mit Einzeiler machen möchte, ist Folgendes möglich. Es ist einfach zu lesen und oben auf dem Controller zu platzieren. ---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
Holli
1
Würde dies einen großen Einfluss auf die Anwendungsleistung haben, wenn verschiedene Layouts beispielsweise mehrere unterschiedliche CSS- und JS-Dateien verwenden?
Noz
15
-1: Zu komplex. Der folgende Kommentar ( stackoverflow.com/a/21203783/285154 ) ist die beste Option.
dimitarvp
Vielen Dank! Dies ist in Rails 4.2 immer noch ein Problem, möglicherweise nur, wenn Sie erbende Controller in vielen Ebenen verwenden. Ich habe die Methode schon einmal verwendet, dachte aber nicht daran, sie zu testen, als ich das Problem hatte, nochmals vielen Dank.
244an
@dimitko nein ist es nicht, ich habe diese Lösung bereits in der Frage selbst erwähnt. Es funktioniert nicht, wenn Sie 3 oder mehr verschiedene Layouts verwenden möchten (genau wie in meinem Fall).
Mrbrdo
201

Wenn Sie nur zwischen zwei Layouts auswählen, können Sie Folgendes verwenden :only:

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

oder

class ProductsController < ApplicationController
   layout "application", only: [:index]
end
Axeltaglia
quelle
2
Nun, das Problem dabei ist, dass Sie nicht auf Objekte wie current_user zugreifen können, um das Layout bedingt zu bestimmen
Andrew K
@AndrewK Die dynamische Auswahl eines Layouts scheint nicht Teil der gestellten Frage zu sein.
Nick
11
Wenn einer von Ihnen die Frage liest, weiß er, dass dies nicht die richtige Antwort ist, da ich diese Lösung bereits in der Frage selbst beschrieben habe und auch, warum sie in meinem Fall nicht funktioniert (3 oder mehr Layouts).
Mrbrdo
2
Wie Herr Brdo sagte, ist dies nicht die Antwort. Seine Frage zeigt ausdrücklich (I am using 3 or more different layouts in the same controller). Diese Antwort erlaubt ein Layout und kein Layout, keine unterschiedlichen Layouts.
Michael
49

Sie können das Layout für eine einzelne Aktion mit reply_to angeben :

  def foo
    @model = Bar.first
    respond_to do |format|
      format.html {render :layout => 'application'}
    end
  end
Gavin Terrill
quelle
Für mich ist dies die flexiblere Antwort. Das Austrocknen von Dingen durch Anwenden von Rendern 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 und / oder Umleiten wurde in diesen Aktionsfehlern mehrmals aufgerufen. und Sie haben keine andere Wahl, als diesen Vorschlag zu verwenden.
Jerome
1
Diese Antwort ist die beste, sie ist einfach und ordentlich im Gegensatz zur Verwendung von Methoden mit switch oder if-Anweisungen.
Kev
es kann auch die erb-Datei und das Layout beide angeben: format.html { render 'custom_index', layout: 'application' } auf die gleiche Weise.
thatway_3
12

Sie können das Layout für die Aktion auch mithilfe von Rendern angeben:

def foo
  render layout: "application"
end
Yottanami
quelle
7

Verschiedene Möglichkeiten, das Layout unter dem Controller festzulegen:

  1. Im folgenden Code wird das Layout application_1 unter index und show action des Users Controllers aufgerufen, und das Anwendungslayout (Standardlayout) wird für andere Aktionen aufgerufen.

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. Im folgenden Code wird das Layout application_1 für alle Aktionen des Users-Controllers aufgerufen.

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. Im folgenden Code wird das Layout application_1 nur für Testaktionen der Benutzercontroller und für alle anderen Aktionen aufgerufen. Das Anwendungslayout (Standard) wird aufgerufen.

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

Präzision:

Ein nicht wirklich, aber trockener Weg ist das, was Sie oben sehen, aber mit einer Präzision: Das Layout muss nach Ihren Variablen sein, damit es funktioniert ("@some"). Wie :

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

Und nicht :

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

Wenn Sie eine before_action ausführen, funktioniert dies auch nicht.

Ich hoffe es hilft.

Gregdebrick
quelle