每个动作的 Rails 布局?

Posted

技术标签:

【中文标题】每个动作的 Rails 布局?【英文标题】:Rails layouts per action? 【发布时间】:2011-03-02 19:58:26 【问题描述】:

我对某些动作使用不同的布局(主要是用于大多数控制器中的新动作)。

我想知道指定布局的最佳方式是什么? (我在同一个控制器中使用了 3 个或更多不同的布局)

我不喜欢使用

渲染 :layout => '名称'

我喜欢做

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

但我不能用它来指定 2 个或更多不同的布局。

例如:

当我在同一个控制器中使用不同的布局名称和不同的唯一选项调用布局 2 次时,第一个将被忽略 - 这些操作不会显示在我指定的布局中。

注意:我使用的是 Rails 2。

【问题讨论】:

Rails 指南文档:guides.rubyonrails.org/… 好点。 Rails 2 的文档:guides.rubyonrails.org/v2.3.11/… (另外,我发布了该指南以帮助未来的读者。我相信您的问题很久以前就解决了;-) 【参考方案1】:

您可以使用一种方法来设置布局。

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

【讨论】:

酷,谢谢。如果有人想用单线做更简单的事情,以下是可能的。它易于阅读并放置在控制器顶部。 --- layout Proc.new ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' 如果各种布局分别使用多个不同的 css 和 js 文件,这会对应用程序性能产生很大影响吗? -1:太复杂了。下面的评论 (***.com/a/21203783/285154) 是最好的选择。 谢谢!这在 Rails 4.2 中仍然是一个问题,也许只有当您在多个级别使用继承控制器时。以前用过方法,现在遇到问题时没想过测试,再次感谢。 @dimitko 不,不是,我已经在问题本身中引用了该解决方案。如果您想使用 3 种或更多不同的布局(这正是我的情况),则它不起作用。【参考方案2】:

您可以使用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 Render 和/或重定向来干燥事物` 错误;你别无选择,只能使用这个建议。 这个答案是最好的,它简单而整洁,而不是使用带有 switch 或 if 语句的方法。 同样可以指定erb文件和布局:format.html render 'custom_index', layout: 'application' 【参考方案3】:

有一个 gem (layout_by_action) :)

layout_by_action [:new, :create] => "some_layout", :index => "other_layout"

https://github.com/barelyknown/layout_by_action

【讨论】:

【参考方案4】:

如果你只在两种布局之间进行选择,你可以使用:only:

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

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

【讨论】:

嗯,这样做的问题是你不能访问诸如current_user之类的对象来有条件地确定布局 @AndrewK 动态选择布局似乎不是问题的一部分。 如果你们中的任何人读过这个问题,你就会知道这不是正确的答案,因为我已经在问题本身中描述了这个解决方案,以及为什么它在我的情况下不起作用(3 个或更多布局)。 就像 mrbrdo 所说,这不是答案。他的问题特别指出(I am using 3 or more different layouts in the same controller)。这个答案允许布局和无布局,not 不同的布局。【参考方案5】:

您还可以使用渲染指定操作的布局:

def foo
  render layout: "application"
end

【讨论】:

【参考方案6】:

在控制器下指定布局的各种方法:

    在下面的代码中,application_1 布局在用户控制器的 index 和 show 操作下调用,其他操作调用应用程序布局(默认布局)。

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
    

    在下面的代码中,users 控制器的所有操作都会调用 application_1 布局。

    class UsersController < ApplicationController
       layout "application_1"
    end
    

    在下面的代码中,application_1 布局仅用于用户控制器的测试操作,所有其他操作应用布局(默认)被调用。

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

【讨论】:

【参考方案7】:

精度:

您在上面看到的不是真正但有效的 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... 它也不会起作用。

希望对你有帮助。

【讨论】:

以上是关于每个动作的 Rails 布局?的主要内容,如果未能解决你的问题,请参考以下文章

ruby on rails 中的控制器和动作有啥区别?

如何直接从 Rails 控制器返回 HTML?

Rails 3:脚手架销毁动作重定向以显示动作

Rails 3:如何获取当前布局的名称?

如何清除 Rails 动作缓存? (Rails.cache.clear 不起作用)

创建动作 - Rails