Układy Rails na akcję?

165

Używam innego układu dla niektórych akcji (głównie dla nowej akcji w większości kontrolerów).

Zastanawiam się, jaki byłby najlepszy sposób określenia układu? (Używam 3 lub więcej różnych układów w tym samym kontrolerze)

Nie lubię używać

render: layout => 'name'

Lubiłem robić

„nazwa” układu,: only => [: new]

Ale nie mogę tego użyć do określenia 2 lub więcej różnych układów.

Na przykład:

Kiedy wywołuję układ 2 razy w tym samym kontrolerze, z różnymi nazwami układu i różnymi tylko opcjami, pierwsza z nich jest ignorowana - te akcje nie są wyświetlane w określonym przeze mnie układzie.

Uwaga: używam Rails 2.

mrbrdo
źródło
1
Dokumentacja przewodników Rails: guide.rubyonrails.org/…
Kevin
1
Słuszna uwaga. Dokumentacja dla Rails 2: guide.rubyonrails.org/v2.3.11/…
Kevin
2
(Opublikowałem także przewodnik, aby pomóc przyszłym czytelnikom. Nie wątpię, że Twój problem został rozwiązany dawno temu ;-)
Kevin,

Odpowiedzi:

297

Możesz użyć metody, aby ustawić układ.

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
źródło
22
Fajne dzięki. A jeśli ktoś chce zrobić prostsze rzeczy z jedną linijką, możliwe jest to. Jest łatwy do odczytania i umieszczony w górnej części kontrolera. ---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
holli
1
Czy miałoby to duży wpływ na wydajność aplikacji, gdyby różne układy używały, powiedzmy, kilku różnych plików css i js?
Noz
15
-1: Zbyt złożone. Poniższy komentarz ( stackoverflow.com/a/21203783/285154 ) jest najlepszą opcją.
dimitarvp
Dzięki! Jest to wciąż problem w Railsach 4.2, być może tylko wtedy, gdy używasz dziedziczących kontrolerów na wielu poziomach. Używałem metody wcześniej, ale nie myślałem o testowaniu tego, kiedy miałem teraz problem, jeszcze raz dziękuję.
244an
@dimitko nie, nie jest, wspomniałem już o tym rozwiązaniu w samym pytaniu. Nie działa, jeśli chcesz użyć 3 lub więcej różnych układów (tak jak jest dokładnie w moim przypadku).
mrbrdo
201

Jeśli wybierasz tylko jeden z dwóch układów, możesz użyć :only:

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

lub

class ProductsController < ApplicationController
   layout "application", only: [:index]
end
axeltaglia
źródło
2
Cóż, problem polega na tym, że nie można uzyskać dostępu do obiektów, takich jak current_user, w celu warunkowego określenia układu
Andrew K,
@AndrewK Dynamiczne wybieranie układu nie wydaje się być częścią zadawanego pytania.
Nick
11
Gdyby ktoś z Was przeczytał pytanie, wiedziałby, że to nie jest właściwa odpowiedź, ponieważ opisałem już to rozwiązanie w samym pytaniu i dlaczego nie działa w moim przypadku (3 lub więcej układów).
mrbrdo
2
Jak powiedział mrbrdo, to nie jest odpowiedź. Jego pytanie konkretnie wskazuje (I am using 3 or more different layouts in the same controller). Ta odpowiedź pozwala na układ i brak układu, a nie różne układy.
Michael
49

Możesz określić układ dla indywidualnej akcji za pomocą respond_to :

  def foo
    @model = Bar.first
    respond_to do |format|
      format.html {render :layout => 'application'}
    end
  end
Gavin Terrill
źródło
Dla mnie jest to bardziej elastyczna odpowiedź. SUSZENIE rzeczy przez zastosowanie 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 renderowania i / lub przekierowania było wywoływane wiele razy w tej akcji; i nie masz innego wyjścia, jak skorzystać z tej sugestii.
Jerome,
1
Ta odpowiedź jest najlepsza, jest prosta i zgrabna w przeciwieństwie do używania metod z przełącznikiem lub instrukcjami if w środku.
kev
może również określić plik erb i układ zarówno: format.html { render 'custom_index', layout: 'application' } w ten sam sposób.
thatway_3
12

Możesz również określić układ akcji za pomocą renderowania:

def foo
  render layout: "application"
end
yottanami
źródło
7

Różne sposoby określenia układu pod kontrolerem:

  1. W poniższym kodzie układ application_1 jest wywoływany pod indeksem, a akcja show kontrolera Users, a układ aplikacji (układ domyślny) jest wywoływany dla innych akcji.

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. W poniższym kodzie układ application_1 jest wywoływany dla wszystkich akcji kontrolera Users.

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. W poniższym kodzie układ application_1 jest wywoływany tylko dla akcji testowej kontrolerów Users, a dla wszystkich innych akcji układ aplikacji (domyślny).

        class UsersController < ApplicationController
          def test
            render layout: "application_1"
          end
        end
puneet18
źródło
5

Precyzja:

Nie bardzo, ale działający SUCHY sposób jest tym, co widzisz powyżej, ale z precyzją: układ musi być zgodny z twoimi zmiennymi do pracy ("@some"). Tak jak :

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

I nie :

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

Jeśli zrobisz przed zadziałaniem ... to też nie zadziała.

Mam nadzieję, że to pomoże.

Gregdebrick
źródło