reasoncorp/dossier

Question: Is it possible to pass my own arguments into the constructor for a report?

Opened this issue · 4 comments

In my ApplicationController, I have a generic index action [that can be overridden by any controller] where I want to return the CSV for any object with something like this:

def index
  @records = apply_page_query_parameters(policy_scope(resource_class))
  respond_to do |format|
    format.html { render_records(@records) }
    format.csv {
      report = GenericReport.new(project: @all_records, table: resource_class)
      send_data generate_csv_from_report(report.results)
    }
  end
end

But I can't seem to figure out how to pass in that table parameter, which I'd like to use in a GenericReport class kind of like this:

class GenericReport < Dossier::Report
  def sql
    'SELECT * FROM table <= :table'
  end
end

Would appreciate some help! And while I'm here, is there a way to generate the CSV from a report object directly? I wrote the generate_csv_from_report function myself in a helper I created. It was a very small and simple method, but it would be nice to eliminate it entirely.

For the record, the reason I do this instead of redirecting to the dossier reports route is that it was far easier to authorize access to a report this way when using the pundit gem.

If you are not afraid of sql injection do something like

def sql
"SELECT * FROM #{ options[:table] }"
end

and in controller pass table as

report = GenericReport.new(project: @all_records, table: resource_class.table_name)

@RocketGuy3 were you ever able to figure this out?

@kcollignon - I just ran in to a similar issue myself.

I needed tenancy - something that can't just be passed via a URL param. As the reports themselves don't have session info I ended up monkey patching the reports controller to add it to the options param hash that gets sent to the report

# /config/initializers/dossier.rb
# Overridding options_params in Dossier controller to add tenancy support

module Dossier
  class ReportsController < ApplicationController
    include ViewContextWithReportFormatter

    self.responder = Dossier::Responder

    respond_to :html, :json, :csv, :xls

    def show
      respond_with(report)
    end

    def multi
      respond_with(report)
    end

    private

    def report_class
      Dossier::Model.name_to_class(params[:report])
    end

    def report
      @report ||= report_class.new(options_params)
    end

    def options_params
      # original was: params[:options].presence || {}
      if params[:options].present?
        params[:options].merge(company_id: current_user.company_id)
      else
        {}.merge(company_id: current_user.company_id)
      end
    end
  end
end

then in my reports I have

  def company_id
    options[:company_id]
  end

and the sql strings for the reports can use ':company_id' as needed in where & join clauses.

It's a fast hack that Ill revisit after I put the fire out but it's working. Hopefully it's of some help to you or others. I'm interested in how others are solving this problem as well.

I was never able to get it working, so I had to abandon the gem and write my own solution.