Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export dynamic number of columns in ActiveAdmin CSV

This is with ActiveAdmin 0.4.3. Our application runs Surveys, which may have an arbitrary number of SurveyQuestions. When a user fills in a Survey, a UserSurveyComment instance is created, which has_many SurveyComments, one for each of the Survey's SurveyQuestions.

The result of this is that for any given Survey, all the UserSurveyComment instances will have the same number of SurveyComments, but between surveys this number may vary.

Is it possible for the ActiveAdmin CSV export to handle UserSurveyComments in this way, such that there are columns for the User, the Survey, and then each SurveyComment in turn? The export is scoped by Survey, so each row has the same columns, but particular exports may have a different number.

What I'd like to do is something like

survey.survey_questions.each do |sq|
  column "Question" { |q| q.survey_comments.where(survey_question_id: sq.id).first.submitted_text }
end

...but within the ActiveAdmin.CSVBuilder instance, there doesn't appear to be a way to reach the Survey.

Maybe it's easier for me to just do this in my own controller?

like image 531
pjmorse Avatar asked Dec 03 '14 17:12

pjmorse


1 Answers

I understand your model to be similar to

class Survey < ActiveRecord::Base
  has_many :user_survey_comments
  has_many :survey_questions
end

class SurveyQuestion < ActiveRecord::Base

  attr_accessor :name

  belongs_to :survey
  has_many :survey_comments
end

class UserSurveyComments < ActiveRecord::Base
  belongs_to :survey
  has_many :survey_comments
end

class SurveyComments  < ActiveRecord::Base

  attr_accessor :content

  belongs_to :user_survey_comments
  belongs_to :survey_question
end

Inside the csv block, @collection contains the list of objects filtered for output. In the configuration you can register UserSurveyComment in a similar way as follows:

ActiveAdmin.register UserSurveyComment do
  csv do

    column(:survey)

    visited_surveys = Set[]

    @collection.each do |user_survey_comment|

      next if visited_surveys.include?(user_survey_comment.survey)
      visited_surveys.add(user_survey_comment.survey)

      user_survey_comment.survey.survey_questions do |question|
        column(question.name) do |user_survey_comment|
          user_survey_comment
            .survey_comments
            .find_by(survey_question_id=question.id)
            .try(:response){''}
        end
      end
    end
  end
end
like image 103
ajaest Avatar answered Sep 21 '22 09:09

ajaest