Layout delle rotaie per azione?


165

Uso un layout diverso per alcune azioni (principalmente per la nuova azione nella maggior parte dei controller).

Mi chiedo quale sarebbe il modo migliore per specificare il layout? (Sto usando 3 o più layout diversi nello stesso controller)

Non mi piace usare

render: layout => 'nome'

Mi è piaciuto fare

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

Ma non posso usarlo per specificare 2 o più layout diversi.

Per esempio:

Quando chiamo layout 2 volte nello stesso controller, con nomi di layout diversi e diverse opzioni, la prima viene ignorata: quelle azioni non vengono visualizzate nel layout che ho specificato.

Nota: sto usando Rails 2.


1
Documentazione di The Rails Guides: guide.rubyonrails.org/…
Kevin,

1
Buon punto. La documentazione per Rails 2: guide.rubyonrails.org/v2.3.11/…
Kevin

2
(Inoltre, ho pubblicato la guida per aiutare i futuri lettori. Non ho dubbi che il tuo problema sia stato risolto molto tempo fa ;-)
Kevin,

Risposte:


297

È possibile utilizzare un metodo per impostare il layout.

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

22
Figo, grazie. E nel caso qualcuno voglia fare cose più semplici con una sola riga, è possibile quanto segue. È facile da leggere e posizionare nella parte superiore del controller. ---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
holli,

1
Ciò avrebbe un grande effetto sulle prestazioni dell'applicazione se diversi layout stessero usando diciamo rispettivamente diversi file css e js?
Noz,

15
-1: troppo complesso. Il commento qui sotto ( stackoverflow.com/a/21203783/285154 ) è l'opzione migliore.
dimitarvp,

Grazie! Questo è ancora un problema in Rails 4.2, forse solo se si utilizzano ereditari di controller a molti livelli. Ho usato il metodo prima, ma non pensavo di testarlo quando ho avuto il problema ora, grazie ancora.
244an,

@dimitko no non lo è, ho già fatto riferimento a quella soluzione nella domanda stessa. Non funziona se si desidera utilizzare 3 o più layout diversi (come è esattamente il mio caso).
mrbrdo,

201

Se si seleziona solo tra due layout, è possibile utilizzare :only:

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

o

class ProductsController < ApplicationController
   layout "application", only: [:index]
end

2
Bene, il problema è che non è possibile accedere ad oggetti come current_user per determinare il layout in modo condizionale
Andrew K

@AndrewK La scelta dinamica di un layout non sembra far parte della domanda posta.
Nick,

11
Se qualcuno di voi leggesse la domanda, saprebbe che questa non è la risposta giusta, poiché ho già descritto questa soluzione nella domanda stessa e anche perché non funziona nel mio caso (3 o più layout).
mrbrdo,

2
Come ha detto mrbrdo, questa non è la risposta. La sua domanda indica specificamente (I am using 3 or more different layouts in the same controller). Questa risposta consente un layout e nessun layout, non layout diversi.
Michael,

49

È possibile specificare il layout per una singola azione usando respond_to :

  def foo
    @model = Bar.first
    respond_to do |format|
      format.html {render :layout => 'application'}
    end
  end

Per me questa è la risposta più flessibile. ASCIUGARE le cose applicando il 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 rendering e / o il reindirizzamento sono stati chiamati più volte in questi errori di azione; e non hai altra scelta che usare questo suggerimento.
Girolamo

1
Questa risposta è la migliore, è semplice e pulita rispetto all'utilizzo di metodi con switch o if istruzioni all'interno.
Kev

inoltre può specificare sia il file erb che il layout: format.html { render 'custom_index', layout: 'application' } allo stesso modo.
thatway_3

12

Puoi anche specificare il layout per l'azione usando render:

def foo
  render layout: "application"
end


7

Vari modi per specificare il layout sotto il controller:

  1. Nel seguente codice, il layout application_1 viene chiamato sotto indice e mostra l'azione del controller utenti e il layout dell'applicazione (layout predefinito) viene chiamato per altre azioni.

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. Nel seguente codice, viene chiamato il layout application_1 per tutte le azioni del controller Utenti.

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. Nel codice seguente, il layout application_1 viene chiamato solo per l'azione di test dei controller utenti e per tutti gli altri layout dell'applicazione azione (impostazione predefinita).

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

5

Precisione:

Un modo DRY non proprio ma funzionante è quello che vedi sopra, ma con una precisione: il layout deve essere dopo le tue variabili per funzionare ("@some"). Come :

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

E non :

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

Se fai una before_action ... non funzionerà anche.

Spero che sia d'aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.