Active Admin 索引页Index Page定制完全指南多视图、过滤器、作用域与分页【免费下载链接】activeadminThe administration framework for Ruby on Rails applications.项目地址: https://gitcode.com/gh_mirrors/ac/activeadmin索引页是后台管理系统中管理员使用最频繁的界面它承担着资源列表的展示、筛选、排序与批量操作入口。Active AdminRails 应用的后台管理框架为索引页内置了多种渲染器并提供了从表格一列一列微调到完全自绘视图的完整定制能力。本文以 docs/3-index-pages.md 为骨架结合仓库源码与各细分文档表格、网格、块、博客、自定义索引系统讲解索引页的每一个可定制点读完你将掌握多索引页切换、四种内置渲染器、过滤器含 Ransack 谓词、过滤器类型与全局配置、索引作用域含分组、默认排序、分页含每页条数下拉与禁用计数以及下载链接的定制。内置索引渲染器总览Active Admin 为资源列表内置了四种渲染器在资源注册块中通过index方法的as:选项切换渲染器as:取值特点细分文档表格Table默认as: :table每个资源一行默认展示全部内容列以及查看/编辑/删除链接index-as-table.md网格Gridas: :grid行列式单元格布局适合缩略图墙index-as-grid.md块Blocksas: :block每个资源渲染一整块自定义内容index-as-block.md博客Blogas: :blog标题 正文的博文流样式index-as-blog.md从源码看index方法在 lib/active_admin/resource_dsl.rb#L85-L88 中定义未显式指定:as时默认值为:tabledef index(options {}, block) options[:as] || :table config.set_page_presenter :index, ActiveAdmin::PagePresenter.new(options, block) end所有索引页无论采用哪种渲染器都统一支持作用域scopes、过滤器filters、分页pagination、操作项action items和侧边栏区块sidebar sections后续章节会逐一展开。表格索引Index as a Table默认表格渲染器由 lib/active_admin/views/index_as_table.rb 中的IndexAsTable组件实现其index_name返回table并接收paginator、tbody_html、row_html、row_class等页面展示选项见build方法。以下是常用定制点。定义列向column传入属性或方法的 Symbol 即可index do selectable_column column :title endselectable_column用于显示复选框列只有配置了 batch actions 时才渲染见 index_as_table.rb#L251-L256。对于关联列Active Admin 会按以下方法顺序猜测展示内容:display_name, :full_name, :name, :username, :login, :title, :email, :to_s该顺序可在config/initializers/active_admin.rb中自定义。标题不合适时可作为第一参数传入index do selectable_column column My Custom Title, :title end需要写视图相关代码时column接受一个块每个资源对象会被依次传入块内index do selectable_column column Title do |post| link_to post.title, admin_post_path(post) end end定义操作列使用actions方法生成查看/编辑/删除链接index do selectable_column column :title actions end在默认链接之后追加自定义链接index do selectable_column column :title actions do |post| item Preview, admin_preview_post_path(post), class: preview-link end end完全去掉默认链接defaults: falseindex do column :title actions defaults: false do |post| item View, admin_post_path(post) end end也可以直接用 Arbre 语法输出自定义 HTML 元素actions的实现见 index_as_table.rb#L303-L316块内结果若不是Arbre::Element会被转为文本节点index do column :title actions do |post| a View, href: admin_post_path(post) end end排序由 Active Record 属性生成的列默认可排序自定义列需要显式给出排序键index do column :title, sortable: :title do |post| link_to post.title, admin_post_path(post) end endsortable: false可关闭某列的排序。PostgreSQL 的 hstore 场景下sortable还支持column-key语法如column :keywords, sortable: meta-keywords。自定义排序表达式借助order_by可注入数据库特定的排序片段。在 lib/active_admin/resource_dsl.rb#L23-L25 中order_by(column, block)会把块存入config.ordering块内接收一个order_clause对象order_by(:title) do |order_clause| if order_clause.order desc [order_clause.to_sql, NULLS LAST].join( ) else [order_clause.to_sql, NULLS FIRST].join( ) end end index do column :title end关联列排序默认无法按关联对象排序但配合includes即可。以 Books 索引页、Book has_one Publisher 为例先消除 N1controller do def scoped_collection super.includes :publisher # prevents N1 queries to your database end end或者用资源级 DSLincludes :publisher见 resource_dsl.rb#L41-L44然后在索引表格中按关联属性排序index do column :publisher, sortable: publishers.name end按上下文显隐列索引块在视图上下文中渲染可结合权限直接控制列的存在例如 CanCan 场景index do column :title, sortable: false column :secret_data if can? :manage, Post end自定义 tbody / 行 HTML 属性tbody_html接受哈希index tbody_html: { class: my-class, data: { controller: stimulus-controller } } do # columns endrow_html接受一个 Proc每行资源对象作为参数返回值作为该行属性index row_html: -elem { { class: (active if elem.active?), data: { element-id elem.id } } } do # columns end网格索引Index as a Grid适合缩略图等卡片式场景。块会在网格单元格中为集合里的每个资源渲染一次资源作为块参数传入index as: :grid do |product| link_to image_tag(product.image_path), admin_product_path(product) end用columns选项控制每行列数index as: :grid, columns: 5 do |product| link_to image_tag(product.image_path), admin_product_path(product) end详见 index-as-grid.md。块索引Index as a Block需要完全自定义每个资源的展示内容时使用。块内可使用 Arbre 语法自由组合元素例如结合批处理选择单元格与自动链接index as: :block do |product| div for: product do resource_selection_cell product h2 auto_link product.title div simple_format product.description end end详见 index-as-block.md。博客索引Index as Blog以标题 正文的博文流方式渲染索引页。title与body是两种核心选项都支持传方法名或传块两种形式。直接调用资源方法index as: :blog do title :my_title # Calls #my_title on each resource body :my_body # Calls #my_body on each resource end标题传块资源作为块参数可用 Arbre 组织复杂标题index as: :blog do title do |post| span post.title, class: title span post.created_at, class: created_at end end正文传块index as: :blog do title :my_title body do |post| div truncate post.title div class: meta do span Post in #{post.categories.join(, )} end end end详见 index-as-blog.md。多个索引页面Multiple Index Pages同一个资源可以注册多个索引组件为不同用户呈现不同视图。多个索引页存在时Active Admin 会自动在默认索引页顶部生成切换链接index do id_column column :image_title actions end index as: :grid do |product| link_to image_tag(product.image_path), admin_product_path(product) end第一个声明的索引组件默认为默认页也可通过default: true显式指定index do column :image_title actions end index as: :grid, default: true do |product| link_to image_tag(product.image_path), admin_product_path(product) end多个索引页之间的链接切换依赖各索引组件提供的index_name类方法见下节自定义索引未定义该方法的组件无法参与多索引页切换。自定义索引Custom Index内置组件无法满足需求时可以自定义索引组件继承ActiveAdmin::Component实现build方法与index_name类方法然后在index中通过as:指定组件类module ActiveAdmin module Views class IndexAsMyIdea ActiveAdmin::Component def build(page_presenter, collection) # ... end def self.index_name my_idea end end end end ActiveAdmin.register Product do index as: ActiveAdmin::Views::IndexAsMyIdea do column :image_title actions end endbuild接收一个PagePresenter对象即index方法传入的 options 与块封装和集合index_name类方法无参、返回代表类名的字符串是多个索引页面特性能否生效的关键。详见 custom-index.md。索引过滤器Index Filters默认情况下索引页右侧会有一个 Filters 侧边栏为注册模型的每个属性生成一个过滤器。可以用filter方法精确控制显示的过滤器及其控件类型DSL 入口见 lib/active_admin/filters/dsl.rbActiveAdmin.register Post do filter :title end内置过滤器类型类型说明:string下拉选择 Contains、Equals、Starts with、Ends with 谓词 值输入框:date_range带日历控件的起止日期字段:numeric下拉选择 Equal To、Greater Than、Less Than 值输入框:select从集合中选择某一项或全部进行过滤:check_boxes一组复选框勾选即过滤Active Admin 默认根据属性类型自动选择最合适的过滤器类型。这一推断逻辑在 lib/active_admin/filters/forms.rb#L20-L39 的default_input_type中实现以_eq/_cont/_start/_end结尾的方法名视为:string自定义 Ransack 搜索器按_ransackers中的类型推断关联或多态外键默认为:select普通列则按列类型映射date/datetime →:date_rangestring/text/citext →:stringinteger/float/decimal →:numericboolean →:boolean。需要强制类型时传:as选项filter :author, as: :check_boxes集合collection选项:check_boxes与:select类型接受collection选项。默认会基于关联自动构建集合也可以传入 Proc 在渲染时求值filter :author, as: :check_boxes, collection: proc { Author.all }限定字符串/数值过滤谓词通过filters选项覆盖字符串或数值过滤器的可选谓词filter :title, filters: [:start, :end]若想让所有字符串过滤器统一使用同一组谓词不必在每个filter上重复传filters可以直接配置string_input_filters作用域优先级为单条 filter 的filters选项 资源级配置 命名空间级配置。# config/initializers/active_admin.rb ActiveAdmin.setup do |config| config.namespace :admin do |admin| admin.string_input_filters [:eq, :cont] end end # app/admin/post.rb ActiveAdmin.register Post do string_input_filters [:eq, :cont] end资源级 DSL 对应 resource_dsl.rb#L166-L168 中的string_input_filters(value)方法实现上写入config.string_input_filters。如果不需要 cont、eq、start、end 这些谓词的选择下拉可以直接把谓词拼到过滤属性名上下划线连接filter :name_eq # or filter :name_cont标签与多属性搜索通过label选项修改过滤器的显示标签默认情况下 Active Admin 会尝试用 ActiveModel I18n 解析标签filter :author, label: Something else过滤器同样支持 Ransack 搜索谓词语法Basic Searching 相关谓词一次过滤多个属性。使用自定义搜索方法时必须同时通过:as指定字段类型并给出labelfilter :first_name_or_last_name_cont, as: :string, label: Name全局禁用过滤器可分别在资源、命名空间、整个应用三个层级关闭过滤器。资源级ActiveAdmin.register Post do config.filters false end命名空间级写在初始化器中ActiveAdmin.setup do |config| config.namespace :my_namespace do |my_namespace| my_namespace.filters false end end应用级ActiveAdmin.setup do |config| config.filters false end保留默认过滤器并增删默认情况下显式调用filter会替换全部默认过滤器。若只想在默认过滤器基础上追加使用preserve_default_filters!想移除某个默认过滤器同样先声明保留再remove_filterpreserve_default_filters! filter :authorpreserve_default_filters! remove_filter :id过滤属性的授权白名单Allow Filtering Attributes出于安全考虑Active Admin 默认拒绝对任何模型属性进行过滤——这是防止用户通过猜测属性名来探测/读取不应访问数据的安全特性。要允许过滤某些属性需要按 Ransack 的授权Authorization Allowlisting/Denylisting指南扩展ransackable_attributes类方法将允许过滤的属性列入白名单如def self.ransackable_attributes(auth_object nil) %w[title body]。只有列入白名单的属性才能在索引页过滤器中使用。索引作用域Index Scopesscope方法用于在索引表格上方添加一个标签栏通过预定义的作用域快速筛选集合。它支持多种定义方式scope :all, default: true # 假定模型上已有名为 :active 的 scope scope :active # 把模型 scope :leaves 改名为 :subcategories scope Subcategories, :leaves # 动态作用域名 scope -{ Date.today.strftime %A }, :published_today # 模型上不存在的自定义 scope scope(Inactive) { |scope| scope.where(active: false) } # 条件显示的控制器级自定义 scope scope Published, if: - { current_admin_user.can? :manage, Posts } do |posts| posts.published endscope的 DSL 入口在 lib/active_admin/resource_dsl.rb#L36-L39实现为config.scope(*args, block)。作用域名可用 i18n 翻译标签键为active_admin.scopes.scope_method。作用域分组Scopes Groups通过group:选项为作用域分组把相关的若干作用域聚在一起、与其余作用域隔开# 默认组中的作用域 scope :all # 按状态过滤的两个作用域 scope :active, group: :status scope :inactive, group: :status # 按日期过滤的两个作用域 scope :today, group: :date scope :tomorrow, group: :dategroup:选项在 lib/active_admin/scope.rb 的Scope类中作为构造参数支持如Scope.new :published, nil, group: :status。默认排序Index default sort order通过资源配置设置索引页的默认排序格式为属性名_asc/属性名_descActiveAdmin.register Post do config.sort_order name_asc end分页Index Pagination每页记录数全局默认值在初始化器中设置源码默认值为 30见 lib/active_admin/namespace_settings.rb#L7 的register :default_per_page, 30同文件还注册了max_per_page, 10_000ActiveAdmin.setup do |config| config.default_per_page 30 end按资源设置ActiveAdmin.register Post do config.per_page 10 end让用户通过下拉框自行选择每页条数传入数组即可ActiveAdmin.register Post do config.per_page [10, 50, 100] end该数组在 lib/active_admin/views/components/paginated_collection.rb 的build_per_page_select中被渲染成下拉选择框。分页相关的默认值装配逻辑在 lib/active_admin/resource/pagination.rb#L18-L20paginate默认为trueper_page默认取命名空间的default_per_pagemax_per_page默认取max_per_page。按请求/动作动态调整在控制器内用before_action设置per_page实例变量controller do before_action only: :index do per_page 100 end end关闭分页ActiveAdmin.register Post do config.paginate false end大数据量场景关闭总数统计如果数据库规模很大可以考虑关闭索引页底部由分页信息触发的SELECT COUNT(*)查询ActiveAdmin.register Post do index pagination_total: false do # ... end end该选项通过page_presenter[:paginator]传入IndexAsTable组件见 index_as_table.rb#L225 的paginator: page_presenter[:paginator] ! false。定制下载链接Customizing Download Links索引集合默认支持 CSV 等格式的下载链接可方便地移除或定制。按资源定制# Per resource: ActiveAdmin.register Post do index download_links: false index download_links: [:pdf] index download_links: proc{ current_user.can_view_download_links? } end全局定制初始化器中默认值为true见 lib/active_admin/namespace_settings.rb#L56# For the entire application: ActiveAdmin.setup do |config| config.download_links false config.download_links [:csv, :xml, :json, :pdf] config.download_links proc { current_user.can_view_download_links? } end注意Active Admin 并不负责生成 PDF 内容——该配置只是决定索引集合下展示哪些格式的下载链接。PDF 的实际渲染需要自行实现可借助 PDFKit、WickedPDF 等 PDF 渲染库。download_links与per_page数组的渲染同样在 paginated_collection.rb#L70-L73 中处理当存在下载格式或每页下拉框时会在分页集合底部生成一个 footer 区域。小结与实战建议默认索引页即表格index未指定as:时使用IndexAsTable日常列/操作/排序定制全部在index do ... end块内完成。多视图并存同一资源可声明 table grid block blog 等任意组合default: true控制默认视图顶部自动出现切换链接。过滤器三件套filter增、preserve_default_filters!保留默认、remove_filter删谓词可内联到属性名name_cont类型推断规则可参考default_input_type源码别忘了ransackable_attributes授权白名单。作用域与分页scope支持方法名、字符串别名、动态名、自定义块与条件显隐group:让标签栏更有条理per_page传数组即可得到下拉选择器超大数据集用pagination_total: false省掉 COUNT 查询。下载链接download_links三态false / 格式数组 / ProcPDF 渲染需要自行接入 PDFKit 或 WickedPDF。以上所有配置均作用于资源注册块app/admin/*.rb与初始化器config/initializers/active_admin.rb可在不修改 Active Admin 源码的前提下完成全部索引页定制。【免费下载链接】activeadminThe administration framework for Ruby on Rails applications.项目地址: https://gitcode.com/gh_mirrors/ac/activeadmin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考