我构建了一个Event Manager类,它对CSV文件执行解析操作,并使用erb生成html字母。它是快速启动实验室tutorial
的一部分该程序运行正常,但如果没有先前的方法干扰后面的方法,我无法在对象上调用多个方法。结果,我选择创建多个对象来调用实例方法,这似乎是一个笨重的不优雅的解决方案。有没有更好的方法来做到这一点,我可以创建一个新对象并在其上调用方法?
像这样:
eventmg = EventManager.new("event_attendees.csv")
eventmg.print_valid_phone_numbers
eventmg_2 = EventManager.new("event_attendees.csv")
eventmg_2.print_zipcodes
eventmg_3 = EventManager.new("event_attendees.csv")
eventmg_3.time_targeter
eventmg_4 = EventManager.new("event_attendees.csv")
eventmg_4.day_of_week
eventmg_5 = EventManager.new("event_attendees.csv")
eventmg_5.create_thank_you_letters
完整的代码如下
require 'csv'
require 'sunlight/congress'
require 'erb'
class EventManager
INVALID_PHONE_NUMBER = "0000000000"
Sunlight::Congress.api_key = "e179a6973728c4dd3fb1204283aaccb5"
def initialize(file_name, list_selections = [])
puts "EventManager Initialized."
@file = CSV.open(file_name, {:headers => true,
:header_converters => :symbol} )
@list_selections = list_selections
end
def clean_zipcode(zipcode)
zipcode.to_s.rjust(5,"0")[0..4]
end
def print_zipcodes
puts "Valid Participant Zipcodes"
@file.each do |line|
zipcode = clean_zipcode(line[:zipcode])
puts zipcode
end
end
def clean_phone(phone_number)
converted = phone_number.scan(/\d/).join('').split('')
if converted.count == 10
phone_number
elsif phone_number.to_s.length < 10
INVALID_PHONE_NUMBER
elsif phone_number.to_s.length == 11 && converted[0] == 1
phone_number.shift
phone_number.join('')
elsif phone_number.to_s.length == 11 && converted[0] != 1
INVALID_PHONE_NUMBER
else
phone_number.to_s.length > 11
INVALID_PHONE_NUMBER
end
end
def print_valid_phone_numbers
puts "Valid Participant Phone Numbers"
@file.each do |line|
clean_number = clean_phone(line[:homephone])
puts clean_number
end
end
def time_targeter
busy_times = Array.new(24) {0}
@file.each do |line|
registration = line[:regdate]
prepped_time = DateTime.strptime(registration, "%m/%d/%Y %H:%M")
prepped_time = prepped_time.hour.to_i
# inserts filtered hour into the array 'list_selections'
@list_selections << prepped_time
end
# tallies number of registrations for each hour
i = 0
while i < @list_selections.count
busy_times[@list_selections[i]] += 1
i+=1
end
# delivers a result showing the hour and the number of registrations
puts "Number of Registered Participants by Hour:"
busy_times.each_with_index {|counter, hours| puts "#{hours}\t#{counter}"}
end
def day_of_week
busy_day = Array.new(7) {0}
d_of_w = ["Monday:", "Tuesday:", "Wednesday:", "Thursday:", "Friday:", "Saturday:", "Sunday:"]
@file.each do |line|
registration = line[:regdate]
# you have to reformat date because of parser format
prepped_date = Date.strptime(registration, "%m/%d/%y")
prepped_date = prepped_date.wday
# adds filtered day of week into array 'list selections'
@list_selections << prepped_date
end
i = 0
while i < @list_selections.count
# i is minus one since days of week begin at '1' and arrays begin at '0'
busy_day[@list_selections[i-1]] += 1
i+=1
end
#busy_day.each_with_index {|counter, day| puts "#{day}\t#{counter}"}
prepared = d_of_w.zip(busy_day)
puts "Number of Registered Participants by Day of Week"
prepared.each{|date| puts date.join(" ")}
end
def legislators_by_zipcode(zipcode)
Sunlight::Congress::Legislator.by_zipcode(zipcode)
end
def save_thank_you_letters(id,form_letter)
Dir.mkdir("output") unless Dir.exists?("output")
filename = "output/thanks_#{id}.html"
File.open(filename,'w') do |file|
file.puts form_letter
end
end
def create_thank_you_letters
puts "Thank You Letters Available in Output Folder"
template_letter = File.read "form_letter.erb"
erb_template = ERB.new template_letter
@file.each do |line|
id = line[0]
name = line[:first_name]
zipcode = clean_zipcode(line[:zipcode])
legislators = legislators_by_zipcode(zipcode)
form_letter = erb_template.result(binding)
save_thank_you_letters(id,form_letter)
end
end
end
答案 0 :(得分:1)
您遇到此问题的原因是,当您将each
应用于CSV.open
的结果时,您每次都会移动文件指针。当您使用某种方法到达文件末尾时,其他任何人都无法阅读。
另一种方法是在初始化时使用readlines
将文件内容读入实例变量。您将获得一组数组,您可以使用each
轻松操作。
答案 1 :(得分:0)
“有没有更好的方法来实现这一点,我可以创建一个新对象并在其上调用方法?”
可能。如果您的方法相互干扰,则意味着您正在更改管理器中的状态,而不是处理局部变量。
有时,这是正确的做法(例如Array#<<
);有时候没有(例如Fixnum#+
)...看到你的方法名称,它可能不是。
将违法者钉死并相应调整代码。 (我只扫描了你的代码,但对实例变量的那些Array#<<
调用,特别是看起来很可疑。)