event_reporter 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +7 -0
- data/README.md +37 -0
- data/bin/event_attendees.csv +1 -0
- data/bin/event_reporter +6 -0
- data/bin/help.yml +10 -0
- data/event_reporter.gemspec +26 -0
- data/lib/event_reporter/accept_any_input.rb +32 -0
- data/lib/event_reporter/attendee.rb +11 -0
- data/lib/event_reporter/cache.rb +42 -0
- data/lib/event_reporter/cleaners.rb +41 -0
- data/lib/event_reporter/csv_parser.rb +33 -0
- data/lib/event_reporter/database.rb +116 -0
- data/lib/event_reporter/parse_input.rb +9 -0
- data/lib/event_reporter/print.rb +75 -0
- data/lib/event_reporter/runner.rb +79 -0
- data/lib/event_reporter/save.rb +102 -0
- metadata +94 -0
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (C) 2013 Raphael Weiner
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Event Reporter
|
2
|
+
|
3
|
+
Allows for inspection, filtering, printing and saving of csv containing event attendees through CLI.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'event_reporter'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install event_reporter
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
For help:
|
22
|
+
$ help
|
23
|
+
|
24
|
+
Example:
|
25
|
+
$ load
|
26
|
+
$ find first_name (chris, sarah) and state (co, ky)
|
27
|
+
$ add last_name smith
|
28
|
+
$ queue print by last_name
|
29
|
+
$ queue save to results.csv
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
36
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
37
|
+
5. Create new Pull Request
|
@@ -0,0 +1 @@
|
|
1
|
+
,RegDate,first_Name,last_Name,Email_Address,HomePhone,Street,City,State,Zipcode
|
data/bin/event_reporter
ADDED
data/bin/help.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
find : find <attribute> <criteria> searches csv for specific criteria
|
2
|
+
load : load <filename> erase any loaded data and parse the specified file. If no filename is given default to event_attendees.csv
|
3
|
+
queue_count : queue count outputs how many records are in the current queue
|
4
|
+
queue_clear : queue clear empty the queue
|
5
|
+
queue_print : queue print print out a tab-delimited data table with a header row
|
6
|
+
queue_print_by : queue print by <attribute> print the data table sorted by the specified attribute like zipcode
|
7
|
+
queue_save_to : queue save to <filename.csv> exports current queue to specified filename as a CSV
|
8
|
+
add : add <attribute> <criteria> exports current queue to specified filename as a CSV
|
9
|
+
subtract : subtract <attribute> <criteria> exports current queue to specified filename as a CSV
|
10
|
+
quit : quit exits program
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = "event_reporter"
|
3
|
+
gem.version = "1.0.0"
|
4
|
+
gem.author = "Raphael Weiner"
|
5
|
+
gem.email = "raphael.weiner@gmail.com"
|
6
|
+
gem.summary = "Loads csv of event attendees and allows for searching"
|
7
|
+
gem.description = %q{
|
8
|
+
Allows for inspection, filtering, printing and saving of csv containing
|
9
|
+
list of event attendees through CLI.
|
10
|
+
}
|
11
|
+
gem.homepage = "http://github.com/raphweiner/event_reporter"
|
12
|
+
|
13
|
+
gem.files = Dir["{bin,lib}/**/*"] + %w(
|
14
|
+
README.md
|
15
|
+
LICENSE
|
16
|
+
event_reporter.gemspec
|
17
|
+
)
|
18
|
+
gem.executables = [ 'event_reporter' ]
|
19
|
+
|
20
|
+
gem.required_ruby_version = '>=1.9'
|
21
|
+
gem.has_rdoc = false
|
22
|
+
# gem.add_dependency 'CSV'
|
23
|
+
# gem.add_dependency 'yaml'
|
24
|
+
gem.add_dependency 'json'
|
25
|
+
gem.add_dependency 'nokogiri'
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module EventReporter
|
2
|
+
module AcceptAnyInput
|
3
|
+
class << self
|
4
|
+
def read_char
|
5
|
+
begin
|
6
|
+
old_state = `stty -g`
|
7
|
+
system "stty raw -echo"
|
8
|
+
c = get_char
|
9
|
+
rescue => ex
|
10
|
+
puts "#{ex.class}: #{ex.message}"
|
11
|
+
puts ex.backtrace
|
12
|
+
ensure
|
13
|
+
system "stty #{old_state}"
|
14
|
+
end
|
15
|
+
return c
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_char
|
19
|
+
c = STDIN.getc.chr
|
20
|
+
if(c=="\e")
|
21
|
+
extra_thread = Thread.new{
|
22
|
+
c = c + STDIN.getc.chr
|
23
|
+
c = c + STDIN.getc.chr
|
24
|
+
}
|
25
|
+
extra_thread.join(0.00001)
|
26
|
+
extra_thread.kill
|
27
|
+
end
|
28
|
+
c
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module EventReporter
|
2
|
+
class Cache
|
3
|
+
attr_accessor :queue
|
4
|
+
include ParseInput
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@queue = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def route_queue(input)
|
11
|
+
command, leftovers = parse_input(input)
|
12
|
+
method = "queue_#{command}"
|
13
|
+
if respond_to? method
|
14
|
+
send(method, leftovers)
|
15
|
+
else
|
16
|
+
throw(:top, "Unknown queue command '#{command}'")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def queue_count(leftovers)
|
21
|
+
puts "There are #{@queue.length} records in your queue"
|
22
|
+
end
|
23
|
+
|
24
|
+
def queue_clear(leftovers)
|
25
|
+
@queue = []
|
26
|
+
puts "Queue is cleared"
|
27
|
+
end
|
28
|
+
|
29
|
+
def queue_print(leftovers)
|
30
|
+
if leftovers[0] == 'by'
|
31
|
+
Print.queue_print_by(leftovers[1], @queue)
|
32
|
+
else
|
33
|
+
Print.queue_print(@queue)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def queue_save(leftovers)
|
38
|
+
throw(:top, "Unknown save command") if leftovers[0] != 'to'
|
39
|
+
Save.route_save_to(leftovers[1], @queue)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module EventReporter
|
2
|
+
module Cleaners
|
3
|
+
class << self
|
4
|
+
def clean_name(name)
|
5
|
+
name.to_s.chomp.downcase.capitalize
|
6
|
+
end
|
7
|
+
|
8
|
+
def clean_email(email)
|
9
|
+
email.to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
def clean_zipcode(zipcode)
|
13
|
+
zipcode.to_s.rjust(5,"0")[0..4]
|
14
|
+
end
|
15
|
+
|
16
|
+
def clean_city(city)
|
17
|
+
city.to_s.downcase.chomp.capitalize
|
18
|
+
end
|
19
|
+
|
20
|
+
def clean_state(state)
|
21
|
+
state.to_s[0..1].upcase
|
22
|
+
end
|
23
|
+
|
24
|
+
def clean_address(address)
|
25
|
+
address.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
def clean_phone_number(phone_number)
|
29
|
+
cleaned_number = phone_number.scan(/\d/).join("")
|
30
|
+
number_length = cleaned_number.length
|
31
|
+
if number_length == 10
|
32
|
+
cleaned_number
|
33
|
+
elsif number_length == 11 and phone_number[0] == '1'
|
34
|
+
phone_number[1..10]
|
35
|
+
else
|
36
|
+
'0'*10
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module EventReporter
|
2
|
+
class CSVParser
|
3
|
+
def initialize(filename)
|
4
|
+
csv_file = File.join(File.dirname(__FILE__), "../../bin/#{filename}")
|
5
|
+
throw(:top, "File not found :(") if !File.exists?(csv_file)
|
6
|
+
@contents = CSV.open(csv_file,
|
7
|
+
:headers => true,
|
8
|
+
:header_converters => :symbol)
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse
|
12
|
+
@contents.map do |line|
|
13
|
+
last_name = Cleaners::clean_name(line[:last_name])
|
14
|
+
first_name = Cleaners::clean_name(line[:first_name])
|
15
|
+
email = Cleaners::clean_email(line[:email_address])
|
16
|
+
zipcode = Cleaners::clean_zipcode(line[:zipcode])
|
17
|
+
city = Cleaners::clean_city(line[:city])
|
18
|
+
state = Cleaners::clean_state(line[:state])
|
19
|
+
address = Cleaners::clean_address(line[:street])
|
20
|
+
phone_number = Cleaners::clean_phone_number(line[:homephone])
|
21
|
+
Attendee.new(last_name,
|
22
|
+
first_name,
|
23
|
+
email,
|
24
|
+
zipcode,
|
25
|
+
city,
|
26
|
+
state,
|
27
|
+
address,
|
28
|
+
phone_number
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module EventReporter
|
2
|
+
class Database
|
3
|
+
include ParseInput
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@attendees = []
|
7
|
+
@cache = Cache.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def route_queue(input)
|
11
|
+
command, leftovers = parse_input(input)
|
12
|
+
if command == 'find'
|
13
|
+
route_find('queue', leftovers)
|
14
|
+
else
|
15
|
+
@cache.route_queue(input)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_csv(filename)
|
20
|
+
filename = filename.empty? ? "event_attendees.csv" : filename[0]
|
21
|
+
@attendees = CSVParser.new(filename).parse
|
22
|
+
|
23
|
+
puts "Loaded #{filename} (#{@attendees.length} attendees)"
|
24
|
+
end
|
25
|
+
|
26
|
+
def route_find(scope, instructions)
|
27
|
+
throw(:top, "Your database is empty (try 'load')") if @attendees.empty?
|
28
|
+
@cache.queue = if instructions.include?("and")
|
29
|
+
advanced_find(scope, instructions, "and")
|
30
|
+
elsif instructions.include?("or")
|
31
|
+
advanced_find(scope, instructions, "or")
|
32
|
+
else
|
33
|
+
initiate_search(scope, instructions)
|
34
|
+
end
|
35
|
+
|
36
|
+
@cache.queue_count("")
|
37
|
+
# remove parameter after Frank's feedback
|
38
|
+
end
|
39
|
+
|
40
|
+
def advanced_find(scope, instructions, logic)
|
41
|
+
instructions = instructions.join(" ").split(" #{logic} ")
|
42
|
+
|
43
|
+
search1 = instructions[0].split(" ")
|
44
|
+
search2 = instructions[1].split(" ")
|
45
|
+
|
46
|
+
result1 = initiate_search(scope, search1)
|
47
|
+
result2 = initiate_search(scope, search2)
|
48
|
+
|
49
|
+
if logic == "and"
|
50
|
+
return result1 & result2
|
51
|
+
elsif logic == "or"
|
52
|
+
return result1 | result2
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def initiate_search(scope, input)
|
57
|
+
throw(:top, "Incorrect find input") if input.length < 2
|
58
|
+
|
59
|
+
attribute, criterias = parse_atts_crits(input)
|
60
|
+
|
61
|
+
results = criterias.map {|criteria| search(scope, attribute, criteria)}
|
62
|
+
results.reduce(&:|)
|
63
|
+
end
|
64
|
+
|
65
|
+
def parse_atts_crits(input)
|
66
|
+
attribute = input[0]
|
67
|
+
criterias = input[1..-1].join(" ").split(",")
|
68
|
+
|
69
|
+
criterias.map! do |criteria|
|
70
|
+
criteria.gsub("(", "").gsub(")", "").strip
|
71
|
+
end
|
72
|
+
|
73
|
+
validate_input(attribute, criterias)
|
74
|
+
return attribute, criterias
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_input(attribute, criterias)
|
78
|
+
if not HEADERS.include? attribute
|
79
|
+
throw(:top, "Attribute '#{attribute}' not found")
|
80
|
+
elsif criterias.nil? || criterias.empty?
|
81
|
+
throw(:top, "Please enter a find criteria")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def search(scope, attribute, criteria)
|
86
|
+
db = scope == 'all' ? @attendees : @cache.queue
|
87
|
+
db.select do |attendee|
|
88
|
+
criteria.chomp.downcase == attendee[attribute].downcase
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def subtract(instructions)
|
93
|
+
attribute, criteria = parse_maths_input(instructions)
|
94
|
+
@cache.queue.delete_if do |attendee|
|
95
|
+
attendee[attribute].downcase == criteria.downcase
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def add(instructions)
|
100
|
+
attribute, criteria = parse_maths_input(instructions)
|
101
|
+
@cache.queue |= search('all', attribute, criteria)
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_maths_input(instructions)
|
105
|
+
if instructions.length != 2
|
106
|
+
throw(:top, "Incorrect add/subtract input")
|
107
|
+
elsif @cache.queue.empty?
|
108
|
+
throw(:top, "Can't add/subtract from an empty queue, silly!")
|
109
|
+
end
|
110
|
+
|
111
|
+
attribute, criteria = instructions[0], instructions[1]
|
112
|
+
validate_input(attribute, criteria)
|
113
|
+
return attribute, criteria
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module EventReporter
|
2
|
+
module Print
|
3
|
+
class << self
|
4
|
+
def find_column_lengths(queue)
|
5
|
+
queue.inject(new_length_hash) do |column_length, attendee|
|
6
|
+
HEADERS.each do |header|
|
7
|
+
header = header.to_sym
|
8
|
+
|
9
|
+
if attendee[header].length > column_length[header]
|
10
|
+
column_length[header] = attendee[header].length
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
column_length
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def new_length_hash
|
19
|
+
HEADERS.inject({}) do |column_length, header|
|
20
|
+
column_length[header.to_sym] = header.length
|
21
|
+
column_length
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def queue_print(queue)
|
26
|
+
if queue.empty?
|
27
|
+
puts "Nothing in queue!"
|
28
|
+
else
|
29
|
+
columns_length = find_column_lengths(queue)
|
30
|
+
print_headers(columns_length)
|
31
|
+
print_contents(columns_length, queue)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def print_headers(columns_length)
|
36
|
+
HEADERS.each do |header|
|
37
|
+
column_width = columns_length[header.to_sym]
|
38
|
+
print "#{header.gsub("_", " ").upcase.ljust(column_width)} "
|
39
|
+
end
|
40
|
+
print "\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
def print_contents(columns_length, queue)
|
44
|
+
queue.each_with_index do |attendee, i|
|
45
|
+
i+=1
|
46
|
+
HEADERS.each do |header|
|
47
|
+
column_width = columns_length[header.to_sym]
|
48
|
+
print "#{attendee[header].ljust(column_width)} "
|
49
|
+
end
|
50
|
+
print "\n"
|
51
|
+
print_status(i, queue)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def print_status(i, queue)
|
56
|
+
if i % 10 == 0 && i != 0
|
57
|
+
puts "Showing Matches #{i-9}-#{i} of #{queue.length}"
|
58
|
+
AcceptAnyInput.read_char
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def queue_print_by(attribute, queue)
|
63
|
+
if attribute.nil? || !queue.first.respond_to?(attribute)
|
64
|
+
throw(:top, "Attribute not found to print by...")
|
65
|
+
end
|
66
|
+
|
67
|
+
queue.sort! do |attendee1, attendee2|
|
68
|
+
attendee1[attribute] <=> attendee2[attribute]
|
69
|
+
end
|
70
|
+
|
71
|
+
queue_print(queue)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'event_reporter/parse_input'
|
2
|
+
require 'event_reporter/database'
|
3
|
+
require 'event_reporter/print'
|
4
|
+
require 'event_reporter/save'
|
5
|
+
require 'event_reporter/csv_parser'
|
6
|
+
require 'event_reporter/cleaners'
|
7
|
+
require 'event_reporter/attendee'
|
8
|
+
require 'event_reporter/cache'
|
9
|
+
require 'event_reporter/accept_any_input'
|
10
|
+
|
11
|
+
require 'CSV'
|
12
|
+
require 'yaml'
|
13
|
+
require 'json'
|
14
|
+
require 'nokogiri'
|
15
|
+
|
16
|
+
module EventReporter
|
17
|
+
|
18
|
+
HEADERS = ["last_name", "first_name", "email",
|
19
|
+
"zipcode", "city", "state", "address", "phone_number"]
|
20
|
+
|
21
|
+
class Runner
|
22
|
+
include ParseInput
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
puts "EventManager initializing..."
|
26
|
+
@database = Database.new
|
27
|
+
run_loop
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def run_loop
|
33
|
+
loop do
|
34
|
+
message = catch(:top) do
|
35
|
+
route_input(user_input)
|
36
|
+
end
|
37
|
+
puts message unless message.nil? || !message.kind_of?(String)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def user_input
|
42
|
+
print "> "
|
43
|
+
return gets.chomp.downcase.split(" ")
|
44
|
+
end
|
45
|
+
|
46
|
+
def route_input(input)
|
47
|
+
command, leftovers = parse_input(input)
|
48
|
+
case command
|
49
|
+
when 'quit' then puts "Ciao, bella!\n\n"; exit
|
50
|
+
when 'help' then route_help(leftovers)
|
51
|
+
when 'load' then @database.load_csv(leftovers)
|
52
|
+
when 'find' then @database.route_find('all', leftovers)
|
53
|
+
when 'queue' then @database.route_queue(leftovers)
|
54
|
+
when 'subtract' then @database.subtract(leftovers)
|
55
|
+
when 'add' then @database.add(leftovers)
|
56
|
+
else
|
57
|
+
throw(:top, "Unknown input. Try 'help'")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def route_help(input)
|
62
|
+
help_contents = load_help_text
|
63
|
+
if input.empty?
|
64
|
+
help_contents.each { |key, value| puts value }
|
65
|
+
else
|
66
|
+
type = input.join("_")
|
67
|
+
if help_contents.include? type
|
68
|
+
puts help_contents[type]
|
69
|
+
else
|
70
|
+
throw(:top, "Unknown help command '#{input.join(" ")}'")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def load_help_text
|
76
|
+
YAML.load_file('bin/help.yml')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module EventReporter
|
2
|
+
module Save
|
3
|
+
class << self
|
4
|
+
def route_save_to(filename, queue)
|
5
|
+
throw(:top, "Please enter a filename to save to") if filename.nil?
|
6
|
+
|
7
|
+
extension = filename.split(".")[1]
|
8
|
+
method = "save_to_#{extension}"
|
9
|
+
|
10
|
+
if respond_to? method
|
11
|
+
send(method, filename, queue)
|
12
|
+
else
|
13
|
+
throw(:top, "Extension not valid! (try .csv, .xml, .txt, .json)")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_to_csv(filename, queue)
|
18
|
+
CSV.open("bin/#{filename}", "w") do |csv|
|
19
|
+
csv << HEADERS.map do |header|
|
20
|
+
header.downcase == 'phone_number' ? 'HomePhone' : header
|
21
|
+
end
|
22
|
+
queue.each do |attendee|
|
23
|
+
csv << [attendee.last_name,
|
24
|
+
attendee.first_name,
|
25
|
+
attendee.email,
|
26
|
+
attendee.zipcode,
|
27
|
+
attendee.city,
|
28
|
+
attendee.state,
|
29
|
+
attendee.address,
|
30
|
+
attendee.phone_number]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
success(filename)
|
34
|
+
end
|
35
|
+
|
36
|
+
def save_to_txt(filename, queue)
|
37
|
+
columns_length = Print.find_column_lengths(queue)
|
38
|
+
File.open("bin/#{filename}", "w") do |txt|
|
39
|
+
save_to_txt_headers(txt, columns_length)
|
40
|
+
save_to_txt_contents(txt, columns_length, queue)
|
41
|
+
end
|
42
|
+
success(filename)
|
43
|
+
end
|
44
|
+
|
45
|
+
def save_to_txt_headers(txt, columns_length)
|
46
|
+
HEADERS.each do |header|
|
47
|
+
column_width = columns_length[header.to_sym]
|
48
|
+
txt.print "#{header.gsub("_", " ").upcase.ljust(column_width)} "
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def save_to_txt_contents(txt, columns_length, queue)
|
53
|
+
queue.each_with_index do |attendee, i|
|
54
|
+
HEADERS.each do |header|
|
55
|
+
column_width = columns_length[header.to_sym]
|
56
|
+
txt.print "#{attendee[header].ljust(column_width)} "
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def save_to_json(filename, queue)
|
62
|
+
File.open("bin/#{filename}", "w") do |json|
|
63
|
+
json.puts queue.to_json
|
64
|
+
end
|
65
|
+
success(filename)
|
66
|
+
end
|
67
|
+
|
68
|
+
def save_to_xml(filename, queue)
|
69
|
+
queue_xml = Nokogiri::XML::Builder.new do |xml|
|
70
|
+
xml.root {
|
71
|
+
xml.event_attendees {
|
72
|
+
build_attendees_xml(xml, queue)
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
File.open("bin/#{filename}", "w") do |xml|
|
77
|
+
xml.puts queue_xml.to_xml
|
78
|
+
end
|
79
|
+
success(filename)
|
80
|
+
end
|
81
|
+
|
82
|
+
def success(filename)
|
83
|
+
puts "Saved to #{filename}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_attendees_xml(xml, queue)
|
87
|
+
queue.each do |attendee|
|
88
|
+
xml.attendee {
|
89
|
+
xml.first_name attendee.first_name
|
90
|
+
xml.last_name attendee.last_name
|
91
|
+
xml.email attendee.email
|
92
|
+
xml.phone_number attendee.phone_number
|
93
|
+
xml.address attendee.address
|
94
|
+
xml.city attendee.city
|
95
|
+
xml.state attendee.state
|
96
|
+
xml.zipcode attendee.zipcode
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: event_reporter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Raphael Weiner
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: nokogiri
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: ! "\n Allows for inspection, filtering, printing and saving of csv
|
47
|
+
containing\n list of event attendees through CLI.\n "
|
48
|
+
email: raphael.weiner@gmail.com
|
49
|
+
executables:
|
50
|
+
- event_reporter
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- bin/event_attendees.csv
|
55
|
+
- bin/event_reporter
|
56
|
+
- bin/help.yml
|
57
|
+
- lib/event_reporter/accept_any_input.rb
|
58
|
+
- lib/event_reporter/attendee.rb
|
59
|
+
- lib/event_reporter/cache.rb
|
60
|
+
- lib/event_reporter/cleaners.rb
|
61
|
+
- lib/event_reporter/csv_parser.rb
|
62
|
+
- lib/event_reporter/database.rb
|
63
|
+
- lib/event_reporter/parse_input.rb
|
64
|
+
- lib/event_reporter/print.rb
|
65
|
+
- lib/event_reporter/runner.rb
|
66
|
+
- lib/event_reporter/save.rb
|
67
|
+
- README.md
|
68
|
+
- LICENSE
|
69
|
+
- event_reporter.gemspec
|
70
|
+
homepage: http://github.com/raphweiner/event_reporter
|
71
|
+
licenses: []
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.9'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.8.24
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: Loads csv of event attendees and allows for searching
|
94
|
+
test_files: []
|