☰
RailsAdmin Show In App 动作详解:从后台跳转前台页面与权限配置
2026/10/6 2:04:42 网站建设 项目流程
  • 后端

【免费下载链接】rails_admin

RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data

项目地址:https://gitcode.com/gh_mirrors/ra/rails_admin
点击查看免费下载

本篇文章以 RailsAdmin 内置的show_in_app动作为核心,讲解它如何让管理员在后台管理界面中一键跳转到业务系统(前台应用)中对应对象的展示页面,并完整覆盖其实现原理、默认配置、CanCanCan / Pundit 授权方式、可见性控制以及集成测试验证。读完本文,你将掌握该动作的完整工作机制,并能在自己的 Rails 项目中精确配置它的显示范围与访问权限。

Show In App 是什么

show_in_app("Show in app")是 RailsAdmin 的成员级(member)动作之一,作用于单个数据对象。它的职责非常单一:把当前后台正在查看的记录,在主应用(即宿主 Rails 应用的前台)中找到对应页面并跳转过去。典型场景是:管理员在/admin/player/1/show中查看一名球员的详情,点击 "Show in app" 后直接进入前台/players/1的公开页面。

该动作的完整实现位于 lib/rails_admin/config/actions/show_in_app.rb,全类只有 35 行,是整个 RailsAdmin 动作体系中"小而美"的典型代表。

动作的默认注册与路由

show_in_app在 RailsAdmin 中是默认开启的动作之一。docs/actions.md 中明确列出,默认配置等价于:

# config/initializers/rails_admin.rb RailsAdmin.config do |config| config.actions do # root actions dashboard # mandatory # collection actions index # mandatory new export history_index bulk_delete # member actions show edit delete history_show show_in_app end end

由于它是成员级动作,其路由会被挂载到对象粒度上。查看 config/routes.rb 中动作路由的动态生成逻辑:

RailsAdmin::Config::Actions.all(:member).each { |action| match "/#{action.route_fragment}", action: action.action_name, as: action.action_name, via: action.http_methods }

也就是说,show_in_app生成的访问路径形如/admin/:model_name/:id/show_in_app,其route_fragment、action_name、authorization_key、i18n_key等默认都取自动作键名:show_in_app(参见 lib/rails_admin/config/actions/base.rb 中register_instance_option :key/self.key的实现:name.to_s.demodulize.underscore.to_sym)。

源码级解析:这个动作到底做了什么

打开 lib/rails_admin/config/actions/show_in_app.rb,可以看到四个关键实例选项,它们共同决定了该动作的行为:

register_instance_option :member do true end register_instance_option :visible? do authorized? && begin bindings[:controller].main_app.url_for(bindings[:object]) rescue StandardError false end end register_instance_option :controller do proc do redirect_to main_app.url_for(@object) end end register_instance_option :link_icon do 'fas fa-eye' end register_instance_option :turbo? do false end

逐项解读:

  • :member为true:声明该动作作用于单个对象。在 base.rb 中,member?决定了breadcrumb_parent默认指向[:show, bindings[:abstract_model], bindings[:object]],即面包屑会挂在 Show 动作之下。
  • :visible?双重要求:首先必须通过authorized?(见下文授权小节),其次尝试调用main_app.url_for(bindings[:object])为主应用中的该对象生成 URL。这里用rescue StandardError兜底:一旦主应用路由无法为该对象生成 URL(例如缺少 show 路由、对象没有to_param对应的页面等),动作就自动不可见。这保证了"Show in app"按钮永远不会出现在一个跳转不了的对象上。
  • :controller重定向:动作真正被访问时,直接redirect_to main_app.url_for(@object)把请求重定向到主应用的对象页面。注意它没有渲染任何 RailsAdmin 视图,而是完全交还给宿主应用的路由系统。
  • :link_icon:使用 Font Awesome 的fas fa-eye眼睛图标作为按钮图标。
  • :turbo?为false:与大多数动作不同,该动作不通过 Turbo Drive 导航,因为它是跳转到主应用页面的外部跳转,需要完整页面加载。测试 spec/integration/actions/show_in_app_spec.rb 专门验证了这一点:
it 'has the>actions: show_in_app: menu: "Show in app"

授权控制:原文档核心示例

show_in_app与 CanCanCan(及其前身 CanCan)的协作是该动作文档的核心内容。docs/show-in-app-action.md 给出了授权声明示例:

can :manage, :all # includes can :show_in_app, :all # includes can :show_in_app, Model # includes can :show_in_app, Model, { conditions }

解读这四行的含义:

  • can :manage, :all允许管理所有资源,其中隐含了show_in_app授权;
  • can :show_in_app, :all对所有模型开放该动作的访问;
  • can :show_in_app, Model仅对指定模型开放;
  • can :show_in_app, Model, { conditions }在指定模型基础上叠加条件哈希,实现"满足条件的记录才能跳转前台"的精细控制。

授权键的由来:在 base.rb 中,authorization_key的默认实现是key.to_sym,而key由类名推导,因此ShowInApp类的授权键就是:show_in_app。每个动作在显示链接、访问页面之前都会经过authorized?检查(见 base.rb 的register_instance_option :authorized?):

authorized? do enabled? && ( bindings[:controller].try(:authorization_adapter).nil? || bindings[:controller].authorization_adapter.authorized?(authorization_key, bindings[:abstract_model], bindings[:object]) ) end

