アクションごとのRailsレイアウト?


165

一部のアクション(主にほとんどのコントローラーの新しいアクション)に異なるレイアウトを使用しています。

レイアウトを指定する最善の方法は何でしょうか?(同じコントローラで3つ以上の異なるレイアウトを使用しています)

使いたくない

render:layout => 'name'

するのが好き

レイアウト 'name'、:only => [:new]

しかし、それを使用して2つ以上の異なるレイアウトを指定することはできません。

例えば:

同じコントローラーでレイアウトを2回呼び出し、レイアウト名が異なり、オプションのみが異なる場合、最初のレイアウトは無視されます。これらのアクションは、指定したレイアウトに表示されません。

注:Rails 2を使用しています。


1
Railsのガイドドキュメント:guides.rubyonrails.org/...
ケビン

1
いい視点ね。Railsの2のドキュメント:guides.rubyonrails.org/v2.3.11/...
ケビン・

2
(また、私は将来の読者を助けるためにガイドを投稿しました。あなたがあなたの問題をずっと前に解決したことは間違いありません;-)
Kevin

回答:


297

メソッドを使用してレイアウトを設定できます。

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
よろしくお願いします。そして、誰かがワンライナーでより簡単なことをしたい場合には、以下が可能です。読みやすく、コントローラの上に置くことができます。---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
holli

1
さまざまなレイアウトがそれぞれいくつかの異なるcss&jsファイルを使用している場合、これはアプリケーションのパフォーマンスに大きな影響を与えるでしょうか?
Nozは

15
-1:複雑すぎる。以下のコメント(stackoverflow.com/a/21203783/285154)が最適なオプションです。
dimitarvp 2014

ありがとう!これは、おそらく多くのレベルで継承コントローラーを使用している場合にのみ、Rails 4.2の問題です。私は以前にメソッドを使用したことがありますが、問題が発生したときにテストを行うことを考えていませんでした。ありがとうございます。
2015年

@dimitkoいいえ、そうではありません。私はすでに質問自体でその解決策を参照しました。3つ以上の異なるレイアウトを使用する場合は機能しません(まさに私の場合です)。
mrbrdo 2016年

201

2つのレイアウトのみを選択する場合は、次を使用できます:only

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

または

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

2
まあ、これの問題は、current_userなどのオブジェクトにアクセスしてレイアウトを条件付きで決定できないことです
Andrew K

@AndrewK動的にレイアウトを選択することは、尋ねられる質問の一部ではないようです。
Nick

11
あなたが質問を読んだ場合、これは正しい答えではないことを知っているでしょう。私はすでにこの解決策を質問自体で説明しており、なぜ私の場合(3つ以上のレイアウト)で機能しないのかについてです。
mrbrdo 2016年

2
mrbrdoが言ったように、これは答えではありません。彼の質問は具体的に示しています(I am using 3 or more different layouts in the same controller)。この回答は、レイアウトを許可し、レイアウトなし、異なるレイアウトを許可しません
マイケル

49

respond_toを使用して、個々のアクションのレイアウトを指定できます。

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

私にはこれがより柔軟な答えです。このアクションの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 エラーでは、レンダリングやリダイレクトを適用して物を乾かすことが複数回呼び出されました。そして、あなたはこの提案を使用せざるを得ません。
ジェローム

1
この回答は、switchまたはifステートメントを内部で使用するのとは対照的に、最もシンプルで簡潔です。
kev 2015

同様に、erbファイルとレイアウトの両方を指定することもできますformat.html { render 'custom_index', layout: 'application' }
thatway_3 2016年

12

renderを使用してアクションのレイアウトを指定することもできます:

def foo
  render layout: "application"
end


7

コントローラの下でレイアウトを指定するさまざまな方法:

  1. 次のコードでは、インデックスの下でapplication_1レイアウトが呼び出され、Usersコントローラーのアクションが表示され、他のアクションではアプリケーションレイアウト(デフォルトレイアウト)が呼び出されます。

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. 次のコードでは、usersコントローラーのすべてのアクションに対してapplication_1レイアウトが呼び出されます。

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. 以下のコードでは、usersコントローラーのテストアクションに対してのみapplication_1レイアウトが呼び出され、他のすべてのアクションに対してはapplication layout(default)が呼び出されます。

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

5

精度:

実際には上手く機能しないDRYの方法は、上記のように見えますが、正確です。レイアウトは、機能する変数( "@some")の後に配置する必要があります。なので :

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

そして:

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

before_actionを実行した場合...それも機能しません。

それが役に立てば幸い。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.