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.