ActiveAdmin:如何避免索引与导出功能间的代码重复?
在ActiveAdmin中复用列配置实现DRY原则
我有一个包含大量属性与方法的复杂模型,需要在ActiveAdmin中实现特定视图,目前编写的index视图代码运行正常:
index do column :status column "Complex data" do |my_object| my_object.compute_complex_data end # 其他列配置 end
现在希望导出功能(主要是CSV,也可能支持XML/JSON)复用同样的列配置,但默认导出的是资源原始数据,而非视图中定义的列。直接复制代码到csv块里会造成重复,不符合DRY原则。之前尝试用lambda定义通用列但没成功:
common_columns = lambda do column :status # 其他列 end csv do common_columns.call end
可行解决方案
方法1:用实例方法封装共享列配置
ActiveAdmin的index、csv等块的执行上下文是资源实例,把通用列定义抽成实例方法,就能在各个块中直接调用:
ActiveAdmin.register YourModel do # 封装通用列配置 def common_columns column :status column "Complex data" do |my_object| my_object.compute_complex_data end # 其他通用列 end index do common_columns # 可额外添加仅在列表页显示的列 end csv do common_columns # 可额外添加仅在CSV导出的列 end # XML/JSON导出同理 json do common_columns end end
方法2:用常量定义列配置集合
把列配置整理成数组,通过遍历批量注册,适合需要更灵活控制列顺序或条件渲染的场景:
ActiveAdmin.register YourModel do # 定义通用列集合:符号对应模型属性,数组对应「自定义列名+处理逻辑」 COMMON_COLUMNS = [ :status, ["Complex data", ->(obj) { obj.compute_complex_data }] # 其他列配置 ] index do COMMON_COLUMNS.each do |col| col.is_a?(Array) ? column(col[0], &col[1]) : column(col) end # 额外列表页列 end csv do COMMON_COLUMNS.each do |col| col.is_a?(Array) ? column(col[0], &col[1]) : column(col) end # 额外导出列 end end
为什么之前的Lambda方式失败?
Lambda执行时的上下文不是ActiveAdmin的资源实例,导致column方法无法被正确识别调用。而上面两种方法都确保了column方法在正确的上下文环境中执行。
内容的提问来源于stack exchange,提问作者gvo
相关产品推荐
相关产品推荐

