Reputation: 457
I'm trying to DRY up my code and wondering if many people have experience with CSV's and ruby.
My code is below. It works just... Its awful.
I'm wondering if anyone has any ideas on how I could do the following:
1 - How could I use a loop rather than explicit 1..10 that I've done. I did try a few ways but couldn't get them to work with CSV. 2 - Is there a nicer way to do headers in CSV? 3 - Any other ideas on how to make CSV code nicer?
I initially went with this
(1..10).each do |number|
end
However the csv system didn't like that one! It was thinking my end statements were incorrect however, I don't think this was the case.
Here's my code. If you have any bright ideas you're awesome! Yes I know it's awful, just wondering how I could do it better!
require 'csv'
class CampagignsCsv
class << self
HEADERS = [
'Job Title',
'Business Name',
'Business Contact Name',
'Location',
'Job Status',
'Created date',
'Last Modified date',
'# Positions',
'Description',
'Std/Prem',
'Referral code (To discuss)',
'Coupon code (To discuss)',
'Question1',
'Knockout?1',
'Correct Answer1',
'Question2',
'Knockout?2',
'Correct Answer2',
'Question3',
'Knockout?3',
'Correct Answer3',
'Question4',
'Knockout?4',
'Correct Answer4',
'Question5',
'Knockout?5',
'Correct Answer5',
'Question6',
'Knockout?6',
'Correct Answer6',
'Question7',
'Knockout?7',
'Correct Answer7',
'Question8',
'Knockout?8',
'Correct Answer8',
'Question9',
'Knockout?9',
'Correct Answer9',
'Question10',
'Knockout?10',
'Correct Answer10'
].freeze
def report
puts 'campaigns_report.csv created in reporting_output folder'
CSV.open("reporting_output/campagins_report.csv", "wb") do |csv|
csv << HEADERS
Paddl::Models::Job.all.each do |job|
csv << [
job.title,
job.employer.business_name,
job.employer.profile.full_name,
job.address,
job.status,
job.created_at,
job.updated_at,
job.num_of_positions,
job.description,
job.employer.account_type,
'null',
'null',
job.job_questions.map { |item| item[:question] }[1],
job.job_questions.map { |item| item[:knockout] }[1],
job.job_questions.map { |item| item[:correct_answer] }[1],
job.job_questions.map { |item| item[:question] }[2],
job.job_questions.map { |item| item[:knockout] }[2],
job.job_questions.map { |item| item[:correct_answer] }[2],
job.job_questions.map { |item| item[:question] }[3],
job.job_questions.map { |item| item[:knockout] }[3],
job.job_questions.map { |item| item[:correct_answer] }[3],
job.job_questions.map { |item| item[:question] }[4],
job.job_questions.map { |item| item[:knockout] }[4],
job.job_questions.map { |item| item[:correct_answer] }[4],
job.job_questions.map { |item| item[:question] }[5],
job.job_questions.map { |item| item[:knockout] }[5],
job.job_questions.map { |item| item[:correct_answer] }[5],
job.job_questions.map { |item| item[:question] }[6],
job.job_questions.map { |item| item[:knockout] }[6],
job.job_questions.map { |item| item[:correct_answer] }[6],
job.job_questions.map { |item| item[:question] }[7],
job.job_questions.map { |item| item[:knockout] }[7],
job.job_questions.map { |item| item[:correct_answer] }[7],
job.job_questions.map { |item| item[:question] }[8],
job.job_questions.map { |item| item[:knockout] }[8],
job.job_questions.map { |item| item[:correct_answer] }[8],
job.job_questions.map { |item| item[:question] }[9],
job.job_questions.map { |item| item[:knockout] }[9],
job.job_questions.map { |item| item[:correct_answer] }[9],
job.job_questions.map { |item| item[:question] }[10],
job.job_questions.map { |item| item[:knockout] }[10],
job.job_questions.map { |item| item[:correct_answer] }[10]
]
end
end
end
end
end
Upvotes: 0
Views: 79
Reputation: 211600
Here's an approach that organizes things better, plus cuts way down on duplication:
require 'csv'
class CampagignsCsv
HEADERS = [
'Job Title',
'Business Name',
'Business Contact Name',
'Location',
'Job Status',
'Created date',
'Last Modified date',
'# Positions',
'Description',
'Std/Prem',
'Referral code (To discuss)',
'Coupon code (To discuss)'
] + (1..10).flat_map do |n|
"Question#{n}",
"Knockout?#{n}",
"Correct Answer#{n}",
end
SECTIONS = [
:question,
:knockout,
:correct_answer
]
def self.report
puts 'campaigns_report.csv created in reporting_output folder'
CSV.open("reporting_output/campagins_report.csv", "wb") do |csv|
csv << HEADERS
Paddl::Models::Job.all.each do |job|
csv << [
job.title,
job.employer.business_name,
job.employer.profile.full_name,
job.address,
job.status,
job.created_at,
job.updated_at,
job.num_of_positions,
job.description,
job.employer.account_type,
'null',
'null'
] + SECTIONS.flat_map do |section|
(1..10).map do |n|
job.job_questions[section][n]
end
end
end
end
end
end
Normally you declare constants at the very top level of your class, not inside a class << self
block. That's also not necessary since declaring a methods as self.x
automatically makes it a class method.
Using flat_map
can help convert array-of-array type results to a flat array, very handy in this case.
Upvotes: 1
Reputation: 1161
How's this?
...
job.employer.account_type,
'null',
'null',
*1.upto(10).flat_map {|i|
jq = job.job_questions[i]
[jq[:question], jq[:knockout], jq[:correct_answer]]
}
...
Upvotes: 1