只要配置了授权适配器,show_in_app的显示与访问都会以can :show_in_app, Model, object的形式查询授权,其中object是当前被检查的对象实例(见 docs/cancancan.md 中成员级动作的授权清单:can :show_in_app, Model, object)。

在 Ability 中完整配置

结合 docs/cancancan.md 的说明,一个可运行的完整示例为:

# config/initializers/rails_admin.rb RailsAdmin.config do |config| config.authorize_with :cancancan end
class Ability include CanCan::Ability def initialize(user) can :access, :rails_admin # grant access to rails_admin can :read, :dashboard # grant access to the dashboard return unless user # 所有登录用户都能跳转前台,但只对未退役的球员生效 can :show_in_app, Player, retired: false end end

cancancan_spec.rb 中的测试 Ability 正是这样写的:

can :show_in_app, Player, retired: false if user.roles.include? :show_in_app_player

测试断言了三种典型行为:

  • 未授予show_in_app权限的角色:列表与 Show 页均不出现.show_in_app_member_link,且无 "Show in app" 文案;
  • 仅授予read_player+show_in_app_player:列表与 Show 页出现该链接,同时 Edit / Delete / History 链接不出现——证明授权是按动作独立控制的;
  • 授予admin+manage_player:所有成员级动作链接全部出现。

使用 Pundit

若改用 Pundit,则授权键同样生效。在 spec/policies.rb 中可以看到ApplicationPolicy定义了show_in_app?方法,通过user.roles.include? :admin控制:

def show_in_app? user.roles.include? :admin end

Pundit 适配器会把:show_in_app授权键映射为策略中的show_in_app?方法(详见 lib/rails_admin/extensions/pundit/authorization_adapter.rb 与 docs/authorization.md)。

精细化控制:可见性与作用范围

通过 visible 块控制

除了授权,还可以直接覆写visible?选项做更精细的控制。这正是原文档 docs/show-in-app-action.md 末尾链接所指的方向(docs/actions.md 中明确建议参考 Show in App 的实现来理解 visible 块的用法)。可用的绑定有:

  • bindings[:controller]:当前控制器实例
  • bindings[:abstract_model]:被检查的抽象模型(成员级动作可用)
  • bindings[:object]:被检查的对象实例(仅成员级动作可用)

示例:只允许对"未归档"的对象显示跳转按钮:

RailsAdmin.config do |config| config.actions do show_in_app do visible do object = bindings[:object] object.present? && !object.archived? end end end end

注意 docs/actions.md 的提醒:在 RailsAdmin 创建路由或定义 controller 动作的生命周期早期,bindings可能为nil,所以visible块内对绑定值的判空是安全写法。

按模型限定作用范围

沿用在 docs/actions.md 中描述的基础选项,可以为该动作限定模型范围:

RailsAdmin.config do |config| config.actions do show_in_app do only ['Player'] # 只在 Player 模型上出现 # except ['Team'] # 或使用 except 排除 end end end

only/except由 base.rb 中的enabled?实现强制执行,结合bindings[:abstract_model].config.excluded?一并判定。

一个关键设计:无法生成 URL 时自动隐藏

show_in_app的visible?实现中rescue StandardError的设计值得特别强调。它意味着:如果主应用无法为当前对象生成 URL(比如模型没有对应前台 show 路由、to_param解析失败),该动作会静默地从操作菜单中消失,而不是渲染出一个注定 404 的死链。这为使用该动作的项目提供了天然的保护——你无需为每个模型手工判断"前台是否有页面",RailsAdmin 会自动替你探测。

从实现上看,main_app.url_for(bindings[:object])会触发主应用的路由系统对对象执行polymorphic_path之类的解析,一旦主应用routes.rb中缺少对应资源的 show 路由,url_for抛出异常即被吞掉并返回false。

自定义与二次开发

如果你需要对跳转行为做定制(例如跳转前带参数、跳转到自定义路径),可以直接在 initializer 中覆写该动作的controller选项:

RailsAdmin.config do |config| config.actions do show_in_app do controller do redirect_to main_app.polymorphic_path(@object, utm_source: 'admin') end end end end

更彻底的方案是参考 docs/actions.md 中"Create a reusable action"一节,继承RailsAdmin::Config::Actions::Base并register一个新动作类(lib/rails_admin/config/actions.rb 中的register方法),把跳转逻辑封装成可复用的自定义动作。

小结

show_in_app虽小,却集中体现了 RailsAdmin 动作系统的几大设计理念:动作即配置对象(register_instance_option)、授权自动联动(authorized?与authorization_key)、可见性按对象动态判定(visible?+url_for探测)、以及与 Turbo 的集成取舍(turbo? false)。阅读它的源码(lib/rails_admin/config/actions/show_in_app.rb)与对应集成测试(spec/integration/actions/show_in_app_spec.rb、spec/integration/authorization/cancancan_spec.rb),是理解并二次开发 RailsAdmin 自定义动作的最佳切入点。

  • 后端

【免费下载链接】rails_admin

RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data

项目地址:https://gitcode.com/gh_mirrors/ra/rails_admin
点击查看免费下载
上一篇:PyTorch证书备考终极指南:The Incredible PyTorch认证资源包 🚀
下一篇:JavaScript 对象与 JSON 互转实战:JSON.stringify / JSON.parse 深度解析与深度克隆(Modern JavaScript Tutorial 精读)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询