Row level caching with "Index as Table"

450 views Asked by At

I am displaying a table with ActiveAdmin using the "Index as Table" functionality:

index :pagination_total => false do

    if Ability.new(current_user).can? :manage, :metric
        selectable_column
    end

    column '' do |metric|
        links = link_to(metric.icon, admin_metric_path(metric), :title => metric.comment)
        links += link_to(metric.data_icon, admin_metric_path(metric)) unless metric.datum_ids.empty?
        links
    end

    column 'Status', :success, sortable: :success do |metric|
        metric.success == 1 ? status_tag('Success', :ok) : status_tag('FAILED', :error)
    end
    column 'When (UTC)', :createddttm
    column 'What', :metric_name
    column 'Area',    :logarea
    column 'Subarea', :subarea
    column 'Value',   :value
    column 'Machine', :machine_name, sortable: 'machinename.machinename'
    column 'Domain',  :domain_name, sortable: 'domain.domainname'
    column 'Product', :product_name, sortable: 'product.productname'
    column 'Version', :product_version, sortable: 'product.productversion'
    column 'Install Type', :install_type, sortable: 'product.productinstalltype'
    column 'Lang', :language
    column 'Duration', :duration
end

Given that the row data does not change, I would like to add row level caching of the rendered html with a long expiry time but I can't figure out how to hook into the row rendering code in Arbre.

I am currently caching the entire page for 60 seconds but that is not optimal. My cache store is Dalli / memcached.

1

There are 1 answers

8
nistvan On BEST ANSWER

UPDATE 2:

Try this with the cashed_rows method:

# lib\active_admin\views\index_as_table.rb
module ActiveAdmin
  module Views
    class IndexAsTable < ActiveAdmin::Component

      def build(page_presenter, collection)

        table_options = {
            id: "index_table_#{active_admin_config.resource_name.plural}",
            sortable: true,
            class: "index_table index",
            i18n: active_admin_config.resource_class,
            paginator: page_presenter[:paginator] != false,
            row_class: page_presenter[:row_class]
        }

        table = table_for collection, table_options do |t|
          table_config_block = page_presenter.block || default_table
          instance_exec(t, &table_config_block)
        end

        #new code
        rows = []
        table.children.each {|row| rows << row.to_s}
        resource_class.cached_rows = rows 

        table
      end
    end
  end
end

UPDATE: This is a monkey patch. Create a new file in lib folder, then you can use the rows array.

module ActiveAdmin
  module Views
    class TableFor < Arbre::HTML::Table

      def build_table_body

        @tbody = tbody do
          # Build enough rows for our collection
          @collection.each do |elem|
            classes = [cycle('odd', 'even')]

            if @row_class
              classes << @row_class.call(elem)
            end

            tr(class: classes.flatten.join(' '), id: dom_id_for(elem))
          end
        end

        #new code: rows will contain the html string for each row
        rows = []
        @tbody.children.each {|row| rows << row.to_s} #you can also use: @tbody.to_s
        YourActiveRecordModel.cached_rows= rows

        @tbody 
      end
    end
  end
end

class YourActiveRecordModel < ActiveRecord::Base

  def self.cached_rows=(attr)
    @@rows = attr
  end

  def self.cached_rows
    @@rows
  end
end

Now you can get the html string: YourActiveRecordModel.cached_rows if you build the index table at least once.

Old answer:

I would make a new table that contains the string representation of the contained objects. You can determine which record want to load (the original or the cached record):

  controller do
    def find_resource
      if params[:action] == 'index' #or something similar
         CachedRecords.find(params[:id])
      elsif params[:action] == 'edit'
         OriginalRecords.find(params[:id])
    end
  end

https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#customizing-resource-retrieval