- The domain problem is users can export
LeadSubmission
s to CSVs and Excels. LeadSubmission::Exportable
concern is added to encapsulate the logic for exportable fields.- When rendering the export page,
BASE_FIELDS
are pre-selected. - Call
export_sections
to get all the exportable fields in the form of sections, which is mapped to the client data structure.
- When rendering the export page,
- Move
Service::Exporter::ContactExporter
toLeadSubmission::Exporter
for coheresiveness, which means code for exportingLeadSubmission
s is in the same place:app/models/lead_submission/*
.
-
-
Save goofansu/f42f0e19fc35a686c8217cfea81bdb5b to your computer and use it in GitHub Desktop.
Code changes influnced by https://world.hey.com/jorge/code-i-like-ii-fractal-journeys-b7688f93
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/contact_export.rb | |
class ContactExport < ApplicationRecord | |
after_create_commit :process_later | |
def process | |
LeadSubmission::Exporter.new(self).perform | |
end | |
private | |
def process_later | |
ContactExporterWorker.perform_async(self.id) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/workers/contact_exporter_worker.rb | |
class ContactExporterWorker | |
include Sidekiq::Worker | |
sidekiq_options queue: :export | |
def perform(contact_export_id) | |
contact_export = ContactExport.find(contact_export_id) | |
contact_export.process | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/lead_submission/exportable.rb | |
module LeadSubmission::Exportable | |
extend ActiveSupport::Concern | |
SECTION_CONTACT = 'contact' | |
SECTION_EXTRA = 'extra' | |
SECTION_CRM = 'crm' | |
CATEGORY_BASE = 'base' | |
CATEGORY_STUDENT = 'student' | |
CATEGORY_EXTRA = 'extra' | |
SECTIONS = { | |
SECTION_CONTACT => [ | |
CATEGORY_BASE, | |
CATEGORY_STUDENT, | |
], | |
SECTION_EXTRA => [ | |
CATEGORY_EXTRA, | |
], | |
SECTION_CRM => [], | |
} | |
CATEGORIES = { | |
CATEGORY_BASE => [ | |
{ id: 'first_name' }, | |
{ id: 'last_name' }, | |
{ id: 'email' }, | |
{ id: 'phone_number' }, | |
{ id: 'representative_name' }, | |
{ id: 'crm_campaign_name' }, | |
{ id: 'agent_name', condition: ->(school) { school.enable_agent_mode? } }, | |
{ id: 'agency_name', condition: ->(school) { school.enable_agent_mode? } }, | |
{ id: 'created_date' }, | |
], | |
CATEGORY_STUDENT => [ | |
{ id: 'student_first_name' }, | |
{ id: 'student_last_name' }, | |
{ id: 'student_gender_name' }, | |
{ id: 'student_birthday' }, | |
{ id: 'apply_grade_name' }, | |
{ id: 'apply_academic_year_name' }, | |
], | |
CATEGORY_EXTRA => [ | |
{ id: 'id' }, | |
{ id: 'openid', condition: ->(school) { school.has_wechat_contact_form_feature? } }, | |
{ id: 'unionid', condition: ->(school) { school.has_wechat_contact_form_feature? } }, | |
], | |
} | |
# BASE_FIELDS are pre-selected automatically. | |
BASE_FIELDS = %w( | |
first_name | |
last_name | |
) | |
class_methods do | |
def export_sections(school) | |
SECTIONS.map do |section, categories| | |
section_data(section, categories, school) | |
end | |
end | |
private | |
def section_name(section) | |
I18n.t(section, scope: 'admin.export.contacts.section') | |
end | |
def category_name(category) | |
I18n.t(category, scope: 'admin.export.contacts.category') | |
end | |
def field_name(field) | |
I18n.t(field[:id], scope: 'admin.export.contacts.contact_field') | |
end | |
def section_data(section, categories, school) | |
title = section_name(section) | |
form_pages = if section == SECTION_CRM | |
crm_form_pages(school) | |
else | |
form_pages_by_categories(categories, school) | |
end | |
{ id: section, title: title, form_pages: form_pages } | |
end | |
def form_pages_by_categories(categories, school) | |
categories.map do |category| | |
name = category_name(category) | |
fields = fields_by_category(category, school) | |
{ id: category, name: name, fields: fields } | |
end | |
end | |
def fields_by_category(category, school) | |
CATEGORIES[category].select do |field| | |
field[:condition].blank? || field[:condition].call(school) | |
end.map do |field| | |
field[:name] = field_name(field) | |
field | |
end | |
end | |
def crm_form_pages(school) | |
Service::Exporter::CRMContactField.new(school).grouped_fields | |
end | |
end | |
# Following are methods to get field values | |
def name | |
[first_name, last_name].join(' ') | |
end | |
def gender_name | |
I18n.t(gender, scope: 'gender') | |
end | |
# ... | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/lead_submission/exporter.rb | |
class LeadSubmission::Exporter | |
attr_reader :contact_export | |
delegate :school, :fields, :contact_ids, to: :contact_export | |
def initialize(contact_export) | |
@contact_export = contact_export | |
end | |
def perform | |
case contact_export.format | |
when 'csv' | |
export_csv { |file| upload_and_notify(file) } | |
when 'xlsx' | |
export_xlsx { |file| upload_and_notify(file) } | |
else | |
raise 'Unknown format!' | |
end | |
end | |
private | |
# ... | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment