如何基于控制器/路由按需组合Rails布局?
Rails按控制器/路由条件组合加载布局内容的解决方案
方法一:控制器设置变量 + 主布局条件渲染
- 保留原有的
layouts/toolbar1.html.erb和layouts/toolbar2.html.erb,也可以将它们改名为partial(比如layouts/_toolbar1.html.erb,下划线开头是Rails partial的命名规范) - 在目标控制器的动作中设置实例变量,指定要加载的toolbar:
# app/controllers/test_controller.rb class TestController < ApplicationController def show # 业务逻辑代码 @active_toolbar = :toolbar1 end def edit # 业务逻辑代码 @active_toolbar = :toolbar2 end end
- 修改
layouts/application.html.erb,根据变量条件渲染对应的toolbar:
<html> <head> <body> <p>Hi</p> <% if @active_toolbar == :toolbar1 %> <%= render 'layouts/toolbar1' %> <% elsif @active_toolbar == :toolbar2 %> <%= render 'layouts/toolbar2' %> <% end %> <%= yield %> </body> </head> </html>
主布局application会正常加载,同时对应的toolbar里的content_for代码会被执行,yield :toolbar1或yield :toolbar2就能输出对应内容。
方法二:直接通过路由判断渲染
如果不想修改控制器逻辑,可以直接在主布局中根据当前路由判断:
# layouts/application.html.erb <html> <head> <body> <p>Hi</p> <%# 匹配TestController的show动作路由 %> <% if current_page?(test_show_path) %> <%= render 'layouts/toolbar1' %> <%# 匹配其他需要加载toolbar2的路由 %> <% elsif current_page?(some_other_path) %> <%= render 'layouts/toolbar2' %> <% end %> <%= yield %> </body> </head> </html>
这种方式无需控制器介入,直接用current_page?方法匹配路由即可实现条件加载。
方法三:使用before_action统一管理
如果多个动作需要设置toolbar,可以用before_action简化代码:
# app/controllers/test_controller.rb class TestController < ApplicationController before_action :set_toolbar, only: [:show, :edit] def show # 业务逻辑代码 end def edit # 业务逻辑代码 end private def set_toolbar @active_toolbar = case action_name when 'show' then :toolbar1 when 'edit' then :toolbar2 end end end
主布局的判断逻辑和方法一保持一致即可。
注:如果原toolbar文件不是partial,渲染时可以用render template: 'layouts/toolbar1'替代render 'layouts/toolbar1',效果完全相同。
内容的提问来源于stack exchange,提问作者ohhh
相关产品推荐
相关产品推荐